001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.builder;
018
019 import java.io.File;
020 import java.io.FileNotFoundException;
021 import java.io.InputStream;
022 import java.nio.channels.ReadableByteChannel;
023 import java.text.SimpleDateFormat;
024 import java.util.Collection;
025 import java.util.Date;
026 import java.util.Scanner;
027 import java.util.regex.Pattern;
028
029 import org.apache.camel.Exchange;
030 import org.apache.camel.Expression;
031 import org.apache.camel.Message;
032 import org.apache.camel.RuntimeCamelException;
033 import org.apache.camel.language.bean.BeanLanguage;
034 import org.apache.camel.language.simple.SimpleLanguage;
035
036 /**
037 * A helper class for working with <a href="http://activemq.apache.org/camel/expression.html">expressions</a>.
038 *
039 * @version $Revision: 756318 $
040 */
041 public final class ExpressionBuilder {
042
043 /**
044 * Utility classes should not have a public constructor.
045 */
046 private ExpressionBuilder() {
047 }
048
049 /**
050 * Returns an expression for the header value with the given name
051 *
052 * @param headerName the name of the header the expression will return
053 * @return an expression object which will return the header value
054 */
055 public static <E extends Exchange> Expression<E> headerExpression(final String headerName) {
056 return new Expression<E>() {
057 public Object evaluate(E exchange) {
058 Object header = exchange.getIn().getHeader(headerName);
059 if (header == null) {
060 // lets try the exchange header
061 header = exchange.getProperty(headerName);
062 }
063 return header;
064 }
065
066 @Override
067 public String toString() {
068 return "header(" + headerName + ")";
069 }
070 };
071 }
072
073 /**
074 * Returns an expression for the inbound message headers
075 *
076 * @see Message#getHeaders()
077 * @return an expression object which will return the inbound headers
078 */
079 public static <E extends Exchange> Expression<E> headersExpression() {
080 return new Expression<E>() {
081 public Object evaluate(E exchange) {
082 return exchange.getIn().getHeaders();
083 }
084
085 @Override
086 public String toString() {
087 return "headers";
088 }
089 };
090 }
091
092 /**
093 * Returns an expression for the out header value with the given name
094 *
095 * @param headerName the name of the header the expression will return
096 * @return an expression object which will return the header value
097 */
098 public static <E extends Exchange> Expression<E> outHeaderExpression(final String headerName) {
099 return new Expression<E>() {
100 public Object evaluate(E exchange) {
101 Message out = exchange.getOut(false);
102 if (out == null) {
103 return null;
104 }
105 Object header = out.getHeader(headerName);
106 if (header == null) {
107 // lets try the exchange header
108 header = exchange.getProperty(headerName);
109 }
110 return header;
111 }
112
113 @Override
114 public String toString() {
115 return "outHeader(" + headerName + ")";
116 }
117 };
118 }
119
120 /**
121 * Returns an expression for the outbound message headers
122 *
123 * @see Message#getHeaders()
124 * @return an expression object which will return the inbound headers
125 */
126 public static <E extends Exchange> Expression<E> outHeadersExpression() {
127 return new Expression<E>() {
128 public Object evaluate(E exchange) {
129 return exchange.getOut().getHeaders();
130 }
131
132 @Override
133 public String toString() {
134 return "outHeaders";
135 }
136 };
137 }
138
139 /**
140 * Returns an expression for the property value of exchange with the given name
141 *
142 * @see Exchange#getProperty(String)
143 * @param propertyName the name of the property the expression will return
144 * @return an expression object which will return the property value
145 */
146 public static <E extends Exchange> Expression<E> propertyExpression(final String propertyName) {
147 return new Expression<E>() {
148 public Object evaluate(E exchange) {
149 return exchange.getProperty(propertyName);
150 }
151
152 @Override
153 public String toString() {
154 return "property(" + propertyName + ")";
155 }
156 };
157 }
158
159 /**
160 * Returns an expression for the properties of exchange with the given name
161 *
162 * @see Exchange#getProperties()
163 * @return an expression object which will return the properties
164 */
165 public static <E extends Exchange> Expression<E> propertiesExpression() {
166 return new Expression<E>() {
167 public Object evaluate(E exchange) {
168 return exchange.getProperties();
169 }
170
171 @Override
172 public String toString() {
173 return "properties";
174 }
175 };
176 }
177
178 /**
179 * Returns an expression for the properties of exchange with the given name
180 *
181 * @see Exchange#getProperties()
182 * @return an expression object which will return the properties
183 */
184 public static <E extends Exchange> Expression<E> camelContextPropertiesExpression() {
185 return new Expression<E>() {
186 public Object evaluate(E exchange) {
187 return exchange.getContext().getProperties();
188 }
189
190 @Override
191 public String toString() {
192 return "camelContextProperties";
193 }
194 };
195 }
196
197 /**
198 * Returns an expression for the property value of the camel context with the given name
199 *
200 * @see Exchange#getProperty(String)
201 * @param propertyName the name of the property the expression will return
202 * @return an expression object which will return the property value
203 */
204 public static <E extends Exchange> Expression<E> camelContextPropertyExpression(final String propertyName) {
205 return new Expression<E>() {
206 public Object evaluate(E exchange) {
207 return exchange.getContext().getProperties().get(propertyName);
208 }
209
210 @Override
211 public String toString() {
212 return "camelContextProperty(" + propertyName + ")";
213 }
214 };
215 }
216
217 /**
218 * Returns an expression for a system property value with the given name
219 *
220 * @param propertyName the name of the system property the expression will
221 * return
222 * @return an expression object which will return the system property value
223 */
224 public static <E extends Exchange> Expression<E> systemPropertyExpression(final String propertyName) {
225 return systemPropertyExpression(propertyName, null);
226 }
227
228 /**
229 * Returns an expression for a system property value with the given name
230 *
231 * @param propertyName the name of the system property the expression will
232 * return
233 * @return an expression object which will return the system property value
234 */
235 public static <E extends Exchange> Expression<E> systemPropertyExpression(final String propertyName,
236 final String defaultValue) {
237 return new Expression<E>() {
238 public Object evaluate(E exchange) {
239 return System.getProperty(propertyName, defaultValue);
240 }
241
242 @Override
243 public String toString() {
244 return "systemProperty(" + propertyName + ")";
245 }
246 };
247 }
248
249 /**
250 * Returns an expression for the constant value
251 *
252 * @param value the value the expression will return
253 * @return an expression object which will return the constant value
254 */
255 public static <E extends Exchange> Expression<E> constantExpression(final Object value) {
256 return new Expression<E>() {
257 public Object evaluate(E exchange) {
258 return value;
259 }
260
261 @Override
262 public String toString() {
263 return "" + value;
264 }
265 };
266 }
267
268 /**
269 * Returns the expression for the exchanges inbound message body
270 */
271 public static <E extends Exchange> Expression<E> bodyExpression() {
272 return new Expression<E>() {
273 public Object evaluate(E exchange) {
274 return exchange.getIn().getBody();
275 }
276
277 @Override
278 public String toString() {
279 return "body";
280 }
281 };
282 }
283
284 /**
285 * Returns the expression for the exchanges inbound message body converted
286 * to the given type
287 */
288 public static <E extends Exchange, T> Expression<E> bodyExpression(final Class<T> type) {
289 return new Expression<E>() {
290 public Object evaluate(E exchange) {
291 return exchange.getIn().getBody(type);
292 }
293
294 @Override
295 public String toString() {
296 return "bodyAs[" + type.getName() + "]";
297 }
298 };
299 }
300
301 /**
302 * Returns the expression for the out messages body
303 */
304 public static <E extends Exchange> Expression<E> outBodyExpression() {
305 return new Expression<E>() {
306 public Object evaluate(E exchange) {
307 Message out = exchange.getOut(false);
308 if (out == null) {
309 return null;
310 }
311 return out.getBody();
312 }
313
314 @Override
315 public String toString() {
316 return "outBody";
317 }
318 };
319 }
320
321 /**
322 * Returns the expression for the exchanges outbound message body converted
323 * to the given type
324 */
325 public static <E extends Exchange, T> Expression<E> outBodyExpression(final Class<T> type) {
326 return new Expression<E>() {
327 public Object evaluate(E exchange) {
328 Message out = exchange.getOut(false);
329 if (out == null) {
330 return null;
331 }
332 return out.getBody(type);
333 }
334
335 @Override
336 public String toString() {
337 return "outBodyAs[" + type.getName() + "]";
338 }
339 };
340 }
341
342 /**
343 * Returns the expression for the fault messages body
344 */
345 public static <E extends Exchange> Expression<E> faultBodyExpression() {
346 return new Expression<E>() {
347 public Object evaluate(E exchange) {
348 return exchange.getFault().getBody();
349 }
350
351 @Override
352 public String toString() {
353 return "faultBody";
354 }
355 };
356 }
357
358 /**
359 * Returns the expression for the exchanges fault message body converted
360 * to the given type
361 */
362 public static <E extends Exchange, T> Expression<E> faultBodyExpression(final Class<T> type) {
363 return new Expression<E>() {
364 public Object evaluate(E exchange) {
365 return exchange.getFault().getBody(type);
366 }
367
368 @Override
369 public String toString() {
370 return "faultBodyAs[" + type.getName() + "]";
371 }
372 };
373 }
374
375 /**
376 * Returns the expression for the exchange
377 */
378 public static <E extends Exchange> Expression<E> exchangeExpression() {
379 return new Expression<E>() {
380 public Object evaluate(E exchange) {
381 return exchange;
382 }
383
384 @Override
385 public String toString() {
386 return "exchange";
387 }
388 };
389 }
390
391 /**
392 * Returns the expression for the IN message
393 */
394 public static <E extends Exchange> Expression<E> inMessageExpression() {
395 return new Expression<E>() {
396 public Object evaluate(E exchange) {
397 return exchange.getIn();
398 }
399
400 @Override
401 public String toString() {
402 return "inMessage";
403 }
404 };
405 }
406
407 /**
408 * Returns the expression for the OUT message
409 */
410 public static <E extends Exchange> Expression<E> outMessageExpression() {
411 return new Expression<E>() {
412 public Object evaluate(E exchange) {
413 return exchange.getOut();
414 }
415
416 @Override
417 public String toString() {
418 return "outMessage";
419 }
420 };
421 }
422
423 /**
424 * Returns an expression which converts the given expression to the given
425 * type
426 */
427 public static <E extends Exchange> Expression<E> convertTo(final Expression expression, final Class type) {
428 return new Expression<E>() {
429 public Object evaluate(E exchange) {
430 Object value = expression.evaluate(exchange);
431 return exchange.getContext().getTypeConverter().convertTo(type, exchange, value);
432 }
433
434 @Override
435 public String toString() {
436 return "" + expression + ".convertTo(" + type.getName() + ".class)";
437 }
438 };
439 }
440
441 /**
442 * Returns a tokenize expression which will tokenize the string with the
443 * given token
444 */
445 public static <E extends Exchange> Expression<E> tokenizeExpression(final Expression<E> expression,
446 final String token) {
447 return new Expression<E>() {
448 public Object evaluate(E exchange) {
449 Object value = expression.evaluate(exchange);
450 Scanner scanner = getScanner(exchange, value);
451 scanner.useDelimiter(token);
452 return scanner;
453 }
454
455 @Override
456 public String toString() {
457 return "tokenize(" + expression + ", " + token + ")";
458 }
459 };
460 }
461
462 /**
463 * Returns a tokenize expression which will tokenize the string with the
464 * given regex
465 */
466 public static <E extends Exchange> Expression<E> regexTokenize(final Expression<E> expression,
467 final String regexTokenizer) {
468 final Pattern pattern = Pattern.compile(regexTokenizer);
469 return new Expression<E>() {
470 public Object evaluate(E exchange) {
471 Object value = expression.evaluate(exchange);
472 Scanner scanner = getScanner(exchange, value);
473 scanner.useDelimiter(regexTokenizer);
474 return scanner;
475 }
476
477 @Override
478 public String toString() {
479 return "regexTokenize(" + expression + ", " + pattern.pattern() + ")";
480 }
481 };
482 }
483
484 private static Scanner getScanner(Exchange exchange, Object value) {
485 String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
486
487 Scanner scanner = null;
488 if (value instanceof Readable) {
489 scanner = new Scanner((Readable)value);
490 } else if (value instanceof InputStream) {
491 scanner = charset == null ? new Scanner((InputStream)value)
492 : new Scanner((InputStream)value, charset);
493 } else if (value instanceof File) {
494 try {
495 scanner = charset == null ? new Scanner((File)value) : new Scanner((File)value, charset);
496 } catch (FileNotFoundException e) {
497 throw new RuntimeCamelException(e);
498 }
499 } else if (value instanceof String) {
500 scanner = new Scanner((String)value);
501 } else if (value instanceof ReadableByteChannel) {
502 scanner = charset == null ? new Scanner((ReadableByteChannel)value)
503 : new Scanner((ReadableByteChannel)value, charset);
504 }
505
506 if (scanner == null) {
507 // value is not a suitable type, try to convert value to a string
508 String text = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
509 if (text != null) {
510 scanner = new Scanner(text);
511 }
512 }
513
514 if (scanner == null) {
515 scanner = new Scanner("");
516 }
517 return scanner;
518 }
519
520 /**
521 * Transforms the expression into a String then performs the regex
522 * replaceAll to transform the String and return the result
523 */
524 public static <E extends Exchange> Expression<E> regexReplaceAll(final Expression<E> expression,
525 final String regex, final String replacement) {
526 final Pattern pattern = Pattern.compile(regex);
527 return new Expression<E>() {
528 public Object evaluate(E exchange) {
529 String text = evaluateStringExpression(expression, exchange);
530 if (text == null) {
531 return null;
532 }
533 return pattern.matcher(text).replaceAll(replacement);
534 }
535
536 @Override
537 public String toString() {
538 return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
539 }
540 };
541 }
542
543 /**
544 * Transforms the expression into a String then performs the regex
545 * replaceAll to transform the String and return the result
546 */
547 public static <E extends Exchange> Expression<E> regexReplaceAll(final Expression<E> expression,
548 String regex,
549 final Expression<E> replacementExpression) {
550 final Pattern pattern = Pattern.compile(regex);
551 return new Expression<E>() {
552 public Object evaluate(E exchange) {
553 String text = evaluateStringExpression(expression, exchange);
554 String replacement = evaluateStringExpression(replacementExpression, exchange);
555 if (text == null || replacement == null) {
556 return null;
557 }
558 return pattern.matcher(text).replaceAll(replacement);
559 }
560
561 @Override
562 public String toString() {
563 return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
564 }
565 };
566 }
567
568 /**
569 * Appends the String evaluations of the two expressions together
570 */
571 public static <E extends Exchange> Expression<E> append(final Expression<E> left,
572 final Expression<E> right) {
573 return new Expression<E>() {
574 public Object evaluate(E exchange) {
575 return evaluateStringExpression(left, exchange) + evaluateStringExpression(right, exchange);
576 }
577
578 @Override
579 public String toString() {
580 return "append(" + left + ", " + right + ")";
581 }
582 };
583 }
584
585 /**
586 * Evaluates the expression on the given exchange and returns the String
587 * representation
588 *
589 * @param expression the expression to evaluate
590 * @param exchange the exchange to use to evaluate the expression
591 * @return the String representation of the expression or null if it could
592 * not be evaluated
593 */
594 public static <E extends Exchange> String evaluateStringExpression(Expression<E> expression, E exchange) {
595 Object value = expression.evaluate(exchange);
596 return exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
597 }
598
599 /**
600 * Returns an expression for the given system property
601 */
602 public static <E extends Exchange> Expression<E> systemProperty(final String name) {
603 return systemProperty(name, null);
604 }
605
606 /**
607 * Returns an expression for the given system property
608 */
609 public static <E extends Exchange> Expression<E> systemProperty(final String name,
610 final String defaultValue) {
611 return new Expression<E>() {
612 public Object evaluate(E exchange) {
613 return System.getProperty(name, defaultValue);
614 }
615 };
616 }
617
618 /**
619 * Returns an expression which returns the string concatenation value of the various
620 * expressions
621 *
622 * @param expressions the expression to be concatenated dynamically
623 * @return an expression which when evaluated will return the concatenated values
624 */
625 public static <E extends Exchange> Expression<E> concatExpression(final Collection<Expression> expressions) {
626 return concatExpression(expressions, null);
627 }
628
629 /**
630 * Returns an expression which returns the string concatenation value of the various
631 * expressions
632 *
633 * @param expressions the expression to be concatenated dynamically
634 * @param expression the text description of the expression
635 * @return an expression which when evaluated will return the concatenated values
636 */
637 public static <E extends Exchange> Expression<E> concatExpression(final Collection<Expression> expressions, final String expression) {
638 return new Expression<E>() {
639 public Object evaluate(E exchange) {
640 StringBuffer buffer = new StringBuffer();
641 for (Expression<E> expression : expressions) {
642 String text = evaluateStringExpression(expression, exchange);
643 if (text != null) {
644 buffer.append(text);
645 }
646 }
647 return buffer.toString();
648 }
649
650 @Override
651 public String toString() {
652 if (expression != null) {
653 return expression;
654 } else {
655 return "concat" + expressions;
656 }
657 }
658 };
659 }
660
661 /**
662 * Returns an Expression for the inbound message id
663 */
664 public static <E extends Exchange> Expression<E> messageIdExpression() {
665 return new Expression<E>() {
666 public Object evaluate(E exchange) {
667 return exchange.getIn().getMessageId();
668 }
669
670 @Override
671 public String toString() {
672 return "messageId";
673 }
674 };
675 }
676
677 public static <E extends Exchange> Expression<E> dateExpression(final String command, final String pattern) {
678 return new Expression<E>() {
679 public Object evaluate(E exchange) {
680 Date date;
681 if ("now".equals(command)) {
682 date = new Date();
683 } else if (command.startsWith("header.") || command.startsWith("in.header.")) {
684 String key = command.substring(command.lastIndexOf(".") + 1);
685 date = exchange.getIn().getHeader(key, Date.class);
686 if (date == null) {
687 throw new IllegalArgumentException("Could not find java.util.Date object at " + command);
688 }
689 } else if (command.startsWith("out.header.")) {
690 String key = command.substring(command.lastIndexOf(".") + 1);
691 date = exchange.getOut().getHeader(key, Date.class);
692 if (date == null) {
693 throw new IllegalArgumentException("Could not find java.util.Date object at " + command);
694 }
695 } else {
696 throw new IllegalArgumentException("Command not supported for dateExpression: " + command);
697 }
698
699 SimpleDateFormat df = new SimpleDateFormat(pattern);
700 return df.format(date);
701 }
702
703 @Override
704 public String toString() {
705 return "date(" + command + ":" + pattern + ")";
706 }
707 };
708 }
709
710 public static <E extends Exchange> Expression<E> simpleExpression(final String simple) {
711 return new Expression<E>() {
712 public Object evaluate(E exchange) {
713 // must call evalute to return the nested langauge evaluate when evaluating
714 // stacked expressions
715 return SimpleLanguage.simple(simple).evaluate(exchange);
716 }
717
718 @Override
719 public String toString() {
720 return "simple(" + simple + ")";
721 }
722 };
723 }
724
725 public static <E extends Exchange> Expression<E> beanExpression(final String bean) {
726 return new Expression<E>() {
727 public Object evaluate(E exchange) {
728 // must call evalute to return the nested langauge evaluate when evaluating
729 // stacked expressions
730 return BeanLanguage.bean(bean).evaluate(exchange);
731 }
732
733 @Override
734 public String toString() {
735 return "bean(" + bean + ")";
736 }
737 };
738 }
739
740 }