mirror of https://github.com/apache/archiva.git
Fixing entity reader.
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-jpox-database-refactor@525280 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
74cb10586c
commit
936fe55580
|
@ -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;
|
||||
|
|
|
@ -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]+\\;" );
|
||||
}
|
||||
|
||||
public int read( char[] cbuf, int off, int len )
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
char tmpbuf[] = new char[cbuf.length];
|
||||
int count = this.originalReader.read( tmpbuf, off, len );
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
|
||||
return count;
|
||||
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;
|
||||
}
|
||||
|
||||
private StringBuffer getExpandedBuffer( int minimum_length )
|
||||
throws IOException
|
||||
{
|
||||
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()
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<basic>
|
||||
<names>
|
||||
<name>Trygve Laugstøl</name>
|
||||
<name>The ∞ Archiva</name>
|
||||
</names>
|
||||
</basic>
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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( "©" ) );
|
||||
assertEquals( "∞", LatinEntities.resolveEntity( "∞" ) );
|
||||
assertEquals( "ø", LatinEntities.resolveEntity( "ø" ) );
|
||||
|
||||
// Bad Entities.
|
||||
assertEquals( "", LatinEntities.resolveEntity( "" ) );
|
||||
assertEquals( "&", LatinEntities.resolveEntity( "&" ) );
|
||||
assertEquals( null, LatinEntities.resolveEntity( 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 );
|
||||
}
|
||||
}
|
|
@ -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() );
|
||||
|
|
Loading…
Reference in New Issue