1 package org.codehaus.plexus.interpolation.fixed;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.codehaus.plexus.interpolation.BasicInterpolator;
23 import org.codehaus.plexus.interpolation.InterpolationException;
24 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
25 import org.codehaus.plexus.interpolation.RecursionInterceptor;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class FixedStringSearchInterpolator implements FixedValueSource {
44
45 private final FixedValueSource[] valueSources;
46
47 private final InterpolationPostProcessor postProcessor;
48
49 public static final String DEFAULT_START_EXPR = "${";
50
51 public static final String DEFAULT_END_EXPR = "}";
52
53 private final String startExpr;
54
55 private final String endExpr;
56
57 private final String escapeString;
58
59 private FixedStringSearchInterpolator(
60 String startExpr,
61 String endExpr,
62 String escapeString,
63 InterpolationPostProcessor postProcessor,
64 FixedValueSource... valueSources) {
65 this.startExpr = startExpr;
66 this.endExpr = endExpr;
67 this.escapeString = escapeString;
68 if (valueSources == null) {
69 throw new IllegalArgumentException("valueSources cannot be null");
70 }
71 for (int i = 0; i < valueSources.length; i++) {
72 if (valueSources[i] == null) {
73 throw new IllegalArgumentException("valueSources[" + i + "] is null");
74 }
75 }
76
77 this.valueSources = valueSources;
78 this.postProcessor = postProcessor;
79 }
80
81 public static FixedStringSearchInterpolator create(
82 String startExpr, String endExpr, FixedValueSource... valueSources) {
83 return new FixedStringSearchInterpolator(startExpr, endExpr, null, null, valueSources);
84 }
85
86 public static FixedStringSearchInterpolator create(FixedValueSource... valueSources) {
87 return new FixedStringSearchInterpolator(DEFAULT_START_EXPR, DEFAULT_END_EXPR, null, null, valueSources);
88 }
89
90 public static FixedStringSearchInterpolator createWithPermittedNulls(FixedValueSource... valueSources) {
91 List<FixedValueSource> nonnulls = new ArrayList<FixedValueSource>();
92 for (FixedValueSource item : valueSources) {
93 if (item != null) nonnulls.add(item);
94 }
95 return new FixedStringSearchInterpolator(
96 DEFAULT_START_EXPR,
97 DEFAULT_END_EXPR,
98 null,
99 null,
100 nonnulls.toArray(new FixedValueSource[nonnulls.size()]));
101 }
102
103 public FixedStringSearchInterpolator withExpressionMarkers(String startExpr, String endExpr) {
104 return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources);
105 }
106
107 public FixedStringSearchInterpolator withPostProcessor(InterpolationPostProcessor postProcessor) {
108 return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources);
109 }
110
111 public FixedStringSearchInterpolator withEscapeString(String escapeString) {
112 return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources);
113 }
114
115 public String interpolate(String input) throws InterpolationCycleException {
116 return interpolate(input, new InterpolationState());
117 }
118
119 public static FixedStringSearchInterpolator empty() {
120 return create();
121 }
122
123
124
125 public Object getValue(String realExpr, InterpolationState interpolationState) {
126
127 interpolationState.recursionInterceptor.expressionResolutionStarted(realExpr);
128
129 try {
130 Object value = null;
131
132 for (FixedValueSource valueSource : valueSources) {
133 value = valueSource.getValue(realExpr, interpolationState);
134 if (value != null) {
135 break;
136 }
137 }
138
139 if (value != null) {
140 if (interpolationState.root != null) {
141 value = interpolationState.root.interpolate(String.valueOf(value), interpolationState);
142 }
143 return String.valueOf(value);
144 } else {
145 return null;
146 }
147 } finally {
148 interpolationState.recursionInterceptor.expressionResolutionFinished(realExpr);
149 }
150 }
151
152 public BasicInterpolator asBasicInterpolator() {
153 final InterpolationState is = new InterpolationState();
154 return new BasicInterpolator() {
155
156 public String interpolate(String input) throws InterpolationException {
157 return FixedStringSearchInterpolator.this.interpolate(input, is);
158 }
159
160 public String interpolate(String input, RecursionInterceptor recursionInterceptor)
161 throws InterpolationException {
162 is.setRecursionInterceptor(recursionInterceptor);
163 return FixedStringSearchInterpolator.this.interpolate(input, is);
164 }
165 };
166 }
167
168 public String interpolate(String input, InterpolationState interpolationState) throws InterpolationCycleException {
169 if (interpolationState.root == null) {
170 interpolationState.root = this;
171 }
172
173 if (input == null) {
174
175 return "";
176 }
177 StringBuilder result = new StringBuilder(input.length() * 2);
178
179 int startIdx;
180 int endIdx = -1;
181 while ((startIdx = input.indexOf(startExpr, endIdx + 1)) > -1) {
182 result.append(input, endIdx + 1, startIdx);
183
184 endIdx = input.indexOf(endExpr, startIdx + 1);
185 if (endIdx < 0) {
186 break;
187 }
188
189 final String wholeExpr = input.substring(startIdx, endIdx + endExpr.length());
190 String realExpr = wholeExpr.substring(startExpr.length(), wholeExpr.length() - endExpr.length());
191
192 if (startIdx >= 0 && escapeString != null && escapeString.length() > 0) {
193 int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length();
194 if (startEscapeIdx >= 0) {
195 String escape = input.substring(startEscapeIdx, startIdx);
196 if (escapeString.equals(escape)) {
197 result.append(wholeExpr);
198 result.replace(startEscapeIdx, startEscapeIdx + escapeString.length(), "");
199 continue;
200 }
201 }
202 }
203
204 boolean resolved = false;
205 if (!interpolationState.unresolvable.contains(wholeExpr)) {
206 if (realExpr.startsWith(".")) {
207 realExpr = realExpr.substring(1);
208 }
209
210 if (interpolationState.recursionInterceptor.hasRecursiveExpression(realExpr)) {
211 throw new InterpolationCycleException(interpolationState.recursionInterceptor, realExpr, wholeExpr);
212 }
213
214 Object value = getValue(realExpr, interpolationState);
215 if (value != null) {
216 value = interpolate(String.valueOf(value), interpolationState);
217
218 if (postProcessor != null) {
219 Object newVal = postProcessor.execute(realExpr, value);
220 if (newVal != null) {
221 value = newVal;
222 }
223 }
224
225 result.append(String.valueOf(value));
226 resolved = true;
227 } else {
228 interpolationState.unresolvable.add(wholeExpr);
229 }
230 }
231
232 if (!resolved) {
233 result.append(wholeExpr);
234 }
235
236 if (endIdx > -1) {
237 endIdx += endExpr.length() - 1;
238 }
239 }
240
241 if (endIdx == -1 && startIdx > -1) {
242 result.append(input, startIdx, input.length());
243 } else if (endIdx < input.length()) {
244 result.append(input, endIdx + 1, input.length());
245 }
246
247 return result.toString();
248 }
249 }