ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From adammurd...@apache.org
Subject cvs commit: jakarta-ant/proposal/myrmidon/src/xdocs todo.xml
Date Mon, 11 Mar 2002 06:07:24 GMT
adammurdoch    02/03/10 22:07:24

  Modified:    proposal/myrmidon/etc/testcases/org/apache/antlib/core
                        property.ant
               proposal/myrmidon/src/java/org/apache/myrmidon/components/builder
                        DefaultProjectBuilder.java Resources.properties
               proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace
                        DefaultTaskContext.java Resources.properties
               proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder
                        ProjectBuilder.java
               proposal/myrmidon/src/testcases/org/apache/antlib/core
                        PropertyTest.java
               proposal/myrmidon/src/xdocs todo.xml
  Added:       proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/builder
                        bad-project-name.ant bad-target-name.ant
               proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder
                        ProjectException.java
               proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model
                        DefaultNameValidator.java NameValidator.java
                        Resources.properties
               proposal/myrmidon/src/testcases/org/apache/myrmidon/components/builder
                        DefaultProjectBuilderTest.java
               proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/model
                        DefaultNameValidatorTest.java
  Log:
  * Added NameValidator, to provide a reasonably flexible mechanism for
    specifying/testing name validity.
  
  * NameValidator is used by DefaultProjectBuilder for project and target
    names, and by DefaultTaskContext for Property names.
  
  * Added ProjectException, thrown by ProjectBuilder.build().
  
  * Tidy-up error messages for project building errors.
  
  * Added a bunch of tests
  
  Submitted by Darrell DeBoer [darrell@apache.org]
  
  Revision  Changes    Path
  1.3       +12 -0     jakarta-ant/proposal/myrmidon/etc/testcases/org/apache/antlib/core/property.ant
  
  Index: property.ant
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/etc/testcases/org/apache/antlib/core/property.ant,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- property.ant	9 Mar 2002 10:13:03 -0000	1.2
  +++ property.ant	11 Mar 2002 06:07:23 -0000	1.3
  @@ -50,4 +50,16 @@
               <property-test-type value="value 3"/>
           </property>
       </target>
  +
  +    <!-- Test properties with invalid names -->
  +    <target name="bad-prop-name1">
  +        <property name="badname!" value="value"/>
  +    </target>
  +    <target name="bad-prop-name2">
  +        <property name="bad name" value="value"/>
  +    </target>
  +    <target name="bad-prop-name3">
  +        <property name="" value="value"/>
  +    </target>
  +
   </project>
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/builder/bad-project-name.ant
  
  Index: bad-project-name.ant
  ===================================================================
  <!-- Project with an invalid name -->
  <project version="2.0" name="!badname">
      <target name="main"/>
  </project>
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/builder/bad-target-name.ant
  
  Index: bad-target-name.ant
  ===================================================================
  <!-- Target with an invalid name -->
  <project version="2.0" name="ok name">
      <target name="main"/>
      <target name="bad ^ name"/>
  </project>
  
  
  
  1.37      +135 -71   jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProjectBuilder.java
  
  Index: DefaultProjectBuilder.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProjectBuilder.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- DefaultProjectBuilder.java	4 Mar 2002 04:23:37 -0000	1.36
  +++ DefaultProjectBuilder.java	11 Mar 2002 06:07:23 -0000	1.37
  @@ -8,6 +8,7 @@
   package org.apache.myrmidon.components.builder;
   
   import java.io.File;
  +import java.net.MalformedURLException;
   import java.net.URL;
   import java.util.ArrayList;
   import java.util.HashMap;
  @@ -22,11 +23,13 @@
   import org.apache.avalon.framework.configuration.ConfigurationException;
   import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  -import org.apache.myrmidon.framework.conditions.Condition;
   import org.apache.myrmidon.framework.conditions.AndCondition;
  +import org.apache.myrmidon.framework.conditions.Condition;
   import org.apache.myrmidon.framework.conditions.IsSetCondition;
   import org.apache.myrmidon.framework.conditions.NotCondition;
   import org.apache.myrmidon.interfaces.builder.ProjectBuilder;
  +import org.apache.myrmidon.interfaces.builder.ProjectException;
  +import org.apache.myrmidon.interfaces.model.DefaultNameValidator;
   import org.apache.myrmidon.interfaces.model.Project;
   import org.apache.myrmidon.interfaces.model.Target;
   import org.apache.myrmidon.interfaces.model.TypeLib;
  @@ -36,7 +39,8 @@
    * Default implementation to construct project from a build file.
    *
    * @author <a href="mailto:peter@apache.org">Peter Donald</a>
  - * @version $Revision: 1.36 $ $Date: 2002/03/04 04:23:37 $
  + * @version $Revision: 1.37 $ $Date: 2002/03/11 06:07:23 $
  + *
    * @ant:type type="project-builder" name="xml"
    * @ant:type type="project-builder" name="ant"
    */
  @@ -54,36 +58,37 @@
       private final static int IMPLICIT_TASKS = 2;
       private final static int TARGETS = 3;
   
  +    // Use a name validator with the default rules.
  +    private DefaultNameValidator m_nameValidator = new DefaultNameValidator();
  +
       /**
        * build a project from file.
        *
        * @param source the source
        * @return the constructed Project
  -     * @exception Exception if an error occurs
  +     * @exception ProjectException if an error occurs
        */
       public Project build( final String source )
  -        throws Exception
  +        throws ProjectException
       {
           final File file = new File( source );
           return build( file, new HashMap() );
       }
   
       private Project build( final File file, final HashMap projects )
  -        throws Exception
  +        throws ProjectException
       {
  -        final URL systemID = file.toURL();
  +        final URL systemID = extractURL( file );
           final Project result = (Project)projects.get( systemID.toString() );
           if( null != result )
           {
               return result;
           }
   
  -        final SAXConfigurationHandler handler = new SAXConfigurationHandler();
  -
  -        process( systemID, handler );
  -
  -        final Configuration configuration = handler.getConfiguration();
  +        // Parse the project file
  +        final Configuration configuration = parseProject( systemID );
   
  +        // Build the project model
           final DefaultProject project = buildProject( file, configuration );
   
           projects.put( systemID.toString(), project );
  @@ -94,20 +99,33 @@
           return project;
       }
   
  -    protected void process( final URL systemID,
  -                            final SAXConfigurationHandler handler )
  -        throws Exception
  -    {
  -        final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
  -        final SAXParser saxParser = saxParserFactory.newSAXParser();
  -        final XMLReader parser = saxParser.getXMLReader();
  -        parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );
  -        parser.setFeature( "http://xml.org/sax/features/namespaces", false );
  -        //parser.setFeature( "http://xml.org/sax/features/validation", false );
  -
  -        parser.setContentHandler( handler );
  -        parser.setErrorHandler( handler );
  -        parser.parse( systemID.toString() );
  +    /**
  +     * Parses the project.
  +     */
  +    private Configuration parseProject( final URL systemID )
  +        throws ProjectException
  +    {
  +        try
  +        {
  +            final SAXConfigurationHandler handler = new SAXConfigurationHandler();
  +            final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
  +            final SAXParser saxParser = saxParserFactory.newSAXParser();
  +            final XMLReader parser = saxParser.getXMLReader();
  +            parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );
  +            parser.setFeature( "http://xml.org/sax/features/namespaces", false );
  +            //parser.setFeature( "http://xml.org/sax/features/validation", false );
  +
  +            parser.setContentHandler( handler );
  +            parser.setErrorHandler( handler );
  +            parser.parse( systemID.toString() );
  +
  +            return handler.getConfiguration();
  +        }
  +        catch( Exception e )
  +        {
  +            String message = REZ.getString( "ant.project-parse.error" );
  +            throw new ProjectException( message, e );
  +        }
       }
   
       /**
  @@ -116,23 +134,20 @@
        * @param file the file from which configuration was loaded
        * @param configuration the configuration loaded
        * @return the created Project
  -     * @exception Exception if an error occurs
  -     * @exception Exception if an error occurs
  -     * @exception ConfigurationException if an error occurs
  +     * @exception ProjectException if an error occurs building the project
        */
       private DefaultProject buildProject( final File file,
                                            final Configuration configuration )
  -        throws Exception
  +        throws ProjectException
       {
           if( !configuration.getName().equals( "project" ) )
           {
               final String message = REZ.getString( "ant.no-project-element.error" );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
           //get project-level attributes
  -        final String projectName = configuration.getAttribute( "name",
  -                                                               FileUtil.removeExtension( file.getName() ) );
  +        final String projectName = getProjectName( configuration, file );
           final String baseDirectoryName = configuration.getAttribute( "basedir", null );
           final String defaultTarget = configuration.getAttribute( "default", "main" );
           final Version version = getVersion( configuration );
  @@ -141,7 +156,7 @@
           {
               final String message =
                   REZ.getString( "ant.bad-version.error", VERSION, version );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
           //determine base directory for project.  Use the directory containing
  @@ -169,11 +184,51 @@
       }
   
       /**
  +     * Get the project name from the configuration, or create a default name if none
  +     * was supplied.
  +     */
  +    private String getProjectName( final Configuration configuration, final File file )
  +        throws ProjectException
  +    {
  +        String projectName = configuration.getAttribute( "name", null );
  +
  +        if( projectName == null )
  +        {
  +            // Create a name based on the file name.
  +            String fileNameBase = FileUtil.removeExtension( file.getName() );
  +            try
  +            {
  +                projectName = m_nameValidator.makeValidName( fileNameBase );
  +            }
  +            catch( Exception e )
  +            {
  +                String message = REZ.getString( "ant.project-create-name.error" );
  +                throw new ProjectException( message, e );
  +            }
  +        }
  +        else
  +        {
  +            // Make sure the supplied name is valid.
  +            try
  +            {
  +                m_nameValidator.validate( projectName );
  +            }
  +            catch( Exception e )
  +            {
  +                String message = REZ.getString( "ant.project-bad-name.error" );
  +                throw new ProjectException( message, e );
  +            }
  +        }
  +        return projectName;
  +
  +    }
  +
  +    /**
        * Retrieve the version attribute from the specified configuration element.
        * Throw exceptions with meaningful errors if malformed or missing.
        */
       private Version getVersion( final Configuration configuration )
  -        throws Exception
  +        throws ProjectException
       {
           try
           {
  @@ -183,7 +238,7 @@
           catch( final ConfigurationException ce )
           {
               final String message = REZ.getString( "ant.version-missing.error" );
  -            throw new ConfigurationException( message, ce );
  +            throw new ProjectException( message, ce );
           }
       }
   
  @@ -191,7 +246,7 @@
        * Utility function to extract version
        */
       private Version parseVersion( final String versionString )
  -        throws Exception
  +        throws ProjectException
       {
   
           try
  @@ -202,8 +257,7 @@
           {
               final String message =
                   REZ.getString( "ant.malformed.version", versionString );
  -            getLogger().warn( message );
  -            throw new ConfigurationException( message, e );
  +            throw new ProjectException( message, e );
           }
       }
   
  @@ -212,12 +266,12 @@
        *
        * @param project the project
        * @param configuration the Configuration
  -     * @exception Exception if an error occurs
  +     * @exception ProjectException if an error occurs
        */
       private void buildTopLevelProject( final DefaultProject project,
                                          final Configuration configuration,
                                          final HashMap projects )
  -        throws Exception
  +        throws ProjectException
       {
           final ArrayList implicitTaskList = new ArrayList();
           final Configuration[] children = configuration.getChildren();
  @@ -277,7 +331,7 @@
               {
                   final String message =
                       REZ.getString( "ant.unknown-toplevel-element.error", name, element.getLocation() );
  -                throw new Exception( message );
  +                throw new ProjectException( message );
               }
           }
   
  @@ -291,7 +345,7 @@
       private void buildProjectRef( final DefaultProject project,
                                     final Configuration element,
                                     final HashMap projects )
  -        throws Exception
  +        throws ProjectException
       {
           final String name = element.getAttribute( "name", null );
           final String location = element.getAttribute( "location", null );
  @@ -300,27 +354,31 @@
           {
               final String message =
                   REZ.getString( "ant.projectref-no-name.error", element.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
  -        if( !validName( name ) )
  +        try
  +        {
  +            m_nameValidator.validate( name );
  +        }
  +        catch( Exception e )
           {
               final String message =
                   REZ.getString( "ant.projectref-bad-name.error", element.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message, e );
           }
   
           if( null == location )
           {
               final String message =
                   REZ.getString( "ant.projectref-no-location.error", element.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
           // Build the URL of the referenced projects
           final File baseDirectory = project.getBaseDirectory();
           final File file = FileUtil.resolveFile( baseDirectory, location );
  -        final String systemID = file.toURL().toString();
  +        final String systemID = extractURL( file ).toString();
   
           // Locate the referenced project, building it if necessary
           Project other = (Project)projects.get( systemID );
  @@ -333,9 +391,22 @@
           project.addProject( name, other );
       }
   
  +    private URL extractURL( final File file ) throws ProjectException
  +    {
  +        try
  +        {
  +            return file.toURL();
  +        }
  +        catch( MalformedURLException e )
  +        {
  +            final String message = REZ.getString( "ant.project-unexpected.error" );
  +            throw new ProjectException( message, e );
  +        }
  +    }
  +
       private void buildTypeLib( final DefaultProject project,
                                  final Configuration element )
  -        throws Exception
  +        throws ProjectException
       {
           final String library = element.getAttribute( "library", null );
           final String name = element.getAttribute( "name", null );
  @@ -345,7 +416,7 @@
           {
               final String message =
                   REZ.getString( "ant.import-no-library.error", element.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
           if( null == name || null == type )
  @@ -354,7 +425,7 @@
               {
                   final String message =
                       REZ.getString( "ant.import-malformed.error", element.getLocation() );
  -                throw new Exception( message );
  +                throw new ProjectException( message );
               }
           }
   
  @@ -368,14 +439,14 @@
        * @param target the Configuration
        */
       private void buildTarget( final DefaultProject project, final Configuration target )
  -        throws Exception
  +        throws ProjectException
       {
           final String name = target.getAttribute( "name", null );
           final String depends = target.getAttribute( "depends", null );
           final String ifCondition = target.getAttribute( "if", null );
           final String unlessCondition = target.getAttribute( "unless", null );
   
  -        verifyName( name, target );
  +        verifyTargetName( name, target );
   
           if( getLogger().isDebugEnabled() )
           {
  @@ -392,24 +463,30 @@
           project.addTarget( name, defaultTarget );
       }
   
  -    private void verifyName( final String name, final Configuration target ) throws Exception
  +    private void verifyTargetName( final String name, final Configuration target )
  +        throws ProjectException
       {
           if( null == name )
           {
               final String message =
                   REZ.getString( "ant.target-noname.error", target.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message );
           }
   
  -        if( !validName( name ) )
  +        try
  +        {
  +            m_nameValidator.validate( name );
  +        }
  +        catch( Exception e )
           {
               final String message =
                   REZ.getString( "ant.target-bad-name.error", target.getLocation() );
  -            throw new Exception( message );
  +            throw new ProjectException( message, e );
           }
       }
   
  -    private String[] buildDependsList( final String depends, final Configuration target ) throws Exception
  +    private String[] buildDependsList( final String depends, final Configuration target )
  +        throws ProjectException
       {
           String[] dependencies = null;
   
  @@ -428,7 +505,7 @@
                       final String message = REZ.getString( "ant.target-bad-dependency.error",
                                                             target.getName(),
                                                             target.getLocation() );
  -                    throw new Exception( message );
  +                    throw new ProjectException( message );
                   }
   
                   if( getLogger().isDebugEnabled() )
  @@ -447,7 +524,6 @@
   
       private Condition buildCondition( final String ifCondition,
                                         final String unlessCondition )
  -        throws Exception
       {
           final AndCondition condition = new AndCondition();
   
  @@ -474,17 +550,5 @@
           }
   
           return condition;
  -    }
  -
  -    protected boolean validName( final String name )
  -    {
  -        if( -1 != name.indexOf( "->" ) )
  -        {
  -            return false;
  -        }
  -        else
  -        {
  -            return true;
  -        }
       }
   }
  
  
  
  1.6       +5 -1      jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/Resources.properties,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Resources.properties	3 Mar 2002 02:19:10 -0000	1.5
  +++ Resources.properties	11 Mar 2002 06:07:23 -0000	1.6
  @@ -10,10 +10,14 @@
   ant.project-banner.notice=Project {0} base directory: {1}.
   ant.target-parse.notice=Parsing target: {0}.
   ant.target-if.notice=Target if condition: {0}
  -ant.target- unless.notice=Target unless condition: {0}
  +ant.target-unless.notice=Target unless condition: {0}
   ant.target-dependency.notice=Target dependency: {0}
  +ant.project-unexpected.error=Unexpected error building project.
  +ant.project-parse.error=Error parsing project.
   ant.no-project-element.error=Project file must be enclosed in project element.
   ant.unknown-toplevel-element.error=Unknown top-level element {0} at {1}.
  +ant.project-bad-name.error=Invalid project name.
  +ant.project-create-name.error=Could not create a name for this project.
   ant.projectref-no-name.error=Malformed projectref without a name attribute at {0}.
   ant.projectref-bad-name.error=Projectref with an invalid name attribute at {0}.
   ant.projectref-no-location.error=Malformed projectref without a location attribute at {0}.
  
  
  
  1.20      +25 -1     jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
  
  Index: DefaultTaskContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- DefaultTaskContext.java	9 Mar 2002 02:04:26 -0000	1.19
  +++ DefaultTaskContext.java	11 Mar 2002 06:07:24 -0000	1.20
  @@ -20,13 +20,14 @@
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.myrmidon.api.TaskContext;
   import org.apache.myrmidon.api.TaskException;
  +import org.apache.myrmidon.interfaces.model.DefaultNameValidator;
   import org.apache.myrmidon.interfaces.workspace.PropertyResolver;
   
   /**
    * Default implementation of TaskContext.
    *
    * @author <a href="mailto:peter@apache.org">Peter Donald</a>
  - * @version $Revision: 1.19 $ $Date: 2002/03/09 02:04:26 $
  + * @version $Revision: 1.20 $ $Date: 2002/03/11 06:07:24 $
    */
   public class DefaultTaskContext
       implements TaskContext, Context
  @@ -34,6 +35,12 @@
       private final static Resources REZ =
           ResourceManager.getPackageResources( DefaultTaskContext.class );
   
  +    // Property name validator allows digits, but no internal whitespace.
  +    private static DefaultNameValidator m_propertyNameValidator = new DefaultNameValidator();
  +    static {
  +        m_propertyNameValidator.setAllowInternalWhitespace( false );
  +    }
  +
       private final Map m_contextData = new Hashtable();
       private final TaskContext m_parent;
       private ServiceManager m_serviceManager;
  @@ -199,6 +206,7 @@
       public void setProperty( final String name, final Object value )
           throws TaskException
       {
  +        checkPropertyName( name );
           checkPropertyValid( name, value );
           m_contextData.put( name, value );
       }
  @@ -360,6 +368,22 @@
               throw new ContextException( message );
           }
           return value;
  +    }
  +
  +    /**
  +     * Checks that the supplied property name is valid.
  +     */
  +    private void checkPropertyName( final String name ) throws TaskException
  +    {
  +        try
  +        {
  +            m_propertyNameValidator.validate( name );
  +        }
  +        catch( Exception e )
  +        {
  +            String message = REZ.getString( "bad-property-name.error" );
  +            throw new TaskException( message, e );
  +        }
       }
   
       /**
  
  
  
  1.9       +1 -0      jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/Resources.properties,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Resources.properties	9 Mar 2002 02:04:26 -0000	1.8
  +++ Resources.properties	11 Mar 2002 06:07:24 -0000	1.9
  @@ -13,6 +13,7 @@
   #DefaultTaskContext
   unknown-prop.error=Unknown property {0}.
   bad-property.error=Property {0} must have a value of type {1}.
  +bad-property-name.error=Invalid property name.
   null-resolved-value.error=Value "{0}" resolved to null.
   bad-resolve.error=Unable to resolve value "{0}".
   bad-find-service.error=Could not find service "{0}".
  
  
  
  1.9       +3 -3      jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectBuilder.java
  
  Index: ProjectBuilder.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectBuilder.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ProjectBuilder.java	21 Feb 2002 11:06:42 -0000	1.8
  +++ ProjectBuilder.java	11 Mar 2002 06:07:24 -0000	1.9
  @@ -13,7 +13,7 @@
    * Interface implemented by components that build projects from sources.
    *
    * @author <a href="mailto:peter@apache.org">Peter Donald</a>
  - * @version $Revision: 1.8 $ $Date: 2002/02/21 11:06:42 $
  + * @version $Revision: 1.9 $ $Date: 2002/03/11 06:07:24 $
    * @ant:role shorthand="project-builder"
    */
   public interface ProjectBuilder
  @@ -25,8 +25,8 @@
        *
        * @param source the source
        * @return the constructed Project
  -     * @exception Exception if an error occurs
  +     * @exception ProjectException if an error occurs
        */
       Project build( String source )
  -        throws Exception;
  +        throws ProjectException;
   }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectException.java
  
  Index: ProjectException.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.interfaces.builder;
  
  /**
   * A cascading exception thrown on a problem constructing a Project model.
   *
   * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/11 06:07:24 $
   */
  public class ProjectException
      extends Exception
  {
      /**
       * If this exception is cascaded, the cause of this exception.
       */
      private final Throwable m_throwable;
  
      /**
       * Constructs an non-cascaded exception with a message
       *
       * @param message the message
       */
      public ProjectException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Constructs a cascaded exception with the supplied message, which links the
       * Throwable provided.
       *
       * @param message the message
       * @param throwable the throwable that caused this exception
       */
      public ProjectException( final String message, final Throwable throwable )
      {
          super( message );
          m_throwable = throwable;
      }
  
      /**
       * Retrieve root cause of the exception.
       *
       * @return the root cause
       */
      public final Throwable getCause()
      {
          return m_throwable;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/DefaultNameValidator.java
  
  Index: DefaultNameValidator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.interfaces.model;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  
  /**
   * Simple helper class which determines the validity of names used
   * in ant projects.
   *
   * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/11 06:07:24 $
   */
  public class DefaultNameValidator
      implements NameValidator
  {
      private final static Resources REZ =
          ResourceManager.getPackageResources( DefaultNameValidator.class );
  
      /**
       * Determines whether the supplied name may include surrounding whitespace.
       */
      private boolean m_allowSurroundingWhitespace;
  
      // Settings for initial characters.
      private boolean m_allowInitialDigit;
      private String m_additionalInitialCharacters;
  
      // Settings for internal characters.
      private boolean m_allowInternalDigits;
      private boolean m_allowInternalWhitespace;
      private String m_additionalInternalCharacters;
  
      /**
       * Construct a default name validator.
       * Letters, digits and "_" are permitted as initial character.
       * Letters, digits, whitespace and "_-." are permitted as internal characters.
       * Surrounding whitespace is not permitted.
       */
      public DefaultNameValidator()
      {
          this( false, true, "_", true, true, "_-." );
      }
  
      /**
       * Contstruct a NameValidator with the specified rules.
       * @param allowSurroundingWhitespace
       *          specified if names are trimmed before checking
       * @param allowInitialDigit
       *          specifies if digits are permitted as intial characters
       * @param additionalInitialCharacters
       *          extra characters to allow as initial characters.
       * @param allowInternalDigits
       *          specifies if digits are permitted as internal characters
       * @param allowInternalWhitespace
       *          specifies if whitespace is permitted internally in names
       * @param additionalInternalCharacters
       *          extra characters permitted in names
       */
      public DefaultNameValidator( final boolean allowSurroundingWhitespace,
                                   final boolean allowInitialDigit,
                                   final String additionalInitialCharacters,
                                   final boolean allowInternalDigits,
                                   final boolean allowInternalWhitespace,
                                   final String additionalInternalCharacters )
      {
          setAllowSurroundingWhitespace( allowSurroundingWhitespace );
          setAllowInitialDigit( allowInitialDigit );
          setAdditionalInitialCharacters( additionalInitialCharacters );
          setAllowInternalDigits( allowInternalDigits );
          setAllowInternalWhitespace( allowInternalWhitespace );
          setAdditionalInternalCharacters( additionalInternalCharacters );
      }
  
      /**
       * Creates a valid name based on the supplied string value, removing invalid
       * characters. If no valid characters are present, an exception is thrown.
       * @param baseName the name used to construct the valid name
       * @throws Exception if no valid name could be constructed.
       */
      public String makeValidName( final String baseName ) throws Exception
      {
          final StringBuffer buffer = new StringBuffer( baseName );
          while( buffer.length() > 0 && !isValidInitialChar( buffer.charAt( 0 ) ) )
          {
              buffer.delete( 0, 1 );
          }
          if( buffer.length() == 0 )
          {
              final String message = REZ.getString( "name.could-not-create.error", baseName );
              throw new Exception( message );
          }
  
          for( int i = 1; i < buffer.length(); )
          {
              if( !isValidInternalChar( buffer.charAt( i ) ) )
              {
                  buffer.delete( i, i + 1 );
              }
              else
              {
                  i++;
              }
          }
  
          return buffer.toString();
      }
  
      /**
       * Validates the supplied name, failing if it is not.
       * @throws Exception is the supplied name is not valid.
       */
      public void validate( final String name ) throws Exception
      {
          String testName = name;
  
          // If surrounding whitespace is allowed, trim it. Otherwise, check.
          if( m_allowSurroundingWhitespace )
          {
              testName = testName.trim();
          }
          else
          {
              checkSurroundingWhitespace( testName );
          }
  
          // Zero-length name is invalid.
          if( testName.length() == 0 )
          {
              final String message = REZ.getString( "name.zero-char-name.error" );
              throw new Exception( message );
          }
  
          // Check first character.
          final char initial = testName.charAt( 0 );
          checkInitialCharacter( initial, testName );
  
          // Check the rest of the characters.
          for( int i = 1; i < testName.length(); i++ )
          {
              final char internal = testName.charAt( i );
              checkInternalCharacter( internal, testName );
          }
      }
  
      /**
       * Checks if the supplied character is permitted as an internal character.
       * @throws Exception if the character is not permitted
       */
      private void checkInternalCharacter( final char internal, final String name )
          throws Exception
      {
          if( !isValidInternalChar( internal ) )
          {
              final String message = REZ.getString( "name.invalid-internal-char.error",
                                                    name,
                                                    describeValidInternalChars() );
              throw new Exception( message );
          }
      }
  
      /**
       * Checks if the supplied character is permitted as an internal character.
       * @throws Exception if the character is not permitted
       */
      private void checkInitialCharacter( final char initial, final String name )
          throws Exception
      {
          if( !isValidInitialChar( initial ) )
          {
              final String message = REZ.getString( "name.invalid-initial-char.error",
                                                    name,
                                                    describeValidInitialChars() );
              throw new Exception( message );
          }
      }
  
      /**
       * Checks the name for surrounding whitespace
       * @throws Exception if surrounding whitespace is found
       */
      private void checkSurroundingWhitespace( final String testName )
          throws Exception
      {
          if( testName.length() == 0 )
          {
              return;
          }
  
          if( Character.isWhitespace( testName.charAt( 0 ) ) ||
              Character.isWhitespace( testName.charAt( testName.length() - 1 ) ) )
          {
              final String message =
                  REZ.getString( "name.enclosing-whitespace.error", testName );
              throw new Exception( message );
          }
      }
  
      /**
       * Determines if a character is allowed as the first character in a name.
       * Valid characters are Letters, Digits, and defined initial characters ("_").
       * @param chr the character to be assessed
       * @return <code>true</code> if the character can be the first character of a name
       */
      protected boolean isValidInitialChar( final char chr )
      {
          if( Character.isLetter( chr ) )
          {
              return true;
          }
  
          if( m_allowInitialDigit
              && Character.isDigit( chr ) )
          {
              return true;
          }
  
          if( m_additionalInitialCharacters.indexOf( chr ) != -1 )
          {
              return true;
          }
  
          return false;
      }
  
      /**
       * Determines if a character is allowed as a non-initial character in a name.
       * Valid characters are Letters, Digits, whitespace, and defined
       * internal characters ("_-.").
       * @param chr the character to be assessed
       * @return <code>true</code> if the character can be included in a name
       */
      protected boolean isValidInternalChar( final char chr )
      {
          if( Character.isLetter( chr ) )
          {
              return true;
          }
  
          if( m_allowInternalDigits
              && Character.isDigit( chr ) )
          {
              return true;
          }
  
          if( m_allowInternalWhitespace
              && Character.isWhitespace( chr ) )
          {
              return true;
          }
  
          if( m_additionalInternalCharacters.indexOf( chr ) != -1 )
          {
              return true;
          }
  
          return false;
      }
  
      /**
       * Builds a message detailing the valid initial characters.
       */
      protected String describeValidInitialChars()
      {
          StringBuffer validChars = new StringBuffer( "letters" );
          if( m_allowInitialDigit )
          {
              validChars.append( ", digits" );
          }
          validChars.append( ", and \"" );
          validChars.append( m_additionalInitialCharacters );
          validChars.append( "\"" );
          return validChars.toString();
      }
  
      /**
       * Builds a message detailing the valid internal characters.
       */
      protected String describeValidInternalChars()
      {
          StringBuffer validChars = new StringBuffer( "letters" );
          if( m_allowInternalDigits )
          {
              validChars.append( ", digits" );
          }
          if( m_allowInternalWhitespace )
          {
              validChars.append( ", whitespace" );
          }
          validChars.append( ", and \"" );
          validChars.append( m_additionalInternalCharacters );
          validChars.append( "\"" );
          return validChars.toString();
      }
  
      /**
       * @param allowSurroundingWhitespace
       *          specified if names are trimmed before checking
       */
      public void setAllowSurroundingWhitespace( boolean allowSurroundingWhitespace )
      {
          m_allowSurroundingWhitespace = allowSurroundingWhitespace;
      }
  
      /**
       * @param allowInitialDigit
       *          specifies if digits are permitted as intial characters
       */
      public void setAllowInitialDigit( boolean allowInitialDigit )
      {
          m_allowInitialDigit = allowInitialDigit;
      }
  
      /**
       * @param additionalInitialCharacters
       *          extra characters to allow as initial characters.
       */
      public void setAdditionalInitialCharacters( String additionalInitialCharacters )
      {
          m_additionalInitialCharacters = additionalInitialCharacters;
      }
  
      /**
       * @param allowInternalDigits
       *          specifies if digits are permitted as internal characters
       */
      public void setAllowInternalDigits( boolean allowInternalDigits )
      {
          m_allowInternalDigits = allowInternalDigits;
      }
  
      /**
       * @param allowInternalWhitespace
       *          specifies if whitespace is permitted internally in names
       */
      public void setAllowInternalWhitespace( boolean allowInternalWhitespace )
      {
          m_allowInternalWhitespace = allowInternalWhitespace;
      }
  
      /**
       * @param additionalInternalCharacters
       *          extra characters permitted in names
       */
      public void setAdditionalInternalCharacters( String additionalInternalCharacters )
      {
          m_additionalInternalCharacters = additionalInternalCharacters;
      }
  
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java
  
  Index: NameValidator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.interfaces.model;
  
  /**
   * Determines the validity of names used in projects.
   *
   * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/11 06:07:24 $
   */
  public interface NameValidator
  {
      /**
       * Validates the supplied name, failing if it is not.
       * @throws Exception is the supplied name is not valid.
       */
      void validate( String name ) throws Exception;
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  # Name validation
  name.zero-char-name.error=Name "" is invalid, as it contains no characters.
  name.enclosing-whitespace.error=Name "{0}" is invalid, as it contains enclosing whitespace.
  name.invalid-initial-char.error=Name "{0}" is invalid, as it begins with an illegal character. Names can start with {1}.
  name.invalid-internal-char.error=Name "{0}" is invalid, as it contains an illegal character. Permitted name characters are {1}.
  name.could-not-create.error=Could not valid name from "{0}".
  
  
  
  1.4       +24 -1     jakarta-ant/proposal/myrmidon/src/testcases/org/apache/antlib/core/PropertyTest.java
  
  Index: PropertyTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/testcases/org/apache/antlib/core/PropertyTest.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- PropertyTest.java	9 Mar 2002 10:13:02 -0000	1.3
  +++ PropertyTest.java	11 Mar 2002 06:07:24 -0000	1.4
  @@ -12,12 +12,13 @@
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.myrmidon.AbstractProjectTest;
   import org.apache.myrmidon.LogMessageTracker;
  +import org.apache.myrmidon.components.workspace.DefaultTaskContext;
   
   /**
    * Test cases for <property> task.
    *
    * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
  - * @version $Revision: 1.3 $ $Date: 2002/03/09 10:13:02 $
  + * @version $Revision: 1.4 $ $Date: 2002/03/11 06:07:24 $
    */
   public class PropertyTest
       extends AbstractProjectTest
  @@ -89,6 +90,28 @@
           executeTargetExpectError( projectFile, "too-many-values1", messages );
           executeTargetExpectError( projectFile, "too-many-values2", messages );
           executeTargetExpectError( projectFile, "too-many-values3", messages );
  +    }
  +
  +    /**
  +     * Tests basic validation of property names.
  +     */
  +    public void testNameValidation() throws Exception
  +    {
  +        final File projectFile = getTestResource( "property.ant" );
  +
  +        final Resources contextResources
  +            = ResourceManager.getPackageResources( DefaultTaskContext.class );
  +
  +        // Invalid names
  +        String[] messages = new String[]
  +        {
  +            null,
  +            contextResources.getString( "bad-property-name.error" ),
  +            null
  +        };
  +        executeTargetExpectError( projectFile, "bad-prop-name1", messages );
  +        executeTargetExpectError( projectFile, "bad-prop-name2", messages );
  +        executeTargetExpectError( projectFile, "bad-prop-name3", messages );
       }
   
   }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/builder/DefaultProjectBuilderTest.java
  
  Index: DefaultProjectBuilderTest.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.components.builder;
  
  import java.io.File;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.myrmidon.AbstractMyrmidonTest;
  
  /**
   * Test cases for {@link DefaultProjectBuilder}.
   *
   * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/11 06:07:24 $
   */
  public class DefaultProjectBuilderTest
      extends AbstractMyrmidonTest
  {
      private final static Resources REZ
          = ResourceManager.getPackageResources( DefaultProjectBuilder.class );
  
      private DefaultProjectBuilder m_builder;
  
      public DefaultProjectBuilderTest( String name )
      {
          super( name );
      }
  
      protected void setUp() throws Exception
      {
          super.setUp();
          m_builder = new DefaultProjectBuilder();
          m_builder.enableLogging( createLogger() );
      }
  
      /**
       * Test validation of project and target names.
       */
      public void testNameValidation() throws Exception
      {
          // Check bad project name
          final File badProjectFile = getTestResource( "bad-project-name.ant" );
          try
          {
              m_builder.build( badProjectFile.getAbsolutePath() );
              fail();
          }
          catch( Exception e )
          {
              assertSameMessage( REZ.getString( "ant.project-bad-name.error" ), e );
          }
  
          // Check bad target name
          final File badTargetFile = getTestResource( "bad-target-name.ant" );
          try
          {
              m_builder.build( badTargetFile.getAbsolutePath() );
              fail();
          }
          catch( Exception e )
          {
              // TODO - check error message
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/model/DefaultNameValidatorTest.java
  
  Index: DefaultNameValidatorTest.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.interfaces.model;
  
  import org.apache.myrmidon.AbstractMyrmidonTest;
  
  /**
   * TestCases for {@link DefaultNameValidator}.
   *
   * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/11 06:07:24 $
   */
  public class DefaultNameValidatorTest
      extends AbstractMyrmidonTest
  {
      private DefaultNameValidator m_validator = new DefaultNameValidator();
  
      public DefaultNameValidatorTest( String name )
      {
          super( name );
      }
  
      /**
       * Test valid names for the default validator.
       */
      public void testValidNames() throws Exception
      {
          testValid( "aName" );
          testValid( "123456" );
          testValid( "s p     a ce s" );
          testValid( "d-a-s-h-e-s-" );
          testValid( "d.o.t.s." );
          testValid( "_u_n_d_e_r_s_c_o_r_e_s" );
          testValid( "a" );
          testValid( "1" );
          testValid( "_" );
  
      }
  
      /**
       * Test invalid names for the default validator.
       */
      public void testInvalidNames() throws Exception
      {
          testInvalid( "" );
          testInvalid( " " );
          testInvalid( "           " );
          testInvalid( " bad" );
          testInvalid( "bad " );
          testInvalid( " bad " );
          testInvalid( "-dashfirst" );
          testInvalid( ".dotfirst" );
          testInvalid( "question?" );
      }
  
      /**
       * Test that certain characters are disallowed in the default validator.
       */
      public void testReservedChars() throws Exception
      {
          String reserved = "!@#$%^&*()+=~`{}[]|\\/?<>,:;";
  
          for( int pos = 0; pos < reserved.length(); pos++ )
          {
              char chr = reserved.charAt( pos );
              testReservedChar( chr );
          }
      }
  
      private void testReservedChar( char chr ) throws Exception
      {
          String test = "a" + String.valueOf( chr );
          testInvalid( test );
      }
  
      /**
       * Test validation using a restrictive set of validation rules.
       */
      public void testStrictNames() throws Exception
      {
          m_validator = new DefaultNameValidator( false, false, "", false, false, "." );
  
          testValid( "name" );
          testValid( "a" );
          testValid( "yep.ok" );
  
          testInvalid( "_nogood" );
          testInvalid( "no_good" );
          testInvalid( "nope1" );
          testInvalid( "123" );
          testInvalid( "not ok" );
      }
  
      private void testValid( String name )
      {
          try
          {
              m_validator.validate( name );
          }
          catch( Exception e )
          {
              fail( e.getMessage() );
          }
      }
  
      private void testInvalid( String name )
      {
          try
          {
              m_validator.validate( name );
              fail( "Name \"" + name + "\" should be invalid." );
          }
          catch( Exception e )
          {
          }
      }
  }
  
  
  
  1.8       +0 -6      jakarta-ant/proposal/myrmidon/src/xdocs/todo.xml
  
  Index: todo.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/xdocs/todo.xml,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- todo.xml	9 Mar 2002 10:31:31 -0000	1.7
  +++ todo.xml	11 Mar 2002 06:07:24 -0000	1.8
  @@ -209,12 +209,6 @@
                       <li>Fire ProjectListener events projectStarted() and projectFinished()
                       events on start and finish of referenced projects, adding indicator methods
                       to ProjectEvent.</li>
  -                    <li>Validate project and target names in DefaultProjectBuilder - reject dodgy
  -                    names like "," or "", or "  ".  Probably want to reject names that start or
  -                    end with white-space (though internal whitespace is probably fine).  We also
  -                    want to reserve certain punctuation characters like , : ? $ [ ] { } &lt; &gt;, etc for
  -                    future use.</li>
  -                    <li>Similarly, validate property names, using the same rules.</li>
                       <li>Detect duplicate type names.</li>
                       <li>Add fully qualified type names, based on antlib name and type shorthand name.
                       Allow these to be used in build files in addition to the shorthand names.</li>
  
  
  

--
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