]> source.dussan.org Git - archiva.git/blob
9b62ee4124c4eb3a8dbd03fdce21d14f7c71899d
[archiva.git] /
1 package org.apache.archiva.xml;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
27
28 /**
29  * LatinEntityResolutionReader - Read a Character Stream.
30  *
31  *
32  */
33 public class LatinEntityResolutionReader
34     extends Reader
35 {
36     private BufferedReader originalReader;
37
38     private char leftover[];
39
40     private Pattern entityPattern;
41
42     public LatinEntityResolutionReader( Reader reader )
43     {
44         this.originalReader = new BufferedReader( reader );
45         this.entityPattern = Pattern.compile( "\\&[a-zA-Z]+\\;" );
46     }
47
48     /**
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.
51      * 
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.
57      */
58     public int read( char[] destbuf, int offset, int length )
59         throws IOException
60     {
61         int tmpLength;
62         int currentRequestedOffset = offset;
63         int currentRequestedLength = length;
64
65         // Drain leftover from last read request.
66         if ( leftover != null )
67         {
68             if ( leftover.length > length )
69             {
70                 // Copy partial leftover.
71                 System.arraycopy( leftover, 0, destbuf, currentRequestedOffset, length );
72                 int copyLeftOverLength = leftover.length - length;
73
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 );
79
80                 // Return len
81                 return length;
82             }
83             else
84             {
85                 tmpLength = leftover.length;
86
87                 // Copy full leftover
88                 System.arraycopy( leftover, 0, destbuf, currentRequestedOffset, tmpLength );
89
90                 // Empty out leftover (as there is now none left)
91                 leftover = null;
92
93                 // Adjust offset and lengths.
94                 currentRequestedOffset += tmpLength;
95                 currentRequestedLength -= tmpLength;
96             }
97         }
98
99         StringBuilder sbuf = getExpandedBuffer( currentRequestedLength );
100
101         // Have we reached the end of the buffer?
102         if ( sbuf == null )
103         {
104             // Do we have content?
105             if ( currentRequestedOffset > offset )
106             {
107                 // Signal that we do, by calculating length.
108                 return ( currentRequestedOffset - offset );
109             }
110
111             // No content. signal end of buffer.
112             return -1;
113         }
114
115         // Copy from expanded buf whatever length we can accomodate.
116         tmpLength = Math.min( sbuf.length(), currentRequestedLength );
117         sbuf.getChars( 0, tmpLength, destbuf, currentRequestedOffset );
118
119         // Create the leftover (if any)
120         if ( tmpLength < sbuf.length() )
121         {
122             leftover = new char[sbuf.length() - tmpLength];
123             sbuf.getChars( tmpLength, tmpLength + leftover.length, leftover, 0 );
124         }
125
126         // Calculate Actual Length and return.
127         return ( currentRequestedOffset - offset ) + tmpLength;
128     }
129
130     private StringBuilder getExpandedBuffer( int minimum_length )
131         throws IOException
132     {
133         StringBuilder buf = null;
134         String line = this.originalReader.readLine();
135         boolean done = ( line == null );
136
137         while ( !done )
138         {
139             if ( buf == null )
140             {
141                 buf = new StringBuilder();
142             }
143
144             buf.append( expandLine( line ) );
145
146             // Add newline only if there is more data.
147             if ( this.originalReader.ready() )
148             {
149                 buf.append( "\n" );
150             }
151
152             if ( buf.length() > minimum_length )
153             {
154                 done = true;
155             }
156             else
157             {
158                 line = this.originalReader.readLine();
159                 done = ( line == null );
160             }
161         }
162
163         return buf;
164     }
165
166     private String expandLine( String line )
167     {
168         StringBuilder ret = new StringBuilder();
169
170         int offset = 0;
171         String entity;
172         Matcher mat = this.entityPattern.matcher( line );
173         while ( mat.find( offset ) )
174         {
175             ret.append( line.substring( offset, mat.start() ) );
176             entity = mat.group();
177             ret.append( LatinEntities.resolveEntity( entity ) );
178             offset = mat.start() + entity.length();
179         }
180         ret.append( line.substring( offset ) );
181
182         return ret.toString();
183     }
184
185     public void close()
186         throws IOException
187     {
188         this.originalReader.close();
189     }
190 }