ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject cvs commit: jakarta-ant/proposal/sandbox/embed ProjectHelper.java ProjectHelperImpl.java
Date Tue, 05 Mar 2002 05:50:09 GMT
costin      02/03/04 21:50:09

  Modified:    proposal/sandbox/embed ProjectHelper.java
                        ProjectHelperImpl.java
  Log:
  Updated ProjectHelper.
  
  I used the current sources ( with the new comments), and reimplemented
  all changes.
  
  The current version doesn't have anything related with the other proposals,
  and is functionally equivalent with the old ProjectHelper - except it's
  cleaner ( all private and SAX code moved to the helper imple ).
  
  I created a new package, o.a.t.ant.helper to keep the core cleaner -
  other helpers may be commited.
  
  The SAX2 based helper is easy to write, but depends on few improvements
  on RoleFactory ( createTask with namespace support, etc ).
  I'm working on a new implementation of the task factory, with support
  for data types and other roles - but that's another story.
  
  Revision  Changes    Path
  1.2       +145 -78   jakarta-ant/proposal/sandbox/embed/ProjectHelper.java
  
  Index: ProjectHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/sandbox/embed/ProjectHelper.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProjectHelper.java	22 Feb 2002 23:28:31 -0000	1.1
  +++ ProjectHelper.java	5 Mar 2002 05:50:09 -0000	1.2
  @@ -69,7 +69,7 @@
   import java.lang.reflect.Method;
   
   import org.xml.sax.AttributeList;
  -
  +import org.apache.tools.ant.helper.ProjectHelperImpl;
   
   /**
    * Configures a Project (complete with Targets and Tasks) based on
  @@ -90,48 +90,42 @@
    *
    * @author duncan@x180.com
    */
  -public /*abstract*/ class ProjectHelper {
  +public class ProjectHelper {
   
       /**
  -     * Configures the Project with the contents of the specified XML file.
  -     * ( should it be deprecated ? Using getProjectHelper(), parse()
  -     * is cleaner )
  +     * Configures the project with the contents of the specified XML file.
  +     * 
  +     * @param project The project to configure. Must not be <code>null</code>.
  +     * @param buildFile An XML file giving the project's configuration.
  +     *                  Must not be <code>null</code>.
  +     * 
  +     * @exception BuildException if the configuration is invalid or cannot 
  +     *                           be read
        */
  -    public static void configureProject(Project project, File buildFile)
  -        throws BuildException
  -    {
  +    public static void configureProject(Project project, File buildFile) throws BuildException {
           ProjectHelper helper=ProjectHelper.getProjectHelper();
           helper.parse(project, buildFile);
       }
   
       public ProjectHelper() {
       }
  -    
  -    /**
  -     * Constructs a new Ant parser for the specified XML file.
  -     * @deprecated Use the plugin mechanism instead.
  -     */
  -    private ProjectHelper(Project project, File buildFile) {
  -        //  this.project = project;
  -        //  this.buildFile = new File(buildFile.getAbsolutePath());
  -        //  buildFileParent = new File(this.buildFile.getParent());
  -    }
   
  -    public Project createProject(ClassLoader coreLoader) {
  -        return new Project();
  -    }
  -    
       /**
  -     * Process an input source for the project.
  +     * Parses the project file, configuring the project as it goes.
        *
  -     * All processors must support at least File sources. It is usefull to also support
  -     * InputSource - this allows the input to come from a non-filesystem source
  -     * (like input stream of a POST, or a soap body ).
  -     */
  -    public /*abstract*/ void parse(Project project, Object source)
  -        throws BuildException
  -    {
  -        throw new BuildException("You must use a real ProjectHelper implementation"); 
  +     * @param project The project for the resulting ProjectHelper to configure. 
  +     *                Must not be <code>null</code>.
  +     * @param source The source for XML configuration. A helper must support
  +     *               at least File, for backward compatibility. Helpers may
  +     *               support URL, InputStream, etc or specialized types.
  +     *
  +     * @since Ant1.5
  +     * @exception BuildException if the configuration is invalid or cannot 
  +     *                           be read
  +     */
  +    public void parse(Project project, Object source) throws BuildException {
  +        throw new BuildException("ProjectHelper.parse() must be implemented in a helper plugin "
  +                                 + this.getClass().getName());
       }
   
       /* -------------------- Helper discovery -------------------- */
  @@ -142,21 +136,22 @@
           "/META-INF/services/org.apache.tools.ant.ProjectHelper";
   
       
  -    /** Discover a project helper instance.
  +    /** Discover a project helper instance. Uses the same patterns
  +     *  as JAXP, commons-logging, etc: a system property, a JDK1.3
  +     *  service discovery, default.
        */
       public static ProjectHelper getProjectHelper()
           throws BuildException
       {
           // Identify the class loader we will be using. Ant may be
           // in a webapp or embeded in a different app
  -        ClassLoader classLoader = getContextClassLoader();
           ProjectHelper helper=null;
           
           // First, try the system property
           try {
               String helperClass = System.getProperty(HELPER_PROPERTY);
               if (helperClass != null) {
  -                helper = newHelper(helperClass, classLoader);
  +                helper = newHelper(helperClass);
               }
           } catch (SecurityException e) {
               // It's ok, we'll try next option
  @@ -167,13 +162,15 @@
           // automatically if in CLASSPATH, with the right META-INF/services.
           if( helper==null ) {
               try {
  +                ClassLoader classLoader=getContextClassLoader();
                   InputStream is=null;
  -                if (classLoader == null) {
  -                    is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
  -                } else {
  +                if (classLoader != null) {
                       is=classLoader.getResourceAsStream( SERVICE_ID );
                   }
  -
  +                if( is==null ) {
  +                    is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
  +                }
  +                
                   if( is != null ) {
                       // This code is needed by EBCDIC and other strange systems.
                       // It's a fix for bugs reported in xerces
  @@ -190,7 +187,7 @@
                       if (helperClassName != null &&
                           ! "".equals(helperClassName)) {
                           
  -                        helper= newHelper( helperClassName, classLoader );
  +                        helper= newHelper( helperClassName );
                       }
                   }
               } catch( Exception ex ) {
  @@ -202,17 +199,25 @@
           return new ProjectHelperImpl();
       }
   
  -    private static ProjectHelper newHelper(String helperClass,
  -                                           ClassLoader classLoader)
  +    /** Create a new helper. It'll first try the thread class loader,
  +     *  then Class.forName() will load from the same loader that
  +     *  loaded this class.
  +     */
  +    private static ProjectHelper newHelper(String helperClass)
           throws BuildException
       {
  -
  +        ClassLoader classLoader = getContextClassLoader();
           try {
               Class clazz = null;
  -            if (classLoader == null) {
  +            if (classLoader != null) {
  +                try {
  +                    clazz = classLoader.loadClass(helperClass);
  +                } catch( ClassNotFoundException ex ) {
  +                    // try next method
  +                }
  +            }
  +            if( clazz==null ) {
                   clazz = Class.forName(helperClass);
  -            } else {
  -                clazz = classLoader.loadClass(helperClass);
               }
               return ((ProjectHelper) clazz.newInstance());
           } catch (Exception e) {
  @@ -220,7 +225,9 @@
           }
       }
   
  -    /** 
  +    /**
  +     *  JDK1.1 compatible access to the context class loader.
  +     *  Cut&paste from Jaxp.
        */
       public static ClassLoader getContextClassLoader()
           throws BuildException
  @@ -251,42 +258,42 @@
           return (classLoader);
       }
   
  -    
  -    /* -------------------- Common utilities and wrappers -------------------- */
  +    // -------------------- Static utils, used by most helpers -------------------- 
   
  -    /** Configure a java object using ant's rules.
  +    /**
  +     * Configures an object using an introspection handler.
  +     * 
  +     * @param target The target object to be configured.
  +     *               Must not be <code>null</code>.
  +     * @param attrs  A list of attributes to configure within the target.
  +     *               Must not be <code>null</code>.
  +     * @param project The project containing the target. 
  +     *                Must not be <code>null</code>.
  +     * 
  +     * @exception BuildException if any of the attributes can't be handled by
  +     *                           the target
        */
       public static void configure(Object target, AttributeList attrs, 
                                    Project project) throws BuildException {
  -        TaskAdapter adapter=null;
           if( target instanceof TaskAdapter ) {
  -            adapter=(TaskAdapter)target;
  -            target=adapter.getProxy();
  +            target=((TaskAdapter)target).getProxy();
           }
   
           IntrospectionHelper ih = 
               IntrospectionHelper.getHelper(target.getClass());
  -        if( adapter != null )
  -            adapter.setIntrospectionHelper( ih );
   
  -        // XXX What's that ?
           project.addBuildListener(ih);
   
           for (int i = 0; i < attrs.getLength(); i++) {
               // reflect these into the target
               String value=replaceProperties(project, attrs.getValue(i), 
                                              project.getProperties() );
  -            String name=attrs.getName(i).toLowerCase(Locale.US);
               try {
  -                if (adapter!=null ) {
  -                    adapter.setAttribute( name, value );
  -                } else {
  -                    ih.setAttribute(project, target, 
  -                                    name, value);
  -                }
  +                ih.setAttribute(project, target, 
  +                                attrs.getName(i).toLowerCase(Locale.US), value);
  +
               } catch (BuildException be) {
                   // id attribute must be set externally
  -                // XXX Shuldn't it be 'name' ( i.e. lower-cased ) ?
                   if (!attrs.getName(i).equals("id")) {
                       throw be;
                   }
  @@ -296,14 +303,35 @@
   
       /**
        * Adds the content of #PCDATA sections to an element.
  +     * 
  +     * @param project The project containing the target. 
  +     *                Must not be <code>null</code>.
  +     * @param target  The target object to be configured.
  +     *                Must not be <code>null</code>.
  +     * @param buf A character array of the text within the element.
  +     *            Will not be <code>null</code>.
  +     * @param start The start element in the array.
  +     * @param count The number of characters to read from the array.
  +     * 
  +     * @exception BuildException if the target object doesn't accept text
        */
  -    public static void addText(Project project, Object target, char[] buf, int start, int end)
  +    public static void addText(Project project, Object target, char[] buf, int start, int count)
           throws BuildException {
  -        addText(project, target, new String(buf, start, end));
  +        addText(project, target, new String(buf, start, count));
       }
   
       /**
        * Adds the content of #PCDATA sections to an element.
  +     * 
  +     * @param project The project containing the target. 
  +     *                Must not be <code>null</code>.
  +     * @param target  The target object to be configured.
  +     *                Must not be <code>null</code>.
  +     * @param text    Text to add to the target.
  +     *                May be <code>null</code>, in which case this
  +     *                method call is a no-op.
  +     * 
  +     * @exception BuildException if the target object doesn't accept text
        */
       public static void addText(Project project, Object target, String text)
           throws BuildException {
  @@ -320,7 +348,17 @@
       }
   
       /**
  -     * Stores a configured child element into its parent object 
  +     * Stores a configured child element within its parent object.
  +     * 
  +     * @param project Project containing the objects.
  +     *                May be <code>null</code>.
  +     * @param parent  Parent object to add child to.
  +     *                Must not be <code>null</code>.
  +     * @param child   Child object to store in parent.
  +     *                Should not be <code>null</code>.
  +     * @param tag     Name of element which generated the child.
  +     *                May be <code>null</code>, in which case
  +     *                the child is not stored.
        */
       public static void storeChild(Project project, Object parent, Object child, String tag) {
           IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass());
  @@ -328,10 +366,18 @@
       }
   
       /**
  -     * Replace ${} style constructions in the given value with the string value of
  -     * the corresponding data types.
  +     * Replaces <code>${xxx}</code> style constructions in the given value with 
  +     * the string value of the corresponding properties.
  +     *
  +     * @param value The string to be scanned for property references.
  +     *              May be <code>null</code>.
        *
  -     * @param value the string to be scanned for property references.
  +     * @exception BuildException if the string contains an opening 
  +     *                           <code>${</code> without a closing 
  +     *                           <code>}</code>
  +     * @return the original string with the properties replaced, or
  +     *         <code>null</code> if the original string is <code>null</code>.
  +     * 
        * @since 1.5
        */
        public static String replaceProperties(Project project, String value)
  @@ -340,10 +386,22 @@
        }
   
       /**
  -     * Replace ${} style constructions in the given value with the string value of
  -     * the corresponding data types.
  +     * Replaces <code>${xxx}</code> style constructions in the given value 
  +     * with the string value of the corresponding data types.
        *
  -     * @param value the string to be scanned for property references.
  +     * @param project The container project. This is used solely for
  +     *                logging purposes. Must not be <code>null</code>.
  +     * @param value The string to be scanned for property references.
  +     *              May be <code>null</code>, in which case this
  +     *              method returns immediately with no effect.
  +     * @param keys  Mapping (String to String) of property names to their 
  +     *              values. Must not be <code>null</code>.
  +     * 
  +     * @exception BuildException if the string contains an opening 
  +     *                           <code>${</code> without a closing 
  +     *                           <code>}</code>
  +     * @return the original string with the properties replaced, or
  +     *         <code>null</code> if the original string is <code>null</code>.
        */
        public static String replaceProperties(Project project, String value, Hashtable keys)
               throws BuildException {
  @@ -375,11 +433,21 @@
       }
   
       /**
  -     * This method will parse a string containing ${value} style 
  -     * property values into two lists. The first list is a collection
  -     * of text fragments, while the other is a set of string property names
  -     * null entries in the first list indicate a property reference from the
  -     * second list.
  +     * Parses a string containing <code>${xxx}</code> style property
  +     * references into two lists. The first list is a collection
  +     * of text fragments, while the other is a set of string property names.
  +     * <code>null</code> entries in the first list indicate a property 
  +     * reference from the second list.
  +     * 
  +     * @param value     Text to parse. Must not be <code>null</code>.
  +     * @param fragments List to add text fragments to. 
  +     *                  Must not be <code>null</code>.
  +     * @param propertyRefs List to add property names to.
  +     *                     Must not be <code>null</code>.
  +     * 
  +     * @exception BuildException if the string contains an opening 
  +     *                           <code>${</code> without a closing 
  +     *                           <code>}</code>
        */
       public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs) 
           throws BuildException {
  @@ -414,5 +482,4 @@
               fragments.addElement(value.substring(prev));
           }
       }
  -
   }
  
  
  
  1.2       +587 -187  jakarta-ant/proposal/sandbox/embed/ProjectHelperImpl.java
  
  Index: ProjectHelperImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/sandbox/embed/ProjectHelperImpl.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProjectHelperImpl.java	22 Feb 2002 23:28:31 -0000	1.1
  +++ ProjectHelperImpl.java	5 Mar 2002 05:50:09 -0000	1.2
  @@ -52,7 +52,9 @@
    * <http://www.apache.org/>.
    */
   
  -package org.apache.tools.ant;
  +package org.apache.tools.ant.helper;
  +
  +import org.apache.tools.ant.*;
   
   import java.io.File;
   import java.io.FileInputStream;
  @@ -75,68 +77,57 @@
   import javax.xml.parsers.SAXParser;
   import javax.xml.parsers.ParserConfigurationException;
   
  -// Note: Use of local classes can create problems with various compilers
  -// like gcc or even jikes. In addition it makes the code harder to read
  -// for many beginners ( at least for me - Costin ).
  -// I changed the code to avoid the tricks that the compiler does, now
  -// jikes works ( for me ). Note that declaring the classes 'private'
  -// is probably overriden by the compiler - a feature of the internal class impl.
  -
   /**
  - * "Original" implementation of the project helper. Or at least
  - * what is present in ant1.4.
  + * Original helper.
    *
    * @author duncan@x180.com
    */
   public class ProjectHelperImpl extends ProjectHelper {
  +
  +    /** 
  +     * Parser factory to use to create parsers.
  +     * @see #getParserFactory
  +     */
       private static SAXParserFactory parserFactory = null;
   
  -    protected Project project;
  -    protected Object source;
  -    protected File buildFile;
  -    protected File buildFileParent;
  +    /**
  +     * SAX 1 style parser used to parse the given file. This may 
  +     * in fact be a SAX 2 XMLReader wrapped in an XMLReaderAdapter.
  +     */
       private org.xml.sax.Parser parser;
  +    
  +    /** The project to configure. */
  +    private Project project;
  +    /** The configuration file to parse. */
  +    private File buildFile;
  +    /** 
  +     * Parent directory of the build file. Used for resolving entities
  +     * and setting the project's base directory.
  +     */
  +    private File buildFileParent;
  +    /** 
  +     * Locator for the configuration file parser. 
  +     * Used for giving locations of errors etc.
  +     */
       private Locator locator;
   
  -    /** Return a handler for project. This can be used by xml helpers to fallback to
  -        the original behavior ( non-namespace aware ).
  -        When the <project> callback is received, if no namespaces are used ( or no
  -        new attributes, etc ) then the easiest way to achieve backward compatibility
  -        is to use the original.
  -
  -        A helper needs to call this method, which will switch the HandlerBase in
  -        the SAX parser and return it to the original on </project>
  -
  -        @experimental This is likely to change
  -    */
  -    public HandlerBase defaultProjectHandler( Project project,
  -                                              org.xml.sax.Parser parser,
  -                                              String tag, AttributeList attrs,
  -                                              DocumentHandler parent )
  -        throws SAXParseException
  -    {
  -        this.project=project;
  -        this.parser=parser;
  -        ProjectHandler h=new ProjectHandler(this, parent);
  -        h.init( tag, attrs );
  -        return h;
  -    }
  -
       /**
  -     * Parses the project file.
  +     * Parses the project file, configuring the project as it goes.
  +     * 
  +     * @exception BuildException if the configuration is invalid or cannot 
  +     *                           be read
        */
       public void parse(Project project, Object source) throws BuildException {
           if( ! (source instanceof File) )
  -            throw new BuildException( "Only File source is supported by the default helper");
  -        
  +            throw new BuildException( "Only File source supported by default plugin" );
           File buildFile=(File)source;
  +        FileInputStream inputStream = null;
  +        InputSource inputSource = null;
  +
           this.project = project;
           this.buildFile = new File(buildFile.getAbsolutePath());
           buildFileParent = new File(this.buildFile.getParent());
           
  -        FileInputStream inputStream = null;
  -        InputSource inputSource = null;
  -        
           try {
               SAXParser saxParser = getParserFactory().newSAXParser();
               try {
  @@ -154,8 +145,7 @@
               inputSource = new InputSource(inputStream);
               inputSource.setSystemId(uri);
               project.log("parsing buildfile " + buildFile + " with URI = " + uri, Project.MSG_VERBOSE);
  -
  -            HandlerBase hb = new RootHandler(this);
  +            HandlerBase hb = new RootHandler();
               parser.setDocumentHandler(hb);
               parser.setEntityResolver(hb);
               parser.setErrorHandler(hb);
  @@ -206,38 +196,74 @@
       }
   
       /**
  -     * The common superclass for all sax event handlers in Ant. Basically
  -     * throws an exception in each method, so subclasses should override
  -     * what they can handle.
  +     * The common superclass for all SAX event handlers used to parse
  +     * the configuration file. Each method just throws an exception, 
  +     * so subclasses should override what they can handle.
        *
  -     * Each type of xml element (task, target, etc) in ant will
  -     * have its own subclass of AbstractHandler.
  +     * Each type of XML element (task, target, etc.) in Ant has
  +     * a specific subclass.
        *
  -     * In the constructor, this class    takes over the handling of sax
  -     * events from the parent handler, and returns
  +     * In the constructor, this class takes over the handling of SAX
  +     * events from the parent handler and returns
        * control back to the parent in the endElement method.
        */
  -    private static class AbstractHandler extends HandlerBase {
  +    private class AbstractHandler extends HandlerBase {
  +        
  +        /** 
  +         * Previous handler for the document. 
  +         * When the next element is finished, control returns
  +         * to this handler.
  +         */
           protected DocumentHandler parentHandler;
  -        protected ProjectHelperImpl helper;
  -
  -        public AbstractHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
  +        
  +        /**
  +         * Creates a handler and sets the parser to use it
  +         * for the current element.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         */
  +        public AbstractHandler(DocumentHandler parentHandler) {
               this.parentHandler = parentHandler;
  -            this.helper=helper;
   
               // Start handling SAX events
  -            helper.parser.setDocumentHandler(this);
  +            parser.setDocumentHandler(this);
           }
  -
  +        
  +        /**
  +         * Handles the start of an element. This base implementation just
  +         * throws an exception.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if this method is not overridden, or in
  +         *                              case of error in an overridden version
  +         */
           public void startElement(String tag, AttributeList attrs) throws SAXParseException {
  -            throw new SAXParseException("Unexpected element \"" + tag + "\"", helper.locator);
  +            throw new SAXParseException("Unexpected element \"" + tag + "\"", locator);
           }
   
  -        public void characters(char[] buf, int start, int end) throws SAXParseException {
  -            String s = new String(buf, start, end).trim();
  +        /**
  +         * Handles text within an element. This base implementation just
  +         * throws an exception.
  +         * 
  +         * @param buf A character array of the text within the element.
  +         *            Will not be <code>null</code>.
  +         * @param start The start element in the array.
  +         * @param count The number of characters to read from the array.
  +         * 
  +         * @exception SAXParseException if this method is not overridden, or in
  +         *                              case of error in an overridden version
  +         */
  +        public void characters(char[] buf, int start, int count) throws SAXParseException {
  +            String s = new String(buf, start, count).trim();
   
               if (s.length() > 0) {
  -                throw new SAXParseException("Unexpected text \"" + s + "\"", helper.locator);
  +                throw new SAXParseException("Unexpected text \"" + s + "\"", locator);
               }
           }
   
  @@ -247,31 +273,45 @@
            */
           protected void finished() {}
   
  +        /**
  +         * Handles the end of an element. Any required clean-up is performed
  +         * by the finished() method and then the original handler is restored to
  +         * the parser.
  +         * 
  +         * @param name The name of the element which is ending.
  +         *             Will not be <code>null</code>.
  +         * 
  +         * @exception SAXException in case of error (not thrown in 
  +         *                         this implementation)
  +         * 
  +         * @see #finished()
  +         */
           public void endElement(String name) throws SAXException {
   
               finished();
               // Let parent resume handling SAX events
  -            helper.parser.setDocumentHandler(parentHandler);
  +            parser.setDocumentHandler(parentHandler);
           }
       }
   
       /**
  -     * Handler for the root element. It's only child must be the "project" element.
  +     * Handler for the root element. Its only child must be the "project" element.
        */
  -    private static class RootHandler extends HandlerBase {
  -        private ProjectHelperImpl helper;
  +    private class RootHandler extends HandlerBase {
   
  -        public RootHandler( ProjectHelperImpl helper ) {
  -            this.helper=helper;
  -        }
  -        
           /**
  -         * resolve file: URIs as relative to the build file.
  +         * Resolves file: URIs relative to the build file.
  +         * 
  +         * @param publicId The public identifer, or <code>null</code>
  +         *                 if none is available. Ignored in this 
  +         *                 implementation.
  +         * @param systemId The system identifier provided in the XML 
  +         *                 document. Will not be <code>null</code>.
            */
           public InputSource resolveEntity(String publicId,
                                            String systemId) {
           
  -            helper.project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
  +            project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
           
               if (systemId.startsWith("file:")) {
                   String path = systemId.substring(5);
  @@ -294,7 +334,7 @@
   
                   File file = new File(path);
                   if (!file.isAbsolute()) {
  -                    file = new File(helper.buildFileParent, path);
  +                    file = new File(buildFileParent, path);
                   }
                   
                   try {
  @@ -302,7 +342,7 @@
                       inputSource.setSystemId("file:" + entitySystemId);
                       return inputSource;
                   } catch (FileNotFoundException fne) {
  -                    helper.project.log(file.getAbsolutePath()+" could not be found", 
  +                    project.log(file.getAbsolutePath()+" could not be found", 
                                   Project.MSG_WARN);
                   }
               }
  @@ -310,27 +350,69 @@
               return null;
           }
   
  +        /**
  +         * Handles the start of a project element. A project handler is created
  +         * and initialised with the element name and attributes.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if the tag given is not 
  +         *                              <code>"project"</code>
  +         */
           public void startElement(String tag, AttributeList attrs) throws SAXParseException {
               if (tag.equals("project")) {
  -                new ProjectHandler(helper, this).init(tag, attrs);
  +                new ProjectHandler(this).init(tag, attrs);
               } else {
  -                throw new SAXParseException("Config file is not of expected XML type", helper.locator);
  +                throw new SAXParseException("Config file is not of expected XML type", locator);
               }
           }
   
  +        /**
  +         * Sets the locator in the project helper for future reference.
  +         * 
  +         * @param locator The locator used by the parser.
  +         *                Will not be <code>null</code>.
  +         */
           public void setDocumentLocator(Locator locator) {
  -            helper.locator = locator;
  +            ProjectHelperImpl.this.locator = locator;
           }
       }
   
       /**
        * Handler for the top level "project" element.
        */
  -    private static class ProjectHandler extends AbstractHandler {
  -        public ProjectHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
  -            super(helper, parentHandler);
  +    private class ProjectHandler extends AbstractHandler {
  +        
  +        /**
  +         * Constructor which just delegates to the superconstructor.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         */
  +        public ProjectHandler(DocumentHandler parentHandler) {
  +            super(parentHandler);
           }
  -
  +        
  +        /**
  +         * Initialisation routine called after handler creation
  +         * with the element name and attributes. The attributes which
  +         * this handler can deal with are: <code>"default"</code>,
  +         * <code>"name"</code>, <code>"id"</code> and <code>"basedir"</code>.
  +         * 
  +         * @param tag Name of the element which caused this handler
  +         *            to be created. Should not be <code>null</code>.
  +         *            Ignored in this implementation.
  +         * @param attrs Attributes of the element which caused this
  +         *              handler to be created. Must not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an unexpected attribute is 
  +         *            encountered or if the <code>"default"</code> attribute
  +         *            is missing.
  +         */
           public void init(String tag, AttributeList attrs) throws SAXParseException {
               String def = null;
               String name = null;
  @@ -350,44 +432,59 @@
                   } else if (key.equals("basedir")) {
                       baseDir = value;
                   } else {
  -                    throw new SAXParseException("Unexpected attribute \"" + attrs.getName(i) + "\"", helper.locator);
  +                    throw new SAXParseException("Unexpected attribute \"" + attrs.getName(i) + "\"", locator);
                   }
               }
   
               if (def == null) {
                   throw new SAXParseException("The default attribute of project is required", 
  -                                            helper.locator);
  +                                            locator);
               }
               
   
  -            helper.project.setDefaultTarget(def);
  +            project.setDefaultTarget(def);
   
               if (name != null) {
  -                helper.project.setName(name);
  -                helper.project.addReference(name, helper.project);
  +                project.setName(name);
  +                project.addReference(name, project);
               }
   
               if (id != null) {
  -              helper.project.addReference(id, helper.project);
  +              project.addReference(id, project);
               }
   
  -            if (helper.project.getProperty("basedir") != null) {
  -                helper.project.setBasedir(helper.project.getProperty("basedir"));
  +            if (project.getProperty("basedir") != null) {
  +                project.setBasedir(project.getProperty("basedir"));
               } else {
                   if (baseDir == null) {
  -                    helper.project.setBasedir(helper.buildFileParent.getAbsolutePath());
  +                    project.setBasedir(buildFileParent.getAbsolutePath());
                   } else {
                       // check whether the user has specified an absolute path
                       if ((new File(baseDir)).isAbsolute()) {
  -                        helper.project.setBasedir(baseDir);
  +                        project.setBasedir(baseDir);
                       } else {
  -                        helper.project.setBaseDir(helper.project.resolveFile(baseDir, helper.buildFileParent));
  +                        project.setBaseDir(project.resolveFile(baseDir, buildFileParent));
                       }
                   }
               }
   
           }
   
  +        /**
  +         * Handles the start of a top-level element within the project. An
  +         * appropriate handler is created and initialised with the details
  +         * of the element.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if the tag given is not 
  +         *            <code>"taskdef"</code>, <code>"typedef"</code>,
  +         *            <code>"property"</code>, <code>"target"</code>
  +         *            or a data type definition
  +         */
           public void startElement(String name, AttributeList attrs) throws SAXParseException {
               if (name.equals("taskdef")) {
                   handleTaskdef(name, attrs);
  @@ -397,31 +494,91 @@
                   handleProperty(name, attrs);
               } else if (name.equals("target")) {
                   handleTarget(name, attrs);
  -            } else if (helper.project.getDataTypeDefinitions().get(name) != null) {
  +            } else if (project.getDataTypeDefinitions().get(name) != null) {
                   handleDataType(name, attrs);
               } else {
  -                throw new SAXParseException("Unexpected element \"" + name + "\"", helper.locator);
  +                throw new SAXParseException("Unexpected element \"" + name + "\"", locator);
               }
           }
  -
  +        
  +        /**
  +         * Handles a task defintion element by creating a task handler
  +         * and initialising is with the details of the element.
  +         * 
  +         * @param tag The name of the element to be handled.
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element to be handled.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs when initialising 
  +         *                              the task handler
  +         *                          
  +         */
           private void handleTaskdef(String name, AttributeList attrs) throws SAXParseException {
  -            (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
  +            (new TaskHandler(this, null, null, null)).init(name, attrs);
           }
   
  +        /**
  +         * Handles a type defintion element by creating a task handler
  +         * and initialising is with the details of the element.
  +         * 
  +         * @param tag The name of the element to be handled.
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element to be handled.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs initialising the 
  +         *                              handler
  +         */
           private void handleTypedef(String name, AttributeList attrs) throws SAXParseException {
  -            (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
  +            (new TaskHandler(this, null, null, null)).init(name, attrs);
           }
   
  +        /**
  +         * Handles a property defintion element by creating a task handler
  +         * and initialising is with the details of the element.
  +         * 
  +         * @param tag The name of the element to be handled.
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element to be handled.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs initialising 
  +         *                              the handler
  +         */
           private void handleProperty(String name, AttributeList attrs) throws SAXParseException {
  -            (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
  +            (new TaskHandler(this, null, null, null)).init(name, attrs);
           }
   
  +        /**
  +         * Handles a target defintion element by creating a target handler
  +         * and initialising is with the details of the element.
  +         * 
  +         * @param tag The name of the element to be handled.
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element to be handled.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs initialising 
  +         *                              the handler
  +         */
           private void handleTarget(String tag, AttributeList attrs) throws SAXParseException {
  -            new TargetHandler(helper, this).init(tag, attrs);
  +            new TargetHandler(this).init(tag, attrs);
           }
  -
  +        /**
  +         * Handles a data type defintion element by creating a data type 
  +         * handler and initialising is with the details of the element.
  +         * 
  +         * @param tag The name of the element to be handled.
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element to be handled.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs initialising 
  +         *                              the handler
  +         */
           private void handleDataType(String name, AttributeList attrs) throws SAXParseException {
  -            new DataTypeHandler(helper, this).init(name, attrs);
  +            new DataTypeHandler(this).init(name, attrs);
           }
   
       }
  @@ -429,13 +586,37 @@
       /**
        * Handler for "target" elements.
        */
  -    private static class TargetHandler extends AbstractHandler {
  +    private class TargetHandler extends AbstractHandler {
           private Target target;
   
  -        public TargetHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
  -            super(helper, parentHandler);
  +        /**
  +         * Constructor which just delegates to the superconstructor.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         */
  +        public TargetHandler(DocumentHandler parentHandler) {
  +            super(parentHandler);
           }
   
  +        /**
  +         * Initialisation routine called after handler creation
  +         * with the element name and attributes. The attributes which
  +         * this handler can deal with are: <code>"name"</code>,
  +         * <code>"depends"</code>, <code>"if"</code>,
  +         * <code>"unless"</code>, <code>"id"</code> and 
  +         * <code>"description"</code>.
  +         * 
  +         * @param tag Name of the element which caused this handler
  +         *            to be created. Should not be <code>null</code>.
  +         *            Ignored in this implementation.
  +         * @param attrs Attributes of the element which caused this
  +         *              handler to be created. Must not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an unexpected attribute is encountered
  +         *            or if the <code>"name"</code> attribute is missing.
  +         */
           public void init(String tag, AttributeList attrs) throws SAXParseException {
               String name = null;
               String depends = "";
  @@ -461,12 +642,12 @@
                   } else if (key.equals("description")) {
                       description = value;
                   } else {
  -                    throw new SAXParseException("Unexpected attribute \"" + key + "\"", helper.locator);
  +                    throw new SAXParseException("Unexpected attribute \"" + key + "\"", locator);
                   }
               }
   
               if (name == null) {
  -                throw new SAXParseException("target element appears without a name attribute", helper.locator);
  +                throw new SAXParseException("target element appears without a name attribute", locator);
               }
   
               target = new Target();
  @@ -474,10 +655,10 @@
               target.setIf(ifCond);
               target.setUnless(unlessCond);
               target.setDescription(description);
  -            helper.project.addTarget(name, target);
  +            project.addTarget(name, target);
   
               if (id != null && !id.equals("")) {
  -                helper.project.addReference(id, target);
  +                project.addReference(id, target);
               }
   
               // take care of dependencies
  @@ -487,11 +668,22 @@
               }
           }
   
  +        /**
  +         * Handles the start of an element within a target.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs when initialising
  +         *                              the appropriate child handler
  +         */
           public void startElement(String name, AttributeList attrs) throws SAXParseException {
  -            if (helper.project.getDataTypeDefinitions().get(name) != null) {
  -                new DataTypeHandler(helper, this, target).init(name, attrs);
  +            if (project.getDataTypeDefinitions().get(name) != null) {
  +                new DataTypeHandler(this, target).init(name, attrs);
               } else {
  -                new TaskHandler(helper, this, target, null, target).init(name, attrs);
  +                new TaskHandler(this, target, null, target).init(name, attrs);
               }
           }
       }
  @@ -499,28 +691,78 @@
       /**
        * Handler for all task elements.
        */
  -    private static class TaskHandler extends AbstractHandler {
  +    private class TaskHandler extends AbstractHandler {
  +        /** Containing target, if any. */
           private Target target;
  +        /** 
  +         * Container for the task, if any. If target is 
  +         * non-<code>null</code>, this must be too.
  +         */
           private TaskContainer container;
  +        /**
  +         * Task created by this handler.
  +         */
           private Task task;
  +        /**
  +         * Wrapper for the parent element, if any. The wrapper for this 
  +         * element will be added to this wrapper as a child.
  +         */
           private RuntimeConfigurable parentWrapper;
  +        /**
  +         * Wrapper for this element which takes care of actually configuring
  +         * the element, if this element is contained within a target. 
  +         * Otherwise the configuration is performed with the configure method.
  +         * @see ProjectHelper#configure(Object,AttributeList,Project)
  +         */
           private RuntimeConfigurable wrapper = null;
  -
  -        public TaskHandler(ProjectHelperImpl helper,
  -                           DocumentHandler parentHandler,
  -                           TaskContainer container,
  -                           RuntimeConfigurable parentWrapper,
  -                           Target target)
  -        {
  -            super(helper, parentHandler);
  +        
  +        /**
  +         * Constructor.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         * 
  +         * @param container     Container for the element. 
  +         *                      May be <code>null</code> if the target is 
  +         *                      <code>null</code> as well. If the
  +         *                      target is <code>null</code>, this parameter
  +         *                      is effectively ignored.
  +         * 
  +         * @param parentWrapper Wrapper for the parent element, if any.
  +         *                      May be <code>null</code>. If the
  +         *                      target is <code>null</code>, this parameter
  +         *                      is effectively ignored.
  +         * 
  +         * @param target        Target this element is part of.
  +         *                      May be <code>null</code>.
  +         */
  +        public TaskHandler(DocumentHandler parentHandler, TaskContainer container, RuntimeConfigurable parentWrapper, Target target) {
  +            super(parentHandler);
               this.container = container;
               this.parentWrapper = parentWrapper;
               this.target = target;
           }
   
  +        /**
  +         * Initialisation routine called after handler creation
  +         * with the element name and attributes. This configures
  +         * the element with its attributes and sets it up with
  +         * its parent container (if any). Nested elements are then
  +         * added later as the parser encounters them.
  +         * 
  +         * @param tag Name of the element which caused this handler
  +         *            to be created. Must not be <code>null</code>.
  +         *            
  +         * @param attrs Attributes of the element which caused this
  +         *              handler to be created. Must not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException in case of error (not thrown in
  +         *                              this implementation)
  +         */
           public void init(String tag, AttributeList attrs) throws SAXParseException {
               try {
  -                task = helper.project.createTask(tag);
  +                task = project.createTask(tag);
               } catch (BuildException e) {
                   // swallow here, will be thrown again in 
                   // UnknownElement.maybeConfigure if the problem persists.
  @@ -528,15 +770,13 @@
   
               if (task == null) {
                   task = new UnknownElement(tag);
  -                task.setProject(helper.project);
  -                task.setTaskType(tag);
  +                task.setProject(project);
  +                //XXX task.setTaskType(tag);
                   task.setTaskName(tag);
               }
   
  -            task.setLocation(new Location(helper.buildFile.toString(),
  -                                          helper.locator.getLineNumber(),
  -                                          helper.locator.getColumnNumber()));
  -            helper.configureId(task, attrs);
  +            task.setLocation(new Location(buildFile.toString(), locator.getLineNumber(), locator.getColumnNumber()));
  +            configureId(task, attrs);
   
               // Top level tasks don't have associated targets
               if (target != null) {
  @@ -550,35 +790,65 @@
                   }
               } else {
                   task.init();
  -                configure(task, attrs, helper.project);
  +                configure(task, attrs, project);
               }
           }
   
  +        /**
  +         * Executes the task if it is a top-level one.
  +         */
           protected void finished() {
               if (task != null && target == null) {
                   task.execute();
               }
           }
   
  -        public void characters(char[] buf, int start, int end) throws SAXParseException {
  +        /**
  +         * Adds text to the task, using the wrapper if one is
  +         * available (in other words if the task is within a target) 
  +         * or using addText otherwise.
  +         * 
  +         * @param buf A character array of the text within the element.
  +         *            Will not be <code>null</code>.
  +         * @param start The start element in the array.
  +         * @param count The number of characters to read from the array.
  +         * 
  +         * @exception SAXParseException if the element doesn't support text
  +         * 
  +         * @see ProjectHelper#addText(Project,Object,char[],int,int)
  +         */
  +        public void characters(char[] buf, int start, int count) throws SAXParseException {
               if (wrapper == null) {
                   try {
  -                    addText(helper.project, task, buf, start, end);
  +                    addText(project, task, buf, start, count);
                   } catch (BuildException exc) {
  -                    throw new SAXParseException(exc.getMessage(), helper.locator, exc);
  +                    throw new SAXParseException(exc.getMessage(), locator, exc);
                   }
               } else {
  -                wrapper.addText(buf, start, end);
  +                wrapper.addText(buf, start, count);
               }
           }
  -
  +        
  +        /**
  +         * Handles the start of an element within a target. Task containers
  +         * will always use another task handler, and all other tasks
  +         * will always use a nested element handler.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs when initialising
  +         *                              the appropriate child handler
  +         */
           public void startElement(String name, AttributeList attrs) throws SAXParseException {
               if (task instanceof TaskContainer) {
                   // task can contain other tasks - no other nested elements possible
  -                new TaskHandler(helper, this, (TaskContainer)task, wrapper, target).init(name, attrs);
  +                new TaskHandler(this, (TaskContainer)task, wrapper, target).init(name, attrs);
               }
               else {
  -                new NestedElementHandler(helper, this, task, wrapper, target).init(name, attrs);
  +                new NestedElementHandler(this, task, wrapper, target).init(name, attrs);
               }
           }
       }
  @@ -586,24 +856,50 @@
       /**
        * Handler for all nested properties.
        */
  -    private static class NestedElementHandler extends AbstractHandler {
  +    private class NestedElementHandler extends AbstractHandler {
  +        /** Parent object (task/data type/etc). */
           private Object parent;
  +        /** The nested element itself. */
           private Object child;
  +        /**
  +         * Wrapper for the parent element, if any. The wrapper for this 
  +         * element will be added to this wrapper as a child.
  +         */
           private RuntimeConfigurable parentWrapper;
  +        /**
  +         * Wrapper for this element which takes care of actually configuring
  +         * the element, if a parent wrapper is provided.
  +         * Otherwise the configuration is performed with the configure method.
  +         * @see ProjectHelper#configure(Object,AttributeList,Project)
  +         */
           private RuntimeConfigurable childWrapper = null;
  -        private TaskAdapter adapter=null;
  +        /** Target this element is part of, if any. */
           private Target target;
   
  -        public NestedElementHandler(ProjectHelperImpl helper,
  -                                    DocumentHandler parentHandler, 
  +        /**
  +         * Constructor.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         * 
  +         * @param parent        Parent of this element (task/data type/etc).
  +         *                      Must not be <code>null</code>.
  +         * 
  +         * @param parentWrapper Wrapper for the parent element, if any.
  +         *                      May be <code>null</code>.
  +         * 
  +         * @param target        Target this element is part of.
  +         *                      May be <code>null</code>.
  +         */
  +        public NestedElementHandler(DocumentHandler parentHandler, 
                                       Object parent,
                                       RuntimeConfigurable parentWrapper,
                                       Target target) {
  -            super(helper, parentHandler);
  +            super(parentHandler);
   
               if (parent instanceof TaskAdapter) {
  -                this.adapter= (TaskAdapter)parent;
  -                this.parent = adapter.getProxy();
  +                this.parent = ((TaskAdapter) parent).getProxy();
               } else {
                   this.parent = parent;
               }
  @@ -611,87 +907,159 @@
               this.target = target;
           }
   
  +        /**
  +         * Initialisation routine called after handler creation
  +         * with the element name and attributes. This configures
  +         * the element with its attributes and sets it up with
  +         * its parent container (if any). Nested elements are then
  +         * added later as the parser encounters them.
  +         * 
  +         * @param tag Name of the element which caused this handler
  +         *            to be created. Must not be <code>null</code>.
  +         *            
  +         * @param attrs Attributes of the element which caused this
  +         *              handler to be created. Must not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException in case of error, such as a 
  +         *            BuildException being thrown during configuration.
  +         */
           public void init(String propType, AttributeList attrs) throws SAXParseException {
               Class parentClass = parent.getClass();
               IntrospectionHelper ih = 
                   IntrospectionHelper.getHelper(parentClass);
  -            if( adapter!=null ) {
  -                adapter.setIntrospectionHelper( ih );
  -            }
  -            
  +
               try {
                   String elementName = propType.toLowerCase(Locale.US);
                   if (parent instanceof UnknownElement) {
                       UnknownElement uc = new UnknownElement(elementName);
  -                    uc.setProject(helper.project);
  +                    uc.setProject(project);
                       ((UnknownElement) parent).addChild(uc);
                       child = uc;
                   } else {
  -                    child = ih.createElement(helper.project, parent, elementName);
  +                    child = ih.createElement(project, parent, elementName);
                   }
   
  -                helper.configureId(child, attrs);
  +                configureId(child, attrs);
   
                   if (parentWrapper != null) {
                       childWrapper = new RuntimeConfigurable(child, propType);
                       childWrapper.setAttributes(attrs);
                       parentWrapper.addChild(childWrapper);
                   } else {
  -                    configure(child, attrs, helper.project);
  -                    ih.storeElement(helper.project, parent, child, elementName);
  +                    configure(child, attrs, project);
  +                    ih.storeElement(project, parent, child, elementName);
                   }
               } catch (BuildException exc) {
  -                throw new SAXParseException(exc.getMessage(), helper.locator, exc);
  +                throw new SAXParseException(exc.getMessage(), locator, exc);
               }
           }
   
  -        public void characters(char[] buf, int start, int end) throws SAXParseException {
  +        /**
  +         * Adds text to the element, using the wrapper if one is
  +         * available or using addText otherwise.
  +         * 
  +         * @param buf A character array of the text within the element.
  +         *            Will not be <code>null</code>.
  +         * @param start The start element in the array.
  +         * @param count The number of characters to read from the array.
  +         * 
  +         * @exception SAXParseException if the element doesn't support text
  +         * 
  +         * @see ProjectHelper#addText(Project,Object,char[],int,int)
  +         */
  +        public void characters(char[] buf, int start, int count) throws SAXParseException {
               if (parentWrapper == null) {
                   try {
  -                    addText(helper.project, child, buf, start, end);
  +                    addText(project, child, buf, start, count);
                   } catch (BuildException exc) {
  -                    throw new SAXParseException(exc.getMessage(), helper.locator, exc);
  +                    throw new SAXParseException(exc.getMessage(), locator, exc);
                   }
               } else {
  -                childWrapper.addText(buf, start, end);
  +                childWrapper.addText(buf, start, count);
               }
           }
   
  +        /**
  +         * Handles the start of an element within this one. Task containers
  +         * will always use a task handler, and all other elements
  +         * will always use another nested element handler.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs when initialising
  +         *                              the appropriate child handler
  +         */
           public void startElement(String name, AttributeList attrs) throws SAXParseException {
               if (child instanceof TaskContainer) {
                   // taskcontainer nested element can contain other tasks - no other 
                   // nested elements possible
  -                new TaskHandler(helper, this, (TaskContainer)child, childWrapper, target).init(name, attrs);
  +                new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs);
               }
               else {
  -                new NestedElementHandler(helper, this, child, childWrapper, target).init(name, attrs);
  +                new NestedElementHandler(this, child, childWrapper, target).init(name, attrs);
               }
           }
       }
   
       /**
  -     * Handler for all data types at global level.
  +     * Handler for all data types directly subordinate to project or target.
        */
  -    private static class DataTypeHandler extends AbstractHandler {
  +    private class DataTypeHandler extends AbstractHandler {
  +        /** Parent target, if any. */
           private Target target;
  +        /** The element being configured. */
           private Object element;
  +        /** Wrapper for this element, if it's part of a target. */
           private RuntimeConfigurable wrapper = null;
  -
  -        public DataTypeHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
  -            this(helper, parentHandler, null);
  +        
  +        /**
  +         * Constructor with no target specified.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         */
  +        public DataTypeHandler(DocumentHandler parentHandler) {
  +            this(parentHandler, null);
           }
   
  -        public DataTypeHandler(ProjectHelperImpl helper,
  -                               DocumentHandler parentHandler,
  -                               Target target)
  -        {
  -            super(helper, parentHandler);
  +        /**
  +         * Constructor with a target specified.
  +         * 
  +         * @param parentHandler The handler which should be restored to the 
  +         *                      parser at the end of the element. 
  +         *                      Must not be <code>null</code>.
  +         * 
  +         * @param target The parent target of this element.
  +         *               May be <code>null</code>.
  +         */
  +        public DataTypeHandler(DocumentHandler parentHandler, Target target) {
  +            super(parentHandler);
               this.target = target;
           }
   
  +        /**
  +         * Initialisation routine called after handler creation
  +         * with the element name and attributes. This configures
  +         * the element with its attributes and sets it up with
  +         * its parent container (if any). Nested elements are then
  +         * added later as the parser encounters them.
  +         * 
  +         * @param tag Name of the element which caused this handler
  +         *            to be created. Must not be <code>null</code>.
  +         *            
  +         * @param attrs Attributes of the element which caused this
  +         *              handler to be created. Must not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException in case of error, such as a 
  +         *            BuildException being thrown during configuration.
  +         */
           public void init(String propType, AttributeList attrs) throws SAXParseException {
               try {
  -                element = helper.project.createDataType(propType);
  +                element = project.createDataType(propType);
                   if (element == null) {
                       throw new BuildException("Unknown data type "+propType);
                   }
  @@ -701,30 +1069,60 @@
                       wrapper.setAttributes(attrs);
                       target.addDataType(wrapper);
                   } else {
  -                    configure(element, attrs, helper.project);
  -                    helper.configureId(element, attrs);
  +                    configure(element, attrs, project);
  +                    configureId(element, attrs);
                   }
               } catch (BuildException exc) {
  -                throw new SAXParseException(exc.getMessage(), helper.locator, exc);
  +                throw new SAXParseException(exc.getMessage(), locator, exc);
               }
           }
   
  -        public void characters(char[] buf, int start, int end) throws SAXParseException {
  +        // XXX: (Jon Skeet) Any reason why this doesn't use the wrapper
  +        // if one is available, whereas NestedElementHandler.characters does?
  +        /**
  +         * Adds text to the element.
  +         * 
  +         * @param buf A character array of the text within the element.
  +         *            Will not be <code>null</code>.
  +         * @param start The start element in the array.
  +         * @param count The number of characters to read from the array.
  +         * 
  +         * @exception SAXParseException if the element doesn't support text
  +         * 
  +         * @see ProjectHelper#addText(Project,Object,char[],int,int)
  +         */
  +        public void characters(char[] buf, int start, int count) throws SAXParseException {
               try {
  -                addText(helper.project, element, buf, start, end);
  +                addText(project, element, buf, start, count);
               } catch (BuildException exc) {
  -                throw new SAXParseException(exc.getMessage(), helper.locator, exc);
  +                throw new SAXParseException(exc.getMessage(), locator, exc);
               }
           }
   
  +        /**
  +         * Handles the start of an element within this one.
  +         * This will always use a nested element handler.
  +         * 
  +         * @param tag The name of the element being started. 
  +         *            Will not be <code>null</code>.
  +         * @param attrs Attributes of the element being started.
  +         *              Will not be <code>null</code>.
  +         * 
  +         * @exception SAXParseException if an error occurs when initialising
  +         *                              the child handler
  +         */
           public void startElement(String name, AttributeList attrs) throws SAXParseException {
  -            new NestedElementHandler(helper, this, element, wrapper, target).init(name, attrs);
  +            new NestedElementHandler(this, element, wrapper, target).init(name, attrs);
           }
       }
   
  -    public ProjectHelperImpl() {
  -    }
  -    
  +    /**
  +     * Returns the parser factory to use. Only one parser
  +     * factory is ever created by this method (multi-threading 
  +     * issues aside) and is then cached for future use.
  +     * 
  +     * @return a SAXParserFactory to use within this class
  +     */
       private static SAXParserFactory getParserFactory() {
           if (parserFactory == null) {
               parserFactory = SAXParserFactory.newInstance();
  @@ -734,11 +1132,14 @@
       }
   
       /**
  -     * Scan AttributeList for the id attribute and maybe add a
  -     * reference to project.  
  -     *
  -     * <p>Moved out of {@link #configure configure} to make it happen
  -     * at parser time.</p> 
  +     * Scans an attribute list for the <code>id</code> attribute and 
  +     * stores a reference to the target object in the project if an
  +     * id is found.
  +     * <p>
  +     * This method was moved out of the configure method to allow
  +     * it to be executed at parse time.
  +     * 
  +     * @see #configure(Object,AttributeList,Project)
        */
       private void configureId(Object target, AttributeList attr) {
           String id = attr.getValue("id");
  @@ -746,5 +1147,4 @@
               project.addReference(id, target);
           }
       }
  -
   }
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message