1
2
3
4
5
6
7
8
9
10
11 package org.mule.expression;
12
13 import static org.mule.expression.ExpressionConstants.ALL_ARGUMENT;
14 import static org.mule.expression.ExpressionConstants.DELIM;
15 import static org.mule.expression.ExpressionConstants.OPTIONAL_ARGUMENT;
16
17 import org.mule.api.MuleMessage;
18 import org.mule.api.expression.RequiredValueException;
19 import org.mule.api.transport.PropertyScope;
20 import org.mule.config.i18n.CoreMessages;
21 import org.mule.routing.filters.WildcardFilter;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29
30
31
32 public final class ExpressionUtils
33 {
34 private ExpressionUtils()
35 {
36
37 }
38
39
40
41
42
43
44
45
46
47
48 public static Object getPropertyWithScope(String expression, MuleMessage msg)
49 {
50 return getPropertyWithScope(expression, msg, Object.class);
51 }
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public static <T> T getPropertyWithScope(String expression, MuleMessage msg, Class<T> type)
66 {
67 return getPropertyInternal(expression, PropertyScope.OUTBOUND, true, msg, type);
68 }
69
70
71
72
73
74
75
76
77
78 public static Object getProperty(String expression, PropertyScope scope, MuleMessage msg)
79 {
80 return getProperty(expression, scope, msg, Object.class);
81 }
82
83
84
85
86
87
88
89
90
91 public static <T> T getProperty(String expression, PropertyScope scope, MuleMessage msg, Class<T> type)
92 {
93 return getPropertyInternal(expression, scope, false, msg, type);
94 }
95
96
97
98
99
100
101
102
103
104
105
106 @SuppressWarnings("unchecked")
107 protected static <T> T getPropertyInternal(String expression, PropertyScope scope, boolean parseScope, MuleMessage msg, Class<T> type)
108 {
109 if (parseScope)
110 {
111 PropertyScope tempScope = getScope(expression);
112 if (tempScope != null)
113 {
114
115 expression = expression.substring(tempScope.getScopeName().length() + 1);
116 scope = tempScope;
117 }
118 }
119
120 if (expression.contains(ALL_ARGUMENT))
121 {
122 WildcardFilter filter = new WildcardFilter(expression);
123 if (Map.class.isAssignableFrom(type))
124 {
125 Map<String, Object> props = new HashMap<String, Object>();
126 for (String name : msg.getPropertyNames(scope))
127 {
128 if (filter.accept(name))
129 {
130 props.put(name, msg.getProperty(name, scope));
131 }
132 }
133 return (T) returnMap(props, scope);
134 }
135 else if (List.class.isAssignableFrom(type))
136 {
137 List<Object> values = new ArrayList<Object>();
138 for (String name : msg.getPropertyNames(scope))
139 {
140 if (filter.accept(name))
141 {
142 values.add(msg.getProperty(name, scope));
143 }
144 }
145 return (T) returnList(values, scope);
146 }
147 else
148 {
149
150 throw new IllegalArgumentException("Type specified is not a collection type but '" + ALL_ARGUMENT + "' was specified for all properties. Type is: " + type);
151 }
152 }
153 else if (Map.class.isAssignableFrom(type))
154 {
155 String[] names = expression.split(DELIM);
156 Map<String, Object> props = new HashMap<String, Object>();
157 for (String name : names)
158 {
159 boolean required = true;
160 name = name.trim();
161 PropertyScope entryScope = scope;
162 if (parseScope)
163 {
164 entryScope = getScope(name);
165 if (entryScope != null)
166 {
167
168 name = name.substring(entryScope.getScopeName().length() + 1);
169 }
170 else
171 {
172 entryScope = scope;
173 }
174 }
175 if (name.endsWith(OPTIONAL_ARGUMENT))
176 {
177 name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
178 required = false;
179 }
180 Object value = msg.getProperty(name, entryScope);
181 if (value == null && required)
182 {
183 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers", entryScope.getScopeName() + ":" + name));
184 }
185 else if (value != null)
186 {
187 props.put(name, value);
188 }
189 }
190 return (T) returnMap(props, scope);
191 }
192 else if (List.class.isAssignableFrom(type))
193 {
194 String[] names = expression.split(DELIM);
195 List<Object> values = new ArrayList<Object>();
196 for (String name : names)
197 {
198 boolean required = true;
199 name = name.trim();
200 PropertyScope itemScope = scope;
201 if (parseScope)
202 {
203 itemScope = getScope(name);
204 if (itemScope != null)
205 {
206
207 name = name.substring(itemScope.getScopeName().length() + 1);
208 }
209 else
210 {
211 itemScope = scope;
212 }
213 }
214 if (name.endsWith(OPTIONAL_ARGUMENT))
215 {
216 name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
217 required = false;
218 }
219 name = name.trim();
220 Object value = msg.getProperty(name, itemScope);
221 if (value == null && required)
222 {
223 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers-list", itemScope.getScopeName() + ":" + name));
224 }
225 else if (value != null)
226 {
227 values.add(value);
228 }
229 }
230 return (T) returnList(values, scope);
231 }
232 else
233 {
234 boolean required = true;
235 if (expression.endsWith(OPTIONAL_ARGUMENT))
236 {
237 expression = expression.substring(0, expression.length() - OPTIONAL_ARGUMENT.length());
238 required = false;
239 }
240 Object result = msg.getProperty(expression.trim(), scope);
241 if (result == null && required)
242 {
243 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("header", scope.getScopeName() + ":" + expression));
244
245 }
246 return (T) result;
247 }
248 }
249
250 private static Map<String, Object> returnMap(Map<String, Object> props, PropertyScope scope)
251 {
252 Map<String, Object> p = (props.size() == 0 ? Collections.<String, Object>emptyMap() : props);
253 if (scope.equals(PropertyScope.INBOUND))
254 {
255 p = Collections.unmodifiableMap(p);
256 }
257 return p;
258 }
259
260 private static List<Object> returnList(List<Object> values, PropertyScope scope)
261 {
262 List<Object> l = (values.size() == 0 ? Collections.emptyList() : values);
263 if (scope.equals(PropertyScope.INBOUND))
264 {
265 l = Collections.unmodifiableList(l);
266 }
267 return l;
268 }
269
270 protected static PropertyScope getScope(String expression)
271 {
272
273 final String[] tokens = expression.split(":", 2);
274 PropertyScope scope;
275 if (tokens.length == 2)
276 {
277 final String candidate = tokens[0];
278 scope = PropertyScope.get(candidate.toLowerCase());
279 if (scope == null)
280 {
281 throw new IllegalArgumentException(String.format("'%s' is not a valid property scope.", candidate));
282 }
283
284 return scope;
285 }
286 return null;
287 }
288 }