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