git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-jpox-database-refactor@525280 13f79535-47bb-0310-9956-ffa450edef68tags/archiva-1.0-alpha-1
@@ -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]+\\;" ); | |||
} | |||
/** | |||
* 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() |
@@ -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() ); |