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