1 package org.apache.archiva.xml;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
29 * LatinEntityResolutionReader - Read a Character Stream.
33 public class LatinEntityResolutionReader
36 private BufferedReader originalReader;
38 private char leftover[];
40 private Pattern entityPattern;
42 public LatinEntityResolutionReader( Reader reader )
44 this.originalReader = new BufferedReader( reader );
45 this.entityPattern = Pattern.compile( "\\&[a-zA-Z]+\\;" );
49 * Read characters into a portion of an array. This method will block until some input is available,
50 * an I/O error occurs, or the end of the stream is reached.
52 * @param destbuf Destination buffer
53 * @param offset Offset (in destination buffer) at which to start storing characters
54 * @param length Maximum number of characters to read
55 * @return The number of characters read, or -1 if the end of the stream has been reached
56 * @throws IOException if an I/O error occurs.
58 public int read( char[] destbuf, int offset, int length )
62 int currentRequestedOffset = offset;
63 int currentRequestedLength = length;
65 // Drain leftover from last read request.
66 if ( leftover != null )
68 if ( leftover.length > length )
70 // Copy partial leftover.
71 System.arraycopy( leftover, 0, destbuf, currentRequestedOffset, length );
72 int copyLeftOverLength = leftover.length - length;
74 // Create new leftover of remaining.
75 char tmp[] = new char[copyLeftOverLength];
76 System.arraycopy( leftover, length, tmp, 0, copyLeftOverLength );
77 leftover = new char[tmp.length];
78 System.arraycopy( tmp, 0, leftover, 0, copyLeftOverLength );
85 tmpLength = leftover.length;
88 System.arraycopy( leftover, 0, destbuf, currentRequestedOffset, tmpLength );
90 // Empty out leftover (as there is now none left)
93 // Adjust offset and lengths.
94 currentRequestedOffset += tmpLength;
95 currentRequestedLength -= tmpLength;
99 StringBuilder sbuf = getExpandedBuffer( currentRequestedLength );
101 // Have we reached the end of the buffer?
104 // Do we have content?
105 if ( currentRequestedOffset > offset )
107 // Signal that we do, by calculating length.
108 return ( currentRequestedOffset - offset );
111 // No content. signal end of buffer.
115 // Copy from expanded buf whatever length we can accomodate.
116 tmpLength = Math.min( sbuf.length(), currentRequestedLength );
117 sbuf.getChars( 0, tmpLength, destbuf, currentRequestedOffset );
119 // Create the leftover (if any)
120 if ( tmpLength < sbuf.length() )
122 leftover = new char[sbuf.length() - tmpLength];
123 sbuf.getChars( tmpLength, tmpLength + leftover.length, leftover, 0 );
126 // Calculate Actual Length and return.
127 return ( currentRequestedOffset - offset ) + tmpLength;
130 private StringBuilder getExpandedBuffer( int minimum_length )
133 StringBuilder buf = null;
134 String line = this.originalReader.readLine();
135 boolean done = ( line == null );
141 buf = new StringBuilder();
144 buf.append( expandLine( line ) );
146 // Add newline only if there is more data.
147 if ( this.originalReader.ready() )
152 if ( buf.length() > minimum_length )
158 line = this.originalReader.readLine();
159 done = ( line == null );
166 private String expandLine( String line )
168 StringBuilder ret = new StringBuilder();
172 Matcher mat = this.entityPattern.matcher( line );
173 while ( mat.find( offset ) )
175 ret.append( line.substring( offset, mat.start() ) );
176 entity = mat.group();
177 ret.append( LatinEntities.resolveEntity( entity ) );
178 offset = mat.start() + entity.length();
180 ret.append( line.substring( offset ) );
182 return ret.toString();
188 this.originalReader.close();