avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From blorit...@apache.org
Subject cvs commit: jakarta-avalon/src/test/org/apache/avalon/framework/configuration/test DefaultConfigurationBuilderTestCase.java
Date Mon, 06 May 2002 19:23:04 GMT
bloritsch    02/05/06 12:23:04

  Modified:    src/java/org/apache/avalon/framework/configuration
                        DefaultConfigurationBuilder.java
                        SAXConfigurationHandler.java
               src/test/org/apache/avalon/framework/configuration/test
                        DefaultConfigurationBuilderTestCase.java
  Log:
  Apply patch from Leo for config object building
  
  Revision  Changes    Path
  1.15      +8 -0      jakarta-avalon/src/java/org/apache/avalon/framework/configuration/DefaultConfigurationBuilder.java
  
  Index: DefaultConfigurationBuilder.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon/src/java/org/apache/avalon/framework/configuration/DefaultConfigurationBuilder.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- DefaultConfigurationBuilder.java	21 Mar 2002 14:51:13 -0000	1.14
  +++ DefaultConfigurationBuilder.java	6 May 2002 19:23:04 -0000	1.15
  @@ -43,6 +43,14 @@
    *  Configuration#getNamespace getNamespace()}.equals("http://foo.com")</code>.
    *  </li>
    * </ul>
  + * <p>
  + * Whitespace handling. Since mixed content is not allowed in the
  + * configurations, whitespace is completely discarded in non-leaf nodes.
  + * For the leaf nodes the default behavior is to trim the space
  + * surrounding the value. This can be changed by specifying
  + * <code>xml:space</code> attribute with value of <code>preserve</code>
  + * in that case the whitespace is left intact.
  + * </p>
    *
    * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
    * @author <a href="mailto:peter@apache.org">Peter Donald</a>
  
  
  
  1.17      +75 -42    jakarta-avalon/src/java/org/apache/avalon/framework/configuration/SAXConfigurationHandler.java
  
  Index: SAXConfigurationHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon/src/java/org/apache/avalon/framework/configuration/SAXConfigurationHandler.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- SAXConfigurationHandler.java	6 May 2002 10:46:57 -0000	1.16
  +++ SAXConfigurationHandler.java	6 May 2002 19:23:04 -0000	1.17
  @@ -14,21 +14,32 @@
   import org.xml.sax.SAXException;
   import org.xml.sax.SAXParseException;
   import org.xml.sax.helpers.DefaultHandler;
  +import java.util.BitSet;
   
   /**
    * A SAXConfigurationHandler helps build Configurations out of sax events.
    *
    * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
    * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
  - * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
    */
   public class SAXConfigurationHandler
       extends DefaultHandler
       implements ErrorHandler
   {
  -    private final ArrayList              m_elements        = new ArrayList();
  -    private Configuration                m_configuration;
  -    private Locator                      m_locator;
  +    /**
  +     * Likely number of nested configuration items. If more is
  +     * encountered the lists will grow automatically.
  +     */
  +    private final static int EXPECTED_DEPTH  = 5;
  +    private final ArrayList m_elements       = new ArrayList(EXPECTED_DEPTH);
  +    private final ArrayList m_values         = new ArrayList(EXPECTED_DEPTH);
  +    /**
  +     * Contains true at index n if space in the configuration with
  +     * depth n is to be preserved.
  +     */
  +    private final BitSet     m_preserveSpace = new BitSet();
  +    private Configuration    m_configuration;
  +    private Locator          m_locator;
   
       /**
        * Get the configuration object that was built.
  @@ -46,6 +57,7 @@
       public void clear()
       {
           m_elements.clear();
  +        m_values.clear();
           m_locator = null;
       }
   
  @@ -70,18 +82,13 @@
       public void characters( final char[] ch, int start, int end )
           throws SAXException
       {
  -        String value = new String( ch, start, end );
  -
  -        if( value.equals( "" ) )
  -        {
  -            return;
  -        }
  -
  -        final DefaultConfiguration configuration =
  -            (DefaultConfiguration)m_elements.get( m_elements.size() - 1 );
  -
  -        value = configuration.getValue( "" ) + value;
  -        configuration.setValue( value );
  +        // it is possible to play micro-optimization here by doing
  +        // manual trimming and thus preserve some precious bits
  +        // of memory, but it's really not important enough to justify
  +        // resulting code complexity
  +        final int depth = m_values.size() - 1;
  +        final StringBuffer valueBuffer = (StringBuffer) m_values.get( depth );
  +        valueBuffer.append( ch, start, end );
       }
   
       /**
  @@ -97,37 +104,41 @@
                               final String rawName )
           throws SAXException
       {
  -        final int location = m_elements.size() - 1;
  -        final DefaultConfiguration object = (DefaultConfiguration) m_elements.remove( location
);
  -
  -        // Check for validity
  -        if ( object.getValue( null ) != null && object.getChildCount() > 0 )

  +        final int depth = m_elements.size() - 1;
  +        final DefaultConfiguration finishedConfiguration =
  +            (DefaultConfiguration) m_elements.remove( depth );
  +        final String accumulatedValue = 
  +            ((StringBuffer) m_values.remove( depth )).toString();
  +        
  +        if( finishedConfiguration.getChildren().length == 0 )
           {
  -            // Could be invalid - the configuration has children and a value.
  -            // It is valid, however, to have a value consisting of just whitespace.
  -            // So let's trim the value, and see if we can resolve the conflict that way.
  -            if ( object.getValue("").trim().equals("") )
  +            // leaf node
  +            String finishedValue;
  +            if( m_preserveSpace.get(depth) )
               {
  -                // Resolved!
  -                object.setValue( null );
  +                finishedValue = accumulatedValue;
               }
  -            else 
  +            else
               {
  -                throw new SAXException( "Not allowed to define mixed content in the " +
  -                                        "element " + object.getName() + " at " +
  -                                        object.getLocation() );
  +                finishedValue = accumulatedValue.trim();
               }
  +            finishedConfiguration.setValue( finishedValue );
           }
  -        
  -        if( 0 == location )
  +        else
           {
  -            m_configuration = object;
  -            final String value = m_configuration.getValue( null );
  -            if( null != value )
  +            final String trimmedValue = accumulatedValue.trim();
  +            if( trimmedValue.length() > 0 )
               {
  -                ((DefaultConfiguration)m_configuration).setValue( value.trim() );
  +                throw new SAXException( "Not allowed to define mixed content in the " +
  +                                        "element " + finishedConfiguration.getName() +
" at " +
  +                                        finishedConfiguration.getLocation() );
               }
           }
  +
  +        if( 0 == depth )
  +        {
  +            m_configuration = finishedConfiguration;
  +        }
       }
   
       /**
  @@ -161,17 +172,22 @@
       {
           final DefaultConfiguration configuration =
               createConfiguration( rawName, getLocationString() );
  -        final int size = m_elements.size() - 1;
  +        // depth of new configuration (not decrementing here, configuration
  +        // is to be added)
  +        final int depth = m_elements.size();
  +        boolean preserveSpace = false; // top level element trims space by default
   
  -        if( size > -1 )
  +        if( depth > 0 )
           {
               final DefaultConfiguration parent =
  -                (DefaultConfiguration)m_elements.get( size );
  -
  +                (DefaultConfiguration)m_elements.get( depth - 1 );
               parent.addChild( configuration );
  +             // inherits parent's space preservation policy
  +            preserveSpace = m_preserveSpace.get( depth - 1 );
           }
   
           m_elements.add( configuration );
  +        m_values.add( new StringBuffer() );
   
           final int attributesSize = attributes.getLength();
   
  @@ -179,7 +195,24 @@
           {
               final String name = attributes.getQName( i );
               final String value = attributes.getValue( i );
  -            configuration.setAttribute( name, value );
  +
  +            if( ! name.equals( "xml:space" ))
  +            {
  +                configuration.setAttribute( name, value );
  +            }
  +            else
  +            {
  +                preserveSpace = value.equals( "preserve" );
  +            }
  +        }
  +
  +        if( preserveSpace )
  +        {
  +            m_preserveSpace.set( depth );
  +        }
  +        else
  +        {
  +            m_preserveSpace.clear( depth );
           }
       }
   
  
  
  
  1.5       +62 -2     jakarta-avalon/src/test/org/apache/avalon/framework/configuration/test/DefaultConfigurationBuilderTestCase.java
  
  Index: DefaultConfigurationBuilderTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon/src/test/org/apache/avalon/framework/configuration/test/DefaultConfigurationBuilderTestCase.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DefaultConfigurationBuilderTestCase.java	6 May 2002 10:46:57 -0000	1.4
  +++ DefaultConfigurationBuilderTestCase.java	6 May 2002 19:23:04 -0000	1.5
  @@ -7,14 +7,15 @@
    */
   package org.apache.avalon.framework.configuration.test;
   
  +import java.io.ByteArrayInputStream;
   import java.io.File;
   import java.io.FileWriter;
  -import java.io.IOException;
  -import java.util.List;
  +import java.io.InputStream;
   import junit.framework.TestCase;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  +import org.xml.sax.SAXException;
   
   /**
    * Test that the <code>Configuration</code>s built by
  @@ -336,5 +337,64 @@
           simpleAssertionsNS( conf );
           conf = m_nsBuilder.buildFromFile( m_nsFile );
           nsAssertions( conf );
  +    }
  +
  +    private final String spaceTrimmingCheckXML =
  +        "<?xml version=\"1.0\" ?>"+
  +        " <config>"+
  +        "   <trimmed-item>\n"+
  +        "    value     \n"+
  +        "   </trimmed-item>\n"+
  +        "   <preserved-item xml:space='preserve'>\n"+
  +        " a space&#13; a CR, then a trailing space </preserved-item>\n"+
  +        "   <first-level-item xml:space='preserve'>\n"+
  +        "      <second-level-preserved> whitespace around </second-level-preserved>\n"+
  +        "   </first-level-item>\n"+
  +        "   <trimmed-again-item>\n"+
  +        "    value     \n"+
  +        "   </trimmed-again-item>\n"+
  +        "</config>";
  +    
  +    /**
  +     * Checks that whitespace is normally stripped but preserved if
  +     * space preserving processing instructions are present.
  +     */
  +    public void testSpaceTrimming()
  +        throws Exception
  +    {
  +        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
  +        InputStream in = new ByteArrayInputStream( spaceTrimmingCheckXML.getBytes() );
  +        Configuration conf = builder.build( in );
  +        assertEquals( "Value is trimmed by default",
  +                      "value",
  +                      conf.getChild( "trimmed-item" ).getValue() );
  +        assertEquals( "After trimming turned off value is preserved",
  +                      "\n a space\r a CR, then a trailing space ",
  +                      conf.getChild( "preserved-item" ).getValue() );
  +        assertEquals( "Trimming two levels deep works too",
  +                      " whitespace around ",
  +                      conf.getChild( "first-level-item" )
  +                      .getChild( "second-level-preserved" ).getValue() );
  +        assertEquals( "Trimming turned back on",
  +                      "value",
  +                      conf.getChild( "trimmed-again-item" ).getValue() );
  +    }
  +
  +    
  +    private final String mixedContentXML =
  +        "<?xml version=\"1.0\" ?>"+
  +        "<a>a<a/></a>"
  +        ;
  +    public void testMixedContentDetection()
  +        throws Exception
  +    {
  +        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
  +        InputStream in = new ByteArrayInputStream( mixedContentXML.getBytes() );
  +        try
  +        {
  +            builder.build( in );
  +            fail ("Must fail on mixed content");
  +        } catch ( SAXException e )
  +        {}
       }
   }
  
  
  

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


Mime
View raw message