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