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.text.SimpleDateFormat;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.Comparator;
023    import java.util.Date;
024    import java.util.List;
025    import java.util.Scanner;
026    import java.util.regex.Pattern;
027    
028    import org.apache.camel.Endpoint;
029    import org.apache.camel.Exchange;
030    import org.apache.camel.Expression;
031    import org.apache.camel.InvalidPayloadException;
032    import org.apache.camel.Message;
033    import org.apache.camel.NoSuchEndpointException;
034    import org.apache.camel.Producer;
035    import org.apache.camel.component.bean.BeanInvocation;
036    import org.apache.camel.impl.ExpressionAdapter;
037    import org.apache.camel.language.bean.BeanLanguage;
038    import org.apache.camel.spi.Language;
039    import org.apache.camel.util.ExchangeHelper;
040    import org.apache.camel.util.FileUtil;
041    import org.apache.camel.util.ObjectHelper;
042    
043    /**
044     * A helper class for working with <a href="http://camel.apache.org/expression.html">expressions</a>.
045     *
046     * @version $Revision: 899932 $
047     */
048    public final class ExpressionBuilder {
049    
050        /**
051         * Utility classes should not have a public constructor.
052         */
053        private ExpressionBuilder() {
054        }
055    
056        /**
057         * Returns an expression for the header value with the given name
058         * <p/>
059         * Will fallback and look in properties if not found in headers.
060         *
061         * @param headerName the name of the header the expression will return
062         * @return an expression object which will return the header value
063         */
064        public static Expression headerExpression(final String headerName) {
065            return new ExpressionAdapter() {
066                public Object evaluate(Exchange exchange) {
067                    Object header = exchange.getIn().getHeader(headerName);
068                    if (header == null) {
069                        // fall back on a property
070                        header = exchange.getProperty(headerName);
071                    }
072                    return header;
073                }
074    
075                @Override
076                public String toString() {
077                    return "header(" + headerName + ")";
078                }
079            };
080        }
081    
082        /**
083         * Returns an expression for the inbound message headers
084         *
085         * @return an expression object which will return the inbound headers
086         */
087        public static Expression headersExpression() {
088            return new ExpressionAdapter() {
089                public Object evaluate(Exchange exchange) {
090                    return exchange.getIn().getHeaders();
091                }
092    
093                @Override
094                public String toString() {
095                    return "headers";
096                }
097            };
098        }
099    
100        /**
101         * Returns an expression for the out header value with the given name
102         * <p/>
103         * Will fallback and look in properties if not found in headers.
104         *
105         * @param headerName the name of the header the expression will return
106         * @return an expression object which will return the header value
107         */
108        public static Expression outHeaderExpression(final String headerName) {
109            return new ExpressionAdapter() {
110                public Object evaluate(Exchange exchange) {
111                    if (!exchange.hasOut()) {
112                        return null;
113                    }
114    
115                    Message out = exchange.getOut();
116                    Object header = out.getHeader(headerName);
117                    if (header == null) {
118                        // lets try the exchange header
119                        header = exchange.getProperty(headerName);
120                    }
121                    return header;
122                }
123    
124                @Override
125                public String toString() {
126                    return "outHeader(" + headerName + ")";
127                }
128            };
129        }
130    
131        /**
132         * Returns an expression for the outbound message headers
133         *
134         * @return an expression object which will return the headers
135         */
136        public static Expression outHeadersExpression() {
137            return new ExpressionAdapter() {
138                public Object evaluate(Exchange exchange) {
139                    return exchange.getOut().getHeaders();
140                }
141    
142                @Override
143                public String toString() {
144                    return "outHeaders";
145                }
146            };
147        }
148    
149        /**
150         * Returns an expression for an exception set on the exchange
151         *
152         * @see Exchange#getException()
153         * @return an expression object which will return the exception set on the exchange
154         */
155        public static Expression exchangeExceptionExpression() {
156            return new ExpressionAdapter() {
157                public Object evaluate(Exchange exchange) {
158                    Exception exception = exchange.getException();
159                    if (exception == null) {
160                        exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
161                    }
162                    return exception;
163                }
164    
165                @Override
166                public String toString() {
167                    return "exchangeException";
168                }
169            };
170        }   
171        
172        /**
173         * Returns an expression for an exception set on the exchange
174         * <p/>
175         * Is used to get the caused exception that typically have been wrapped in some sort
176         * of Camel wrapper exception
177         * @param type the exception type
178         * @see Exchange#getException(Class)
179         * @return an expression object which will return the exception set on the exchange
180         */
181        public static Expression exchangeExceptionExpression(final Class<Exception> type) {
182            return new ExpressionAdapter() {
183                public Object evaluate(Exchange exchange) {
184                    Exception exception = exchange.getException(type);
185                    if (exception == null) {
186                        exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
187                        return ObjectHelper.getException(type, exception);
188                    }
189                    return exception;
190                }
191    
192                @Override
193                public String toString() {
194                    return "exchangeException[" + type + "]";
195                }
196            };
197        }
198    
199        /**
200         * Returns an expression for the type converter
201         *
202         * @return an expression object which will return the type converter
203         */
204        public static Expression typeConverterExpression() {
205            return new ExpressionAdapter() {
206                public Object evaluate(Exchange exchange) {
207                    return exchange.getContext().getTypeConverter();
208                }
209    
210                @Override
211                public String toString() {
212                    return "typeConverter";
213                }
214            };
215        }
216    
217        /**
218         * Returns an expression for the {@link org.apache.camel.spi.Registry}
219         *
220         * @return an expression object which will return the registry
221         */
222        public static Expression registryExpression() {
223            return new ExpressionAdapter() {
224                public Object evaluate(Exchange exchange) {
225                    return exchange.getContext().getRegistry();
226                }
227    
228                @Override
229                public String toString() {
230                    return "registry";
231                }
232            };
233        }
234    
235        /**
236         * Returns an expression for the {@link org.apache.camel.CamelContext}
237         *
238         * @return an expression object which will return the camel context
239         */
240        public static Expression camelContextExpression() {
241            return new ExpressionAdapter() {
242                public Object evaluate(Exchange exchange) {
243                    return exchange.getContext();
244                }
245    
246                @Override
247                public String toString() {
248                    return "camelContext";
249                }
250            };
251        }
252    
253        /**
254         * Returns an expression for an exception message set on the exchange
255         *
256         * @see <tt>Exchange.getException().getMessage()</tt>
257         * @return an expression object which will return the exception message set on the exchange
258         */
259        public static Expression exchangeExceptionMessageExpression() {
260            return new ExpressionAdapter() {
261                public Object evaluate(Exchange exchange) {
262                    Exception exception = exchange.getException();
263                    if (exception == null) {
264                        exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
265                    }
266                    return exception != null ? exception.getMessage() : null;
267                }
268    
269                @Override
270                public String toString() {
271                    return "exchangeExceptionMessage";
272                }
273            };
274        }
275    
276        /**
277         * Returns an expression for the property value of exchange with the given name
278         *
279         * @param propertyName the name of the property the expression will return
280         * @return an expression object which will return the property value
281         */
282        public static Expression propertyExpression(final String propertyName) {
283            return new ExpressionAdapter() {
284                public Object evaluate(Exchange exchange) {
285                    return exchange.getProperty(propertyName);
286                }
287    
288                @Override
289                public String toString() {
290                    return "property(" + propertyName + ")";
291                }
292            };
293        }
294    
295        /**
296         * Returns an expression for the properties of exchange
297         *
298         * @return an expression object which will return the properties
299         */
300        public static Expression propertiesExpression() {
301            return new ExpressionAdapter() {
302                public Object evaluate(Exchange exchange) {
303                    return exchange.getProperties();
304                }
305    
306                @Override
307                public String toString() {
308                    return "properties";
309                }
310            };
311        }
312        
313        /**
314         * Returns an expression for the properties of the camel context
315         *
316         * @return an expression object which will return the properties
317         */
318        public static Expression camelContextPropertiesExpression() {
319            return new ExpressionAdapter() {
320                public Object evaluate(Exchange exchange) {
321                    return exchange.getContext().getProperties();
322                }
323    
324                @Override
325                public String toString() {
326                    return "camelContextProperties";
327                }
328            };
329        }
330        
331        /**
332         * Returns an expression for the property value of the camel context with the given name
333         *
334         * @param propertyName the name of the property the expression will return
335         * @return an expression object which will return the property value
336         */
337        public static Expression camelContextPropertyExpression(final String propertyName) {
338            return new ExpressionAdapter() {
339                public Object evaluate(Exchange exchange) {
340                    return exchange.getContext().getProperties().get(propertyName);
341                }
342    
343                @Override
344                public String toString() {
345                    return "camelContextProperty(" + propertyName + ")";
346                }
347            };
348        }
349    
350        /**
351         * Returns an expression for a system property value with the given name
352         *
353         * @param propertyName the name of the system property the expression will return
354         * @return an expression object which will return the system property value
355         */
356        public static Expression systemPropertyExpression(final String propertyName) {
357            return systemPropertyExpression(propertyName, null);
358        }
359    
360        /**
361         * Returns an expression for a system property value with the given name
362         *
363         * @param propertyName the name of the system property the expression will return
364         * @param defaultValue default value to return if no system property exists
365         * @return an expression object which will return the system property value
366         */
367        public static Expression systemPropertyExpression(final String propertyName,
368                                                          final String defaultValue) {
369            return new ExpressionAdapter() {
370                public Object evaluate(Exchange exchange) {
371                    return System.getProperty(propertyName, defaultValue);
372                }
373    
374                @Override
375                public String toString() {
376                    return "systemProperty(" + propertyName + ")";
377                }
378            };
379        }
380    
381        /**
382         * Returns an expression for the constant value
383         *
384         * @param value the value the expression will return
385         * @return an expression object which will return the constant value
386         */
387        public static Expression constantExpression(final Object value) {
388            return new ExpressionAdapter() {
389                public Object evaluate(Exchange exchange) {
390                    return value;
391                }
392    
393                @Override
394                public String toString() {
395                    return "" + value;
396                }
397            };
398        }
399    
400        /**
401         * Returns the expression for the exchanges inbound message body
402         */
403        public static Expression bodyExpression() {
404            return new ExpressionAdapter() {
405                public Object evaluate(Exchange exchange) {
406                    return exchange.getIn().getBody();
407                }
408    
409                @Override
410                public String toString() {
411                    return "body";
412                }
413            };
414        }
415    
416        /**
417         * Returns the expression for the exchanges inbound message body converted
418         * to the given type
419         */
420        public static <T> Expression bodyExpression(final Class<T> type) {
421            return new ExpressionAdapter() {
422                public Object evaluate(Exchange exchange) {
423                    return exchange.getIn().getBody(type);
424                }
425    
426                @Override
427                public String toString() {
428                    return "bodyAs[" + type.getName() + "]";
429                }
430            };
431        }
432    
433        /**
434         * Returns the expression for the exchanges inbound message body converted
435         * to the given type.
436         * <p/>
437         * Does <b>not</b> allow null bodies.
438         */
439        public static <T> Expression mandatoryBodyExpression(final Class<T> type) {
440            return mandatoryBodyExpression(type, false);
441        }
442    
443        /**
444         * Returns the expression for the exchanges inbound message body converted
445         * to the given type
446         *
447         * @param type the type
448         * @param nullBodyAllowed whether null bodies is allowed and if so a null is returned,
449         *                        otherwise an exception is thrown
450         */
451        public static <T> Expression mandatoryBodyExpression(final Class<T> type, final boolean nullBodyAllowed) {
452            return new ExpressionAdapter() {
453                public Object evaluate(Exchange exchange) {
454                    if (nullBodyAllowed) {
455                        if (exchange.getIn().getBody() == null) {
456                            return null;
457                        }
458    
459                        // if its a bean invocation then if it has no arguments then it should be threaded as null body allowed
460                        BeanInvocation bi = exchange.getIn().getBody(BeanInvocation.class);
461                        if (bi != null && (bi.getArgs() == null || bi.getArgs().length == 0 || bi.getArgs()[0] == null)) {
462                            return null;
463                        }
464                    }
465    
466                    try {
467                        return exchange.getIn().getMandatoryBody(type);
468                    } catch (InvalidPayloadException e) {
469                        throw ObjectHelper.wrapCamelExecutionException(exchange, e);
470                    }
471                }
472    
473                @Override
474                public String toString() {
475                    return "mandatoryBodyAs[" + type.getName() + "]";
476                }
477            };
478        }
479    
480        /**
481         * Returns the expression for the exchanges inbound message body type
482         */
483        public static Expression bodyTypeExpression() {
484            return new ExpressionAdapter() {
485                public Object evaluate(Exchange exchange) {
486                    return exchange.getIn().getBody().getClass();
487                }
488    
489                @Override
490                public String toString() {
491                    return "bodyType";
492                }
493            };
494        }
495    
496        /**
497         * Returns the expression for the out messages body
498         */
499        public static Expression outBodyExpression() {
500            return new ExpressionAdapter() {
501                public Object evaluate(Exchange exchange) {
502                    if (exchange.hasOut()) {
503                        return exchange.getOut().getBody();
504                    } else {
505                        return null;
506                    }
507                }
508    
509                @Override
510                public String toString() {
511                    return "outBody";
512                }
513            };
514        }
515    
516        /**
517         * Returns the expression for the exchanges outbound message body converted
518         * to the given type
519         */
520        public static <T> Expression outBodyExpression(final Class<T> type) {
521            return new ExpressionAdapter() {
522                public Object evaluate(Exchange exchange) {
523                    if (exchange.hasOut()) {
524                        return exchange.getOut().getBody(type);
525                    } else {
526                        return null;
527                    }
528                }
529    
530                @Override
531                public String toString() {
532                    return "outBodyAs[" + type.getName() + "]";
533                }
534            };
535        }
536    
537        /**
538         * Returns the expression for the fault messages body
539         */
540        public static Expression faultBodyExpression() {
541            return new ExpressionAdapter() {
542                public Object evaluate(Exchange exchange) {
543                    return exchange.getOut().isFault() ? exchange.getOut().getBody() : null;
544                }
545    
546                @Override
547                public String toString() {
548                    return "faultBody";
549                }
550            };
551        }
552    
553        /**
554         * Returns the expression for the exchanges fault message body converted
555         * to the given type
556         */
557        public static <T> Expression faultBodyExpression(final Class<T> type) {
558            return new ExpressionAdapter() {
559                public Object evaluate(Exchange exchange) {
560                    return exchange.getOut().isFault() ? exchange.getOut().getBody(type) : null;
561                }
562    
563                @Override
564                public String toString() {
565                    return "faultBodyAs[" + type.getName() + "]";
566                }
567            };
568        }
569    
570        /**
571         * Returns the expression for the exchange
572         */
573        public static Expression exchangeExpression() {
574            return new ExpressionAdapter() {
575                public Object evaluate(Exchange exchange) {
576                    return exchange;
577                }
578    
579                @Override
580                public String toString() {
581                    return "exchange";
582                }
583            };
584        }
585    
586        /**
587         * Returns the expression for the IN message
588         */
589        public static Expression inMessageExpression() {
590            return new ExpressionAdapter() {
591                public Object evaluate(Exchange exchange) {
592                    return exchange.getIn();
593                }
594    
595                @Override
596                public String toString() {
597                    return "inMessage";
598                }
599            };
600        }
601    
602        /**
603         * Returns the expression for the OUT message
604         */
605        public static Expression outMessageExpression() {
606            return new ExpressionAdapter() {
607                public Object evaluate(Exchange exchange) {
608                    return exchange.getOut();
609                }
610    
611                @Override
612                public String toString() {
613                    return "outMessage";
614                }
615            };
616        }
617    
618        /**
619         * Returns an expression which converts the given expression to the given type
620         */
621        @SuppressWarnings("unchecked")
622        public static Expression convertToExpression(final Expression expression, final Class type) {
623            return new ExpressionAdapter() {
624                public Object evaluate(Exchange exchange) {
625                    return expression.evaluate(exchange, type);
626                }
627    
628                @Override
629                public String toString() {
630                    return "" + expression + ".convertTo(" + type.getCanonicalName() + ".class)";
631                }
632            };
633        }
634    
635        /**
636         * Returns an expression which converts the given expression to the given type the type
637         * expression is evaluated to
638         */
639        public static Expression convertToExpression(final Expression expression, final Expression type) {
640            return new ExpressionAdapter() {
641                public Object evaluate(Exchange exchange) {
642                    return expression.evaluate(exchange, type.evaluate(exchange, Object.class).getClass());
643                }
644    
645                @Override
646                public String toString() {
647                    return "" + expression + ".convertToEvaluatedType(" + type + ")";
648                }
649            };
650        }
651    
652        /**
653         * Returns a tokenize expression which will tokenize the string with the
654         * given token
655         */
656        public static Expression tokenizeExpression(final Expression expression,
657                                                    final String token) {
658            return new ExpressionAdapter() {
659                public Object evaluate(Exchange exchange) {
660                    Object value = expression.evaluate(exchange, Object.class);
661                    Scanner scanner = ObjectHelper.getScanner(exchange, value);
662                    scanner.useDelimiter(token);
663                    return scanner;
664                }
665    
666                @Override
667                public String toString() {
668                    return "tokenize(" + expression + ", " + token + ")";
669                }
670            };
671        }
672    
673        /**
674         * Returns a tokenize expression which will tokenize the string with the
675         * given regex
676         */
677        public static Expression regexTokenizeExpression(final Expression expression,
678                                                         final String regexTokenizer) {
679            final Pattern pattern = Pattern.compile(regexTokenizer);
680            return new ExpressionAdapter() {
681                public Object evaluate(Exchange exchange) {
682                    Object value = expression.evaluate(exchange, Object.class);
683                    Scanner scanner = ObjectHelper.getScanner(exchange, value);
684                    scanner.useDelimiter(regexTokenizer);
685                    return scanner;
686                }
687    
688                @Override
689                public String toString() {
690                    return "regexTokenize(" + expression + ", " + pattern.pattern() + ")";
691                }
692            };
693        }
694    
695        /**
696         * Returns a sort expression which will sort the expression with the given comparator.
697         * <p/>
698         * The expression is evaluted as a {@link List} object to allow sorting.
699         */
700        @SuppressWarnings("unchecked")
701        public static Expression sortExpression(final Expression expression, final Comparator comparator) {
702            return new ExpressionAdapter() {
703                public Object evaluate(Exchange exchange) {
704                    List list = expression.evaluate(exchange, List.class);
705                    Collections.sort(list, comparator);
706                    return list;
707                }
708    
709                @Override
710                public String toString() {
711                    return "sort(" + expression + " by: " + comparator + ")";
712                }
713            };
714        }
715    
716        /**
717         * Transforms the expression into a String then performs the regex
718         * replaceAll to transform the String and return the result
719         */
720        public static Expression regexReplaceAll(final Expression expression,
721                                                 final String regex, final String replacement) {
722            final Pattern pattern = Pattern.compile(regex);
723            return new ExpressionAdapter() {
724                public Object evaluate(Exchange exchange) {
725                    String text = expression.evaluate(exchange, String.class);
726                    if (text == null) {
727                        return null;
728                    }
729                    return pattern.matcher(text).replaceAll(replacement);
730                }
731    
732                @Override
733                public String toString() {
734                    return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
735                }
736            };
737        }
738    
739        /**
740         * Transforms the expression into a String then performs the regex
741         * replaceAll to transform the String and return the result
742         */
743        public static Expression regexReplaceAll(final Expression expression,
744                                                 final String regex, final Expression replacementExpression) {
745    
746            final Pattern pattern = Pattern.compile(regex);
747            return new ExpressionAdapter() {
748                public Object evaluate(Exchange exchange) {
749                    String text = expression.evaluate(exchange, String.class);
750                    String replacement = replacementExpression.evaluate(exchange, String.class);
751                    if (text == null || replacement == null) {
752                        return null;
753                    }
754                    return pattern.matcher(text).replaceAll(replacement);
755                }
756    
757                @Override
758                public String toString() {
759                    return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
760                }
761            };
762        }
763    
764        /**
765         * Appends the String evaluations of the two expressions together
766         */
767        public static Expression append(final Expression left, final Expression right) {
768            return new ExpressionAdapter() {
769                public Object evaluate(Exchange exchange) {
770                    return left.evaluate(exchange, String.class) + right.evaluate(exchange, String.class);
771                }
772    
773                @Override
774                public String toString() {
775                    return "append(" + left + ", " + right + ")";
776                }
777            };
778        }
779    
780        /**
781         * Prepends the String evaluations of the two expressions together
782         */
783        public static Expression prepend(final Expression left, final Expression right) {
784            return new ExpressionAdapter() {
785                public Object evaluate(Exchange exchange) {
786                    return right.evaluate(exchange, String.class) + left.evaluate(exchange, String.class);
787                }
788    
789                @Override
790                public String toString() {
791                    return "prepend(" + left + ", " + right + ")";
792                }
793            };
794        }
795    
796        /**
797         * Returns an expression which returns the string concatenation value of the various
798         * expressions
799         *
800         * @param expressions the expression to be concatenated dynamically
801         * @return an expression which when evaluated will return the concatenated values
802         */
803        public static Expression concatExpression(final Collection<Expression> expressions) {
804            return concatExpression(expressions, null);
805        }
806    
807        /**
808         * Returns an expression which returns the string concatenation value of the various
809         * expressions
810         *
811         * @param expressions the expression to be concatenated dynamically
812         * @param expression the text description of the expression
813         * @return an expression which when evaluated will return the concatenated values
814         */
815        public static Expression concatExpression(final Collection<Expression> expressions, final String expression) {
816            return new ExpressionAdapter() {
817                public Object evaluate(Exchange exchange) {
818                    StringBuffer buffer = new StringBuffer();
819                    for (Expression expression : expressions) {
820                        String text = expression.evaluate(exchange, String.class);
821                        if (text != null) {
822                            buffer.append(text);
823                        }
824                    }
825                    return buffer.toString();
826                }
827    
828                @Override
829                public String toString() {
830                    if (expression != null) {
831                        return expression;
832                    } else {
833                        return "concat" + expressions;
834                    }
835                }
836            };
837        }
838    
839        /**
840         * Returns an Expression for the inbound message id
841         */
842        public static Expression messageIdExpression() {
843            return new ExpressionAdapter() {
844                public Object evaluate(Exchange exchange) {
845                    return exchange.getIn().getMessageId();
846                }
847    
848                @Override
849                public String toString() {
850                    return "messageId";
851                }
852            };
853        }
854    
855        public static Expression dateExpression(final String command, final String pattern) {
856            return new ExpressionAdapter() {
857                public Object evaluate(Exchange exchange) {
858                    Date date;
859                    if ("now".equals(command)) {
860                        date = new Date();
861                    } else if (command.startsWith("header.") || command.startsWith("in.header.")) {
862                        String key = command.substring(command.lastIndexOf('.') + 1);
863                        date = exchange.getIn().getHeader(key, Date.class);
864                        if (date == null) {
865                            throw new IllegalArgumentException("Cannot find java.util.Date object at command: " + command);
866                        }
867                    } else if (command.startsWith("out.header.")) {
868                        String key = command.substring(command.lastIndexOf('.') + 1);
869                        date = exchange.getOut().getHeader(key, Date.class);
870                        if (date == null) {
871                            throw new IllegalArgumentException("Cannot find java.util.Date object at command: " + command);
872                        }
873                    } else if ("file".equals(command)) {
874                        date = exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Date.class);
875                        if (date == null) {
876                            throw new IllegalArgumentException("Cannot find " + Exchange.FILE_LAST_MODIFIED + " header at command: " + command);
877                        }
878                    } else {
879                        throw new IllegalArgumentException("Command not supported for dateExpression: " + command);
880                    }
881    
882                    SimpleDateFormat df = new SimpleDateFormat(pattern);
883                    return df.format(date);
884                }
885    
886                @Override
887                public String toString() {
888                    return "date(" + command + ":" + pattern + ")";
889                }
890            };
891        }
892    
893        public static Expression simpleExpression(final String expression) {
894            return new ExpressionAdapter() {
895                public Object evaluate(Exchange exchange) {
896                    // resolve language using context to have a clear separation of packages
897                    // must call evaluate to return the nested language evaluate when evaluating
898                    // stacked expressions
899                    Language language = exchange.getContext().resolveLanguage("simple");
900                    return language.createExpression(expression).evaluate(exchange, Object.class);
901                }
902    
903                @Override
904                public String toString() {
905                    return "simple(" + expression + ")";
906                }
907            };
908        }
909    
910        public static Expression beanExpression(final String expression) {
911            return new ExpressionAdapter() {
912                public Object evaluate(Exchange exchange) {
913                    // resolve language using context to have a clear separation of packages
914                    // must call evaluate to return the nested language evaluate when evaluating
915                    // stacked expressions
916                    Language language = exchange.getContext().resolveLanguage("bean");
917                    return language.createExpression(expression).evaluate(exchange, Object.class);
918                }
919    
920                @Override
921                public String toString() {
922                    return "bean(" + expression + ")";
923                }
924            };
925        }
926        
927        public static Expression beanExpression(final Class<?> beanType, final String methodName) {
928            return BeanLanguage.bean(beanType, methodName);        
929        }
930    
931        public static Expression beanExpression(final Object bean, final String methodName) {
932            return BeanLanguage.bean(bean, methodName);        
933        }
934    
935        public static Expression beanExpression(final String beanRef, final String methodName) {
936            String expression = methodName != null ? beanRef + "." + methodName : beanRef;
937            return beanExpression(expression);
938        }
939    
940        /**
941         * Returns an expression processing the exchange to the given endpoint uri
942         *
943         * @param uri endpoint uri to send the exchange to
944         * @return an expression object which will return the OUT body
945         */
946        public static Expression toExpression(final String uri) {
947            return new ExpressionAdapter() {
948                public Object evaluate(Exchange exchange) {
949                    Endpoint endpoint = exchange.getContext().getEndpoint(uri);
950                    if (endpoint == null) {
951                        throw new NoSuchEndpointException(uri);
952                    }
953    
954                    Producer producer;
955                    try {
956                        producer = endpoint.createProducer();
957                        producer.start();
958                        producer.process(exchange);
959                        producer.stop();
960                    } catch (Exception e) {
961                        throw ObjectHelper.wrapRuntimeCamelException(e);
962                    }
963    
964                    // return the OUT body, but check for exchange pattern
965                    if (ExchangeHelper.isOutCapable(exchange)) {
966                        return exchange.getOut().getBody();
967                    } else {
968                        return exchange.getIn().getBody();
969                    }
970                }
971    
972                @Override
973                public String toString() {
974                    return "to(" + uri + ")";
975                }
976            };
977        }
978    
979        public static Expression fileNameExpression() {
980            return new ExpressionAdapter() {
981                public Object evaluate(Exchange exchange) {
982                    return exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
983                }
984    
985                @Override
986                public String toString() {
987                    return "file:name";
988                }
989            };
990        }
991    
992        public static Expression fileOnlyNameExpression() {
993            return new ExpressionAdapter() {
994                public Object evaluate(Exchange exchange) {
995                    String answer = exchange.getIn().getHeader(Exchange.FILE_NAME_ONLY, String.class);
996                    if (answer == null) {
997                        answer = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
998                        answer = FileUtil.stripPath(answer);
999                    }
1000                    return answer;
1001                }
1002    
1003                @Override
1004                public String toString() {
1005                    return "file:onlyname";
1006                }
1007            };
1008        }
1009    
1010        public static Expression fileNameNoExtensionExpression() {
1011            return new ExpressionAdapter() {
1012                public Object evaluate(Exchange exchange) {
1013                    String name = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
1014                    return FileUtil.stripExt(name);
1015                }
1016    
1017                @Override
1018                public String toString() {
1019                    return "file:name.noext";
1020                }
1021            };
1022        }
1023    
1024        public static Expression fileOnlyNameNoExtensionExpression() {
1025            return new ExpressionAdapter() {
1026                public Object evaluate(Exchange exchange) {
1027                    String name = fileOnlyNameExpression().evaluate(exchange, String.class);
1028                    return FileUtil.stripExt(name);
1029                }
1030    
1031                @Override
1032                public String toString() {
1033                    return "file:onlyname.noext";
1034                }
1035            };
1036        }
1037    
1038        public static Expression fileExtensionExpression() {
1039            return new ExpressionAdapter() {
1040                public Object evaluate(Exchange exchange) {
1041                    String name = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
1042                    if (name != null) {
1043                        return name.substring(name.lastIndexOf('.') + 1);
1044                    } else {
1045                        return null;
1046                    }
1047                }
1048    
1049                @Override
1050                public String toString() {
1051                    return "file:ext";
1052                }
1053            };
1054        }
1055    
1056        public static Expression fileParentExpression() {
1057            return new ExpressionAdapter() {
1058                public Object evaluate(Exchange exchange) {
1059                    return exchange.getIn().getHeader("CamelFileParent", String.class);
1060                }
1061    
1062                @Override
1063                public String toString() {
1064                    return "file:parent";
1065                }
1066            };
1067        }
1068    
1069        public static Expression filePathExpression() {
1070            return new ExpressionAdapter() {
1071                public Object evaluate(Exchange exchange) {
1072                    return exchange.getIn().getHeader("CamelFilePath", String.class);
1073                }
1074    
1075                @Override
1076                public String toString() {
1077                    return "file:path";
1078                }
1079            };
1080        }
1081    
1082        public static Expression fileAbsolutePathExpression() {
1083            return new ExpressionAdapter() {
1084                public Object evaluate(Exchange exchange) {
1085                    return exchange.getIn().getHeader("CamelFileAbsolutePath", String.class);
1086                }
1087    
1088                @Override
1089                public String toString() {
1090                    return "file:absolute.path";
1091                }
1092            };
1093        }
1094    
1095        public static Expression fileAbsoluteExpression() {
1096            return new ExpressionAdapter() {
1097                public Object evaluate(Exchange exchange) {
1098                    return exchange.getIn().getHeader("CamelFileAbsolute", Boolean.class);
1099                }
1100    
1101                @Override
1102                public String toString() {
1103                    return "file:absolute";
1104                }
1105            };
1106        }
1107    
1108        public static Expression fileSizeExpression() {
1109            return new ExpressionAdapter() {
1110                public Object evaluate(Exchange exchange) {
1111                    return exchange.getIn().getHeader("CamelFileLength", Long.class);
1112                }
1113    
1114                @Override
1115                public String toString() {
1116                    return "file:length";
1117                }
1118            };
1119        }
1120    
1121        public static Expression fileLastModifiedExpression() {
1122            return new ExpressionAdapter() {
1123                public Object evaluate(Exchange exchange) {
1124                    return exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Date.class);
1125                }
1126    
1127                @Override
1128                public String toString() {
1129                    return "file:modified";
1130                }
1131            };
1132        }
1133    
1134    }