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 end = endToken.length();
315 do
316 {
317 if ( ch == -1 )
318 {
319 break;
320 }
321 else if ( ch == '\n' && !supportMultiLineFiltering )
322 {
323
324 key.append( (char) ch );
325 break;
326 }
327
328 key.append( (char) ch );
329
330 if ( ch == this.endToken.charAt( end - 1 ) )
331 {
332 end--;
333 if ( end == 0 )
334 {
335 break;
336 }
337 }
338 else
339 {
340 end = endToken.length();
341 }
342
343 ch = in.read();
344 }
345 while ( true );
346
347
348 String value = null;
349 if ( end == 0 )
350 {
351 try
352 {
353 if ( interpolateWithPrefixPattern )
354 {
355 value = interpolator.interpolate( key.toString(), "", recursionInterceptor );
356 }
357 else
358 {
359 value = interpolator.interpolate( key.toString(), recursionInterceptor );
360 }
361 }
362 catch ( InterpolationException e )
363 {
364 IllegalArgumentException error = new IllegalArgumentException( e.getMessage() );
365 error.initCause( e );
366
367 throw error;
368 }
369 }
370
371
372 if ( value != null )
373 {
374 replaceData = value;
375 replaceIndex = value.length();
376 }
377 else
378 {
379 replaceData = key.toString();
380 replaceIndex = key.length();
381 }
382
383 if ( ch == -1 )
384 {
385 eof = true;
386 }
387 return read();
388
389 }
390
391 public boolean isInterpolateWithPrefixPattern()
392 {
393 return interpolateWithPrefixPattern;
394 }
395
396 public void setInterpolateWithPrefixPattern( boolean interpolateWithPrefixPattern )
397 {
398 this.interpolateWithPrefixPattern = interpolateWithPrefixPattern;
399 }
400
401 public String getEscapeString()
402 {
403 return escapeString;
404 }
405
406 public void setEscapeString( String escapeString )
407 {
408
409 if ( escapeString != null && escapeString.length() >= 1 )
410 {
411 this.escapeString = escapeString;
412 this.useEscape = escapeString != null && escapeString.length() >= 1;
413 calculateMarkLength();
414 }
415 }
416
417 public boolean isPreserveEscapeString()
418 {
419 return preserveEscapeString;
420 }
421
422 public void setPreserveEscapeString( boolean preserveEscapeString )
423 {
424 this.preserveEscapeString = preserveEscapeString;
425 }
426
427 public RecursionInterceptor getRecursionInterceptor()
428 {
429 return recursionInterceptor;
430 }
431
432 public InterpolatorFilterReaderLineEnding setRecursionInterceptor( RecursionInterceptor recursionInterceptor )
433 {
434 this.recursionInterceptor = recursionInterceptor;
435 return this;
436 }
437
438 private void calculateMarkLength()
439 {
440 markLength = 16;
441
442 if ( escapeString != null )
443 {
444 markLength += escapeString.length();
445 }
446
447 if ( beginToken != null )
448 {
449 markLength += beginToken.length();
450 }
451
452 if ( endToken != null )
453 {
454 markLength += endToken.length();
455 }
456
457 }
458
459 }