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