-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
SimpleLanguage.java
240 lines (220 loc) · 10.2 KB
/
SimpleLanguage.java
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.language.simple;
import org.apache.camel.Expression;
import org.apache.camel.Predicate;
import org.apache.camel.builder.ExpressionBuilder;
import org.apache.camel.support.LanguageSupport;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.PredicateToExpressionAdapter;
/**
* A <a href="http://camel.apache.org/simple.html">simple language</a>
* which maps simple property style notations to access headers and bodies.
* Examples of supported expressions are:
* <ul>
* <li>exchangeId to access the exchange id</li>
* <li>id to access the inbound message id</li>
* <li>in.body or body to access the inbound body</li>
* <li>in.body.OGNL or body.OGNL to access the inbound body using an OGNL expression</li>
* <li>mandatoryBodyAs(<classname>) to convert the in body to the given type, will throw exception if not possible to convert</li>
* <li>bodyAs(<classname>) to convert the in body to the given type, will return null if not possible to convert</li>
* <li>headerAs(<key>, <classname>) to convert the in header to the given type, will return null if not possible to convert</li>
* <li>out.body to access the inbound body</li>
* <li>in.header.foo or header.foo to access an inbound header called 'foo'</li>
* <li>in.header.foo[bar] or header.foo[bar] to access an inbound header called 'foo' as a Map and lookup the map with 'bar' as key</li>
* <li>in.header.foo.OGNL or header.OGNL to access an inbound header called 'foo' using an OGNL expression</li>
* <li>out.header.foo to access an outbound header called 'foo'</li>
* <li>property.foo to access the exchange property called 'foo'</li>
* <li>property.foo.OGNL to access the exchange property called 'foo' using an OGNL expression</li>
* <li>sys.foo to access the system property called 'foo'</li>
* <li>sysenv.foo to access the system environment called 'foo'</li>
* <li>exception.messsage to access the exception message</li>
* <li>threadName to access the current thread name</li>
* <li>date:<command>:<pattern> for date formatting using the {@link java.text.SimpleDateFormat} patterns.
* Supported commands are: <tt>now</tt> for current timestamp,
* <tt>in.header.xxx</tt> or <tt>header.xxx</tt> to use the Date object in the in header.
* <tt>out.header.xxx</tt> to use the Date object in the out header.
* </li>
* <li>bean:<bean expression> to invoke a bean using the
* {@link org.apache.camel.language.bean.BeanLanguage BeanLanguage}</li>
* <li>properties:<[locations]>:<key> for using property placeholders using the
* {@link org.apache.camel.component.properties.PropertiesComponent}.
* The locations parameter is optional and you can enter multiple locations separated with comma.
* </li>
* </ul>
* <p/>
* The simple language supports OGNL notation when accessing either body or header.
* <p/>
* The simple language now also includes file language out of the box which means the following expression is also
* supported:
* <ul>
* <li><tt>file:name</tt> to access the file name (is relative, see note below))</li>
* <li><tt>file:name.noext</tt> to access the file name with no extension</li>
* <li><tt>file:name.ext</tt> to access the file extension</li>
* <li><tt>file:ext</tt> to access the file extension</li>
* <li><tt>file:onlyname</tt> to access the file name (no paths)</li>
* <li><tt>file:onlyname.noext</tt> to access the file name (no paths) with no extension </li>
* <li><tt>file:parent</tt> to access the parent file name</li>
* <li><tt>file:path</tt> to access the file path name</li>
* <li><tt>file:absolute</tt> is the file regarded as absolute or relative</li>
* <li><tt>file:absolute.path</tt> to access the absolute file path name</li>
* <li><tt>file:length</tt> to access the file length as a Long type</li>
* <li><tt>file:size</tt> to access the file length as a Long type</li>
* <li><tt>file:modified</tt> to access the file last modified as a Date type</li>
* <li><tt>date:<command>:<pattern></tt> for date formatting using the {@link java.text.SimpleDateFormat} patterns.
* Additional Supported commands are: <tt>file</tt> for the last modified timestamp of the file.
* All the commands from {@link SimpleLanguage} is also available.
* </li>
* </ul>
* The <b>relative</b> file is the filename with the starting directory clipped, as opposed to <b>path</b> that will
* return the full path including the starting directory.
* <br/>
* The <b>only</b> file is the filename only with all paths clipped.
*
*/
public class SimpleLanguage extends LanguageSupport {
// singleton for expressions without a result type
private static final SimpleLanguage SIMPLE = new SimpleLanguage();
protected boolean allowEscape = true;
/**
* Default constructor.
*/
public SimpleLanguage() {
}
public Predicate createPredicate(String expression) {
ObjectHelper.notNull(expression, "expression");
expression = loadResource(expression);
// support old simple language syntax
@SuppressWarnings("deprecation")
Predicate answer = SimpleBackwardsCompatibleParser.parsePredicate(expression, allowEscape);
if (answer == null) {
// use the new parser
SimplePredicateParser parser = new SimplePredicateParser(expression, allowEscape);
answer = parser.parsePredicate();
}
return answer;
}
public Expression createExpression(String expression) {
ObjectHelper.notNull(expression, "expression");
expression = loadResource(expression);
// support old simple language syntax
@SuppressWarnings("deprecation")
Expression answer = SimpleBackwardsCompatibleParser.parseExpression(expression, allowEscape);
if (answer == null) {
// use the new parser
SimpleExpressionParser parser = new SimpleExpressionParser(expression, allowEscape);
answer = parser.parseExpression();
}
return answer;
}
/**
* Creates a new {@link Expression}.
* <p/>
* <b>Important:</b> If you need to use a predicate (function to return true|false) then use
* {@link #predicate(String)} instead.
*/
public static Expression simple(String expression) {
return expression(expression);
}
/**
* Creates a new {@link Expression} (or {@link Predicate}
* if the resultType is a <tt>Boolean</tt>, or <tt>boolean</tt> type).
*/
public static Expression simple(String expression, Class<?> resultType) {
return new SimpleLanguage().createExpression(expression, resultType);
}
public Expression createExpression(String expression, Class<?> resultType) {
if (resultType == Boolean.class || resultType == boolean.class) {
// if its a boolean as result then its a predicate
Predicate predicate = createPredicate(expression);
return PredicateToExpressionAdapter.toExpression(predicate);
} else {
Expression exp = createExpression(expression);
if (resultType != null) {
exp = ExpressionBuilder.convertToExpression(exp, resultType);
}
return exp;
}
}
/**
* Creates a new {@link Expression}.
* <p/>
* <b>Important:</b> If you need to use a predicate (function to return true|false) then use
* {@link #predicate(String)} instead.
*/
public static Expression expression(String expression) {
return SIMPLE.createExpression(expression);
}
/**
* Creates a new {@link Predicate}.
*/
public static Predicate predicate(String predicate) {
return SIMPLE.createPredicate(predicate);
}
/**
* Change the start tokens used for functions.
* <p/>
* This can be used to alter the function tokens to avoid clashes with other
* frameworks etc.
* <p/>
* The default start tokens is <tt>${</tt> and <tt>$simple{</tt>.
*
* @param startToken new start token(s) to be used for functions
*/
public static void changeFunctionStartToken(String... startToken) {
SimpleTokenizer.changeFunctionStartToken(startToken);
}
/**
* Change the end tokens used for functions.
* <p/>
* This can be used to alter the function tokens to avoid clashes with other
* frameworks etc.
* <p/>
* The default end token is <tt>}</tt>
*
* @param endToken new end token(s) to be used for functions
*/
public static void changeFunctionEndToken(String... endToken) {
SimpleTokenizer.changeFunctionEndToken(endToken);
}
/**
* Change the start token used for functions.
* <p/>
* This can be used to alter the function tokens to avoid clashes with other
* frameworks etc.
* <p/>
* The default start tokens is <tt>${</tt> and <tt>$simple{</tt>.
*
* @param startToken new start token to be used for functions
*/
public void setFunctionStartToken(String startToken) {
changeFunctionStartToken(startToken);
}
/**
* Change the end token used for functions.
* <p/>
* This can be used to alter the function tokens to avoid clashes with other
* frameworks etc.
* <p/>
* The default end token is <tt>}</tt>
*
* @param endToken new end token to be used for functions
*/
public void setFunctionEndToken(String endToken) {
changeFunctionEndToken(endToken);
}
}