]> source.dussan.org Git - archiva.git/commitdiff
Fixing entity reader.
authorJoakim Erdfelt <joakime@apache.org>
Tue, 3 Apr 2007 21:17:42 +0000 (21:17 +0000)
committerJoakim Erdfelt <joakime@apache.org>
Tue, 3 Apr 2007 21:17:42 +0000 (21:17 +0000)
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches@525280 13f79535-47bb-0310-9956-ffa450edef68

archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/main/java/org/apache/maven/archiva/xml/LatinEntities.java
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/main/java/org/apache/maven/archiva/xml/LatinEntityResolutionReader.java
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/examples/no-prolog-with-entities.xml-resolved [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/AbstractArchivaXmlTestCase.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntitiesTest.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntityResolutionReaderTest.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/XMLReaderTest.java

index 9db17993c148be96c6732e7402b933b8e9d7644c..c8349000125a0d29a9fc6f99b4e1852542e40b40 100644 (file)
@@ -298,7 +298,25 @@ public class LatinEntities
 
     public static String resolveEntity( String entity )
     {
-        String result = (String) defaultEntityMap.get( entity );
+        if ( entity == null )
+        {
+            // Invalid. null.
+            return entity;
+        }
+
+        if ( entity.trim().length() <= 0 )
+        {
+            // Invalid. empty.
+            return entity;
+        }
+
+        if ( !( entity.charAt( 0 ) == '&' ) && ( entity.charAt( entity.length() ) == ';' ) )
+        {
+            // Invalid, not an entity.
+            return entity;
+        }
+
+        String result = (String) defaultEntityMap.get( entity.substring( 1, entity.length() - 1 ) );
         if ( result == null )
         {
             return entity;
index e2fef0468b8885fc120943030cd205cb720dfeeb..d1f75612d668665399da5082420bfd810cba2035 100644 (file)
@@ -21,11 +21,12 @@ package org.apache.maven.archiva.xml;
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.PushbackReader;
 import java.io.Reader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
- * LatinEntityResolutionReader 
+ * LatinEntityResolutionReader - Read a Character Stream.
  *
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  * @version $Id$
@@ -33,23 +34,152 @@ import java.io.Reader;
 public class LatinEntityResolutionReader
     extends Reader
 {
-    private PushbackReader originalReader;
+    private BufferedReader originalReader;
+
+    private char leftover[];
+
+    private Pattern entityPattern;
 
     public LatinEntityResolutionReader( Reader reader )
     {
-        this.originalReader = new PushbackReader( reader );
+        this.originalReader = new BufferedReader( reader );
+        this.entityPattern = Pattern.compile( "\\&[a-zA-Z]+\\;" );
+    }
+
+    /**
+     * Read characters into a portion of an array. This method will block until some input is available, 
+     * an I/O error occurs, or the end of the stream is reached.
+     * 
+     * @param destbuf Destination buffer
+     * @param offset Offset (in destination buffer) at which to start storing characters
+     * @param length Maximum number of characters to read
+     * @return The number of characters read, or -1 if the end of the stream has been reached
+     * @throws IOException if an I/O error occurs.
+     */
+    public int read( char[] destbuf, int offset, int length )
+        throws IOException
+    {
+        int tmp_length;
+        int current_requested_offset = offset;
+        int current_requested_length = length;
+
+        // Drain leftover from last read request.
+        if ( leftover != null )
+        {
+            if ( leftover.length > length )
+            {
+                // Copy partial leftover.
+                System.arraycopy( leftover, 0, destbuf, current_requested_offset, length );
+
+                // Create new leftover of remaining.
+                char tmp[] = new char[length];
+                System.arraycopy( leftover, length, tmp, 0, length );
+                leftover = new char[tmp.length];
+                System.arraycopy( tmp, 0, leftover, 0, length );
+
+                // Return len
+                return length;
+            }
+            else
+            {
+                tmp_length = leftover.length;
+
+                // Copy full leftover
+                System.arraycopy( leftover, 0, destbuf, current_requested_offset, tmp_length );
+
+                // Empty out leftover (as there is now none left)
+                leftover = null;
+
+                // Adjust offset and lengths.
+                current_requested_offset += tmp_length;
+                current_requested_length -= tmp_length;
+            }
+        }
+
+        StringBuffer sbuf = getExpandedBuffer( current_requested_length );
+
+        // Have we reached the end of the buffer?
+        if ( sbuf == null )
+        {
+            // Do we have content?
+            if ( current_requested_offset > offset )
+            {
+                // Signal that we do, by calculating length.
+                return ( current_requested_offset - offset );
+            }
+
+            // No content. signal end of buffer.
+            return -1;
+        }
+
+        // Copy from expanded buf whatever length we can accomodate.
+        tmp_length = Math.min( sbuf.length(), current_requested_length );
+        sbuf.getChars( 0, tmp_length, destbuf, current_requested_offset );
+
+        // Create the leftover (if any)
+        if ( tmp_length < sbuf.length() )
+        {
+            leftover = new char[sbuf.length() - tmp_length];
+            sbuf.getChars( tmp_length, tmp_length + leftover.length, leftover, 0 );
+        }
+
+        // Calculate Actual Length and return.
+        return ( current_requested_offset - offset ) + tmp_length;
     }
 
-    public int read( char[] cbuf, int off, int len )
+    private StringBuffer getExpandedBuffer( int minimum_length )
         throws IOException
     {
-        char tmpbuf[] = new char[cbuf.length];
-        int count = this.originalReader.read( tmpbuf, off, len );
-        
-        StringBuffer sb = new StringBuffer();
-        
-        
-        return count;
+        StringBuffer buf = null;
+        String line = this.originalReader.readLine();
+        boolean done = ( line == null );
+
+        while ( !done )
+        {
+            if ( buf == null )
+            {
+                buf = new StringBuffer();
+            }
+
+            buf.append( expandLine( line ) );
+
+            // Add newline only if there is more data.
+            if ( this.originalReader.ready() )
+            {
+                buf.append( "\n" );
+            }
+
+            if ( buf.length() > minimum_length )
+            {
+                done = true;
+            }
+            else
+            {
+                line = this.originalReader.readLine();
+                done = ( line == null );
+            }
+        }
+
+        return buf;
+    }
+
+    private String expandLine( String line )
+    {
+        StringBuffer ret = new StringBuffer();
+
+        int offset = 0;
+        String entity;
+        Matcher mat = this.entityPattern.matcher( line );
+        while ( mat.find() )
+        {
+            ret.append( line.substring( offset, mat.start() ) );
+            entity = mat.group();
+            ret.append( LatinEntities.resolveEntity( entity ) );
+            offset += mat.start() + entity.length();
+        }
+        ret.append( line.substring( offset ) );
+
+        return ret.toString();
     }
 
     public void close()
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/examples/no-prolog-with-entities.xml-resolved b/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/examples/no-prolog-with-entities.xml-resolved
new file mode 100644 (file)
index 0000000..c6fd401
--- /dev/null
@@ -0,0 +1,6 @@
+<basic>
+  <names>
+    <name>Trygve Laugstøl</name>
+    <name>The ∞ Archiva</name>
+  </names>
+</basic>
\ No newline at end of file
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/AbstractArchivaXmlTestCase.java b/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/AbstractArchivaXmlTestCase.java
new file mode 100644 (file)
index 0000000..25a9f62
--- /dev/null
@@ -0,0 +1,51 @@
+package org.apache.maven.archiva.xml;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+/**
+ * AbstractArchivaXmlTestCase 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class AbstractArchivaXmlTestCase
+    extends TestCase
+{
+
+    protected File getExampleXml( String filename )
+    {
+        File examplesDir = new File( "src/test/examples" );
+        if ( !examplesDir.exists() )
+        {
+            fail( "Missing the examples directory: " + examplesDir.getAbsolutePath() );
+        }
+        File exampleFile = new File( examplesDir, filename );
+        if ( !exampleFile.exists() )
+        {
+            fail( "Missing the example xml file: " + exampleFile.getAbsolutePath() );
+        }
+        return exampleFile;
+    }
+
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntitiesTest.java b/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntitiesTest.java
new file mode 100644 (file)
index 0000000..c2424f3
--- /dev/null
@@ -0,0 +1,45 @@
+package org.apache.maven.archiva.xml;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.TestCase;
+
+/**
+ * LatinEntitiesTest 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class LatinEntitiesTest
+    extends TestCase
+{
+    public void testResolveEntity()
+    {
+        // Good Entities.
+        assertEquals( "©", LatinEntities.resolveEntity( "&copy;" ) );
+        assertEquals( "∞", LatinEntities.resolveEntity( "&infin;" ) );
+        assertEquals( "ø", LatinEntities.resolveEntity( "&oslash;" ) );
+
+        // Bad Entities.
+        assertEquals( "", LatinEntities.resolveEntity( "" ) );
+        assertEquals( "&amp;", LatinEntities.resolveEntity( "&amp;" ) );
+        assertEquals( null, LatinEntities.resolveEntity( null ) );
+    }
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntityResolutionReaderTest.java b/archiva-jpox-database-refactor/archiva-base/archiva-xml-tools/src/test/java/org/apache/maven/archiva/xml/LatinEntityResolutionReaderTest.java
new file mode 100644 (file)
index 0000000..0d38c68
--- /dev/null
@@ -0,0 +1,141 @@
+package org.apache.maven.archiva.xml;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+
+/**
+ * LatinEntityResolutionReaderTest 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class LatinEntityResolutionReaderTest
+    extends AbstractArchivaXmlTestCase
+{
+    /**
+     * A method to obtain the content of a reader as a String,
+     * while allowing for specifing the buffer size of the operation.
+     * 
+     * This method is only really useful for testing a Reader implementation.
+     * 
+     * @param input the reader to get the input from.
+     * @param bufsize the buffer size to use.
+     * @return the contents of the reader as a String.
+     * @throws IOException if there was an I/O error.
+     */
+    private String toStringFromReader( Reader input, int bufsize )
+        throws IOException
+    {
+        StringWriter output = new StringWriter();
+
+        final char[] buffer = new char[bufsize];
+        int n = 0;
+        while ( -1 != ( n = input.read( buffer ) ) )
+        {
+            output.write( buffer, 0, n );
+        }
+        output.flush();
+
+        return output.toString();
+    }
+
+    /**
+     * This reads a text file from the src/test/examples directory,
+     * normalizes the end of lines, and returns the contents as a big String.
+     * 
+     * @param examplePath the name of the file in the src/test/examples directory.
+     * @return the contents of the provided file
+     * @throws IOException if there was an I/O error.
+     */
+    private String toStringFromExample( String examplePath )
+        throws IOException
+    {
+        File exampleFile = getExampleXml( examplePath );
+        FileReader fileReader = new FileReader( exampleFile );
+        BufferedReader lineReader = new BufferedReader( fileReader );
+        StringBuffer sb = new StringBuffer();
+
+        boolean hasContent = false;
+
+        String line = lineReader.readLine();
+        while ( line != null )
+        {
+            if ( hasContent )
+            {
+                sb.append( "\n" );
+            }
+            sb.append( line );
+            hasContent = true;
+            line = lineReader.readLine();
+        }
+
+        return sb.toString();
+    }
+
+    public void assertProperRead( String sourcePath, String expectedPath, int bufsize )
+    {
+        try
+        {
+            File inputFile = getExampleXml( sourcePath );
+
+            FileReader fileReader = new FileReader( inputFile );
+            LatinEntityResolutionReader testReader = new LatinEntityResolutionReader( fileReader );
+
+            String actualOutput = toStringFromReader( testReader, bufsize );
+            String expectedOutput = toStringFromExample( expectedPath );
+
+            assertEquals( expectedOutput, actualOutput );
+        }
+        catch ( IOException e )
+        {
+            fail( "IOException: " + e.getMessage() );
+        }
+    }
+
+    public void testReaderNormalBufsize()
+        throws IOException
+    {
+        assertProperRead( "no-prolog-with-entities.xml", "no-prolog-with-entities.xml-resolved", 4096 );
+    }
+
+    public void testReaderSmallBufsize()
+        throws IOException
+    {
+        assertProperRead( "no-prolog-with-entities.xml", "no-prolog-with-entities.xml-resolved", 1024 );
+    }
+
+    public void testReaderRediculouslyTinyBufsize()
+        throws IOException
+    {
+        assertProperRead( "no-prolog-with-entities.xml", "no-prolog-with-entities.xml-resolved", 32 );
+    }
+
+    public void testReaderHugeBufsize()
+        throws IOException
+    {
+        assertProperRead( "no-prolog-with-entities.xml", "no-prolog-with-entities.xml-resolved", 409600 );
+    }
+}
index 44f73e4e960723db1d9011488321e885bb065caf..b02daeca30a0a92f9f75c5ea2092d23d48408a21 100644 (file)
@@ -26,8 +26,6 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import junit.framework.TestCase;
-
 /**
  * XMLReaderTest 
  *
@@ -35,23 +33,8 @@ import junit.framework.TestCase;
  * @version $Id$
  */
 public class XMLReaderTest
-    extends TestCase
+    extends AbstractArchivaXmlTestCase
 {
-    private File getExampleXml( String filename )
-    {
-        File examplesDir = new File( "src/test/examples" );
-        if ( !examplesDir.exists() )
-        {
-            fail( "Missing the examples directory: " + examplesDir.getAbsolutePath() );
-        }
-        File exampleFile = new File( examplesDir, filename );
-        if ( !exampleFile.exists() )
-        {
-            fail( "Missing the example xml file: " + exampleFile.getAbsolutePath() );
-        }
-        return exampleFile;
-    }
-
     private void assertElementTexts( List elementList, String[] expectedTexts )
     {
         assertEquals( "Element List Size", expectedTexts.length, elementList.size() );