1 package org.apache.maven.shared.filtering;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.Reader;
25
26 import org.codehaus.plexus.interpolation.InterpolationException;
27 import org.codehaus.plexus.interpolation.Interpolator;
28 import org.codehaus.plexus.interpolation.RecursionInterceptor;
29 import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor;
30
31
32
33
34
35
36
37
38
39 public class InterpolatorFilterReaderLineEnding
40 extends AbstractFilterReaderLineEnding
41 {
42
43
44
45
46 private Interpolator interpolator;
47
48 private RecursionInterceptor recursionInterceptor;
49
50
51
52
53 private String replaceData = null;
54
55
56
57
58 private int replaceIndex = 0;
59
60
61
62
63 public static final String DEFAULT_BEGIN_TOKEN = "${";
64
65
66
67
68 public static final String DEFAULT_END_TOKEN = "}";
69
70 private String beginToken;
71
72 private String endToken;
73
74
75
76
77 private boolean interpolateWithPrefixPattern = true;
78
79 private boolean supportMultiLineFiltering;
80
81 private boolean eof = false;
82
83
84
85
86
87
88
89
90 public InterpolatorFilterReaderLineEnding( Reader in, Interpolator interpolator, String beginToken, String endToken,
91 boolean supportMultiLineFiltering )
92 {
93 this( in, interpolator, beginToken, endToken, new SimpleRecursionInterceptor(), supportMultiLineFiltering );
94 }
95
96
97
98
99
100
101
102
103
104 private InterpolatorFilterReaderLineEnding( Reader in, Interpolator interpolator, String beginToken,
105 String endToken, RecursionInterceptor ri,
106 boolean supportMultiLineFiltering )
107 {
108
109 super( new BufferedReader( in ) );
110
111 this.interpolator = interpolator;
112
113 this.beginToken = beginToken;
114
115 this.endToken = endToken;
116
117 recursionInterceptor = ri;
118
119 this.supportMultiLineFiltering = supportMultiLineFiltering;
120
121 calculateMarkLength();
122
123 }
124
125
126
127
128
129
130
131
132
133 @Override
134 public long skip( long n )
135 throws IOException
136 {
137 if ( n < 0L )
138 {
139 throw new IllegalArgumentException( "skip value is negative" );
140 }
141
142 for ( long i = 0; i < n; i++ )
143 {
144 if ( read() == -1 )
145 {
146 return i;
147 }
148 }
149 return n;
150 }
151
152
153
154
155
156
157
158
159
160
161
162 @Override
163 public int read( char cbuf[], int off, int len )
164 throws IOException
165 {
166 for ( int i = 0; i < len; i++ )
167 {
168 int ch = read();
169 if ( ch == -1 )
170 {
171 if ( i == 0 )
172 {
173 return -1;
174 }
175 else
176 {
177 return i;
178 }
179 }
180 cbuf[off + i] = (char) ch;
181 }
182 return len;
183 }
184
185
186
187
188
189
190
191 @Override
192 public int read()
193 throws IOException
194 {
195 if ( replaceIndex > 0 )
196 {
197 return replaceData.charAt( replaceData.length() - ( replaceIndex-- ) );
198 }
199 if ( eof )
200 {
201 return -1;
202 }
203
204 in.mark( markLength );
205
206 int ch = in.read();
207 if ( ch == -1 || ( ch == '\n' && !supportMultiLineFiltering ) )
208 {
209 return ch;
210 }
211
212 boolean inEscape = useEscape && ch == getEscapeString().charAt( 0 );
213
214 StringBuilder key = new StringBuilder();
215
216
217 if ( inEscape )
218 {
219 for ( int i = 0; i < getEscapeString().length(); i++ )
220 {
221 key.append( (char) ch );
222
223 if ( ch != getEscapeString().charAt( i ) || ch == -1 || ( ch == '\n' && !supportMultiLineFiltering ) )
224 {
225
226 in.reset();
227 inEscape = false;
228 key.setLength( 0 );
229 break;
230 }
231
232 ch = in.read();
233 }
234
235 }
236
237
238 boolean foundToken = false;
239 for ( int i = 0; i < beginToken.length(); i++ )
240 {
241 if ( ch != beginToken.charAt( i ) || ch == -1 || ( ch == '\n' && !supportMultiLineFiltering ) )
242 {
243
244 break;
245 }
246
247 if ( i == beginToken.length() - 1 )
248 {
249
250 foundToken = true;
251
252 }
253
254 ch = in.read();
255
256 }
257
258 in.reset();
259 in.skip( key.length() );
260 ch = in.read();
261
262
263 if ( inEscape )
264 {
265
266 if ( beginToken != null )
267 {
268 if ( !isPreserveEscapeString() )
269 {
270 key.setLength( 0 );
271 }
272 }
273
274 key.append( (char) ch );
275
276 replaceData = key.toString();
277 replaceIndex = key.length();
278
279 return read();
280
281 }
282
283
284 if ( !foundToken )
285 {
286
287 in.reset();
288 return in.read();
289
290 }
291
292
293
294 key.append( beginToken );
295 in.reset();
296 in.skip( beginToken.length() );
297 ch = in.read();
298
299 int endTokenSize = endToken.length();
300 int end = endTokenSize;
301 do
302 {
303 if ( ch == -1 )
304 {
305 break;
306 }
307 else if ( ch == '\n' && !supportMultiLineFiltering )
308 {
309
310 key.append( (char) ch );
311 break;
312 }
313
314 key.append( (char) ch );
315
316 if ( ch == this.endToken.charAt( endTokenSize - end ) )
317 {
318 end--;
319 if ( end == 0 )
320 {
321 break;
322 }
323 }
324 else
325 {
326 end = endTokenSize;
327 }
328
329 ch = in.read();
330 }
331 while ( true );
332
333
334 String value = null;
335 if ( end == 0 )
336 {
337 try
338 {
339 if ( interpolateWithPrefixPattern )
340 {
341 value = interpolator.interpolate( key.toString(), "", recursionInterceptor );
342 }
343 else
344 {
345 value = interpolator.interpolate( key.toString(), recursionInterceptor );
346 }
347 }
348 catch ( InterpolationException e )
349 {
350 IllegalArgumentException error = new IllegalArgumentException( e.getMessage() );
351 error.initCause( e );
352
353 throw error;
354 }
355 }
356
357
358 if ( value != null )
359 {
360 replaceData = value;
361 replaceIndex = value.length();
362 }
363 else
364 {
365 replaceData = key.toString();
366 replaceIndex = key.length();
367 }
368
369 if ( ch == -1 )
370 {
371 eof = true;
372 }
373 return read();
374
375 }
376
377
378
379
380 public boolean isInterpolateWithPrefixPattern()
381 {
382 return interpolateWithPrefixPattern;
383 }
384
385
386
387
388 public void setInterpolateWithPrefixPattern( boolean interpolateWithPrefixPattern )
389 {
390 this.interpolateWithPrefixPattern = interpolateWithPrefixPattern;
391 }
392
393
394
395
396 public RecursionInterceptor getRecursionInterceptor()
397 {
398 return recursionInterceptor;
399 }
400
401
402
403
404
405 public InterpolatorFilterReaderLineEnding setRecursionInterceptor( RecursionInterceptor theRecursionInterceptor )
406 {
407 this.recursionInterceptor = theRecursionInterceptor;
408 return this;
409 }
410
411 }