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.language.simple;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.Expression;
024    import org.apache.camel.Predicate;
025    import org.apache.camel.builder.ExpressionBuilder;
026    import org.apache.camel.builder.PredicateBuilder;
027    import org.apache.camel.language.IllegalSyntaxException;
028    import org.apache.camel.spi.Language;
029    import org.apache.camel.util.ObjectHelper;
030    
031    /**
032     * A <a href="http://activemq.apache.org/camel/simple.html>simple language</a>
033     * which maps simple property style notations to access headers and bodies.
034     * Examples of supported expressions are <p/>
035     * <ul>
036     * <li>in.header.foo or header.foo to access an inbound header called 'foo'</li>
037     * <li>in.body or body to access the inbound body</li>
038     * <li>out.header.foo to access an outbound header called 'foo'</li>
039     * <li>out.body to access the inbound body</li>
040     * <li>property.foo to access the exchange property called 'foo'</li>
041     * <li>sys.foo to access the system property called 'foo'</li>
042     * </ul>
043     *
044     * @version $Revision: 40913 $
045     */
046    public class SimpleLanguage implements Language {
047    
048        public static Expression simple(String expression) {
049            SimpleLanguage language = new SimpleLanguage();
050            return language.createExpression(expression);
051        }
052    
053        public Predicate<Exchange> createPredicate(String expression) {
054            return PredicateBuilder.toPredicate(createExpression(expression));
055        }
056    
057        public Expression<Exchange> createExpression(String expression) {
058            if (expression.indexOf("${") >= 0) {
059                return createComplexExpression(expression);
060            }
061            return createSimpleExpression(expression);
062        }
063    
064        protected Expression<Exchange> createComplexExpression(String expression) {
065            List<Expression> results = new ArrayList<Expression>();
066    
067            int pivot = 0;
068            int size = expression.length();
069            while (pivot < size) {
070                int idx = expression.indexOf("${", pivot);
071                if (idx < 0) {
072                    results.add(createConstantExpression(expression, pivot, size));
073                    break;
074                } else {
075                    if (pivot < idx) {
076                        results.add(createConstantExpression(expression, pivot, idx));
077                    }
078                    pivot = idx + 2;
079                    int endIdx = expression.indexOf("}", pivot);
080                    if (endIdx < 0) {
081                        throw new IllegalArgumentException("Expecting } but found end of string for simple expression: " + expression);
082                    }
083                    String simpleText = expression.substring(pivot, endIdx);
084    
085                    Expression simpleExpression = createSimpleExpression(simpleText);
086                    results.add(simpleExpression);
087                    pivot = endIdx + 1;
088                }
089            }
090            return ExpressionBuilder.concatExpression(results, expression);
091        }
092    
093        protected Expression createConstantExpression(String expression, int start, int end) {
094            return ExpressionBuilder.constantExpression(expression.substring(start, end));
095        }
096    
097        protected Expression<Exchange> createSimpleExpression(String expression) {
098            if (ObjectHelper.isEqualToAny(expression, "body", "in.body")) {
099                return ExpressionBuilder.bodyExpression();
100            } else if (ObjectHelper.equal(expression, "out.body")) {
101                return ExpressionBuilder.outBodyExpression();
102            }
103    
104            // in header expression
105            String remainder = ifStartsWithReturnRemainder("in.header.", expression);
106            if (remainder == null) {
107                remainder = ifStartsWithReturnRemainder("header.", expression);
108            }
109            if (remainder == null) {
110                remainder = ifStartsWithReturnRemainder("headers.", expression);
111            }
112            if (remainder == null) {
113                remainder = ifStartsWithReturnRemainder("in.headers.", expression);
114            }
115            if (remainder != null) {
116                return ExpressionBuilder.headerExpression(remainder);
117            }
118    
119            // out header expression
120            remainder = ifStartsWithReturnRemainder("out.header.", expression);
121            if (remainder == null) {
122                remainder = ifStartsWithReturnRemainder("out.headers.", expression);
123            }
124            if (remainder != null) {
125                return ExpressionBuilder.outHeaderExpression(remainder);
126            }
127    
128            // property
129            remainder = ifStartsWithReturnRemainder("property.", expression);
130            if (remainder != null) {
131                return ExpressionBuilder.propertyExpression(remainder);
132            }
133    
134            // system property
135            remainder = ifStartsWithReturnRemainder("sys.", expression);
136            if (remainder != null) {
137                return ExpressionBuilder.propertyExpression(remainder);
138            }
139            throw new IllegalSyntaxException(this, expression);
140        }
141    
142        protected String ifStartsWithReturnRemainder(String prefix, String text) {
143            if (text.startsWith(prefix)) {
144                String remainder = text.substring(prefix.length());
145                if (remainder.length() > 0) {
146                    return remainder;
147                }
148            }
149            return null;
150        }
151    }