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 */ 017package org.apache.camel.util; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.net.URL; 022import java.util.Enumeration; 023import java.util.HashMap; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Locale; 027import java.util.Map; 028import java.util.Properties; 029import java.util.Set; 030import java.util.SortedMap; 031import java.util.StringTokenizer; 032import java.util.TreeMap; 033 034import org.apache.camel.CamelContext; 035import org.apache.camel.Component; 036import org.apache.camel.Endpoint; 037import org.apache.camel.Exchange; 038import org.apache.camel.NoSuchBeanException; 039import org.apache.camel.NoSuchEndpointException; 040import org.apache.camel.component.properties.PropertiesComponent; 041import org.apache.camel.model.FromDefinition; 042import org.apache.camel.model.ProcessorDefinition; 043import org.apache.camel.model.ProcessorDefinitionHelper; 044import org.apache.camel.model.RouteDefinition; 045import org.apache.camel.spi.ClassResolver; 046import org.apache.camel.spi.RouteStartupOrder; 047import org.slf4j.Logger; 048import org.slf4j.LoggerFactory; 049 050import static org.apache.camel.util.ObjectHelper.isEmpty; 051import static org.apache.camel.util.ObjectHelper.isNotEmpty; 052import static org.apache.camel.util.ObjectHelper.notNull; 053 054/** 055 * A number of helper methods 056 * 057 * @version 058 */ 059public final class CamelContextHelper { 060 public static final String COMPONENT_BASE = "META-INF/services/org/apache/camel/component/"; 061 public static final String COMPONENT_DESCRIPTOR = "META-INF/services/org/apache/camel/component.properties"; 062 public static final String COMPONENT_DOCUMENTATION_PREFIX = "org/apache/camel/component/"; 063 public static final String MODEL_DESCRIPTOR = "META-INF/services/org/apache/camel/model.properties"; 064 public static final String MODEL_DOCUMENTATION_PREFIX = "org/apache/camel/model/"; 065 066 private static final Logger LOG = LoggerFactory.getLogger(CamelContextHelper.class); 067 068 /** 069 * Utility classes should not have a public constructor. 070 */ 071 private CamelContextHelper() { 072 } 073 074 /** 075 * Returns the mandatory endpoint for the given URI or the 076 * {@link org.apache.camel.NoSuchEndpointException} is thrown 077 */ 078 public static Endpoint getMandatoryEndpoint(CamelContext camelContext, String uri) 079 throws NoSuchEndpointException { 080 Endpoint endpoint = camelContext.getEndpoint(uri); 081 if (endpoint == null) { 082 throw new NoSuchEndpointException(uri); 083 } else { 084 return endpoint; 085 } 086 } 087 088 /** 089 * Returns the mandatory endpoint for the given URI and type or the 090 * {@link org.apache.camel.NoSuchEndpointException} is thrown 091 */ 092 public static <T extends Endpoint> T getMandatoryEndpoint(CamelContext camelContext, String uri, Class<T> type) { 093 Endpoint endpoint = getMandatoryEndpoint(camelContext, uri); 094 return ObjectHelper.cast(type, endpoint); 095 } 096 097 /** 098 * Converts the given value to the requested type 099 */ 100 public static <T> T convertTo(CamelContext context, Class<T> type, Object value) { 101 notNull(context, "camelContext"); 102 return context.getTypeConverter().convertTo(type, value); 103 } 104 105 /** 106 * Tried to convert the given value to the requested type 107 */ 108 public static <T> T tryConvertTo(CamelContext context, Class<T> type, Object value) { 109 notNull(context, "camelContext"); 110 return context.getTypeConverter().tryConvertTo(type, value); 111 } 112 113 /** 114 * Converts the given value to the specified type throwing an {@link IllegalArgumentException} 115 * if the value could not be converted to a non null value 116 */ 117 public static <T> T mandatoryConvertTo(CamelContext context, Class<T> type, Object value) { 118 T answer = convertTo(context, type, value); 119 if (answer == null) { 120 throw new IllegalArgumentException("Value " + value + " converted to " + type.getName() + " cannot be null"); 121 } 122 return answer; 123 } 124 125 /** 126 * Creates a new instance of the given type using the {@link org.apache.camel.spi.Injector} on the given 127 * {@link CamelContext} 128 */ 129 public static <T> T newInstance(CamelContext context, Class<T> beanType) { 130 return context.getInjector().newInstance(beanType); 131 } 132 133 /** 134 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 135 * {@link CamelContext} 136 */ 137 public static Object lookup(CamelContext context, String name) { 138 return context.getRegistry().lookupByName(name); 139 } 140 141 /** 142 * Look up the given named bean of the given type in the {@link org.apache.camel.spi.Registry} on the 143 * {@link CamelContext} 144 */ 145 public static <T> T lookup(CamelContext context, String name, Class<T> beanType) { 146 return context.getRegistry().lookupByNameAndType(name, beanType); 147 } 148 149 /** 150 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 151 * {@link CamelContext} and try to convert it to the given type. 152 */ 153 public static <T> T lookupAndConvert(CamelContext context, String name, Class<T> beanType) { 154 return tryConvertTo(context, beanType, lookup(context, name)); 155 } 156 157 /** 158 * Look up a bean of the give type in the {@link org.apache.camel.spi.Registry} on the 159 * {@link CamelContext} returning an instance if only one bean is present, 160 */ 161 public static <T> T findByType(CamelContext camelContext, Class<T> type) { 162 Set<T> set = camelContext.getRegistry().findByType(type); 163 if (set.size() == 1) { 164 return set.iterator().next(); 165 } 166 167 return null; 168 } 169 170 /** 171 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 172 * {@link CamelContext} or throws {@link NoSuchBeanException} if not found. 173 */ 174 public static Object mandatoryLookup(CamelContext context, String name) { 175 Object answer = lookup(context, name); 176 if (answer == null) { 177 throw new NoSuchBeanException(name); 178 } 179 return answer; 180 } 181 182 /** 183 * Look up the given named bean of the given type in the {@link org.apache.camel.spi.Registry} on the 184 * {@link CamelContext} or throws NoSuchBeanException if not found. 185 */ 186 public static <T> T mandatoryLookup(CamelContext context, String name, Class<T> beanType) { 187 T answer = lookup(context, name, beanType); 188 if (answer == null) { 189 throw new NoSuchBeanException(name, beanType.getName()); 190 } 191 return answer; 192 } 193 194 /** 195 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 196 * {@link CamelContext} and convert it to the given type or throws NoSuchBeanException if not found. 197 */ 198 public static <T> T mandatoryLookupAndConvert(CamelContext context, String name, Class<T> beanType) { 199 Object value = lookup(context, name); 200 if (value == null) { 201 throw new NoSuchBeanException(name, beanType.getName()); 202 } 203 return convertTo(context, beanType, value); 204 } 205 206 /** 207 * Evaluates the @EndpointInject annotation using the given context 208 */ 209 public static Endpoint getEndpointInjection(CamelContext camelContext, String uri, String ref, String injectionPointName, boolean mandatory) { 210 if (ObjectHelper.isNotEmpty(uri) && ObjectHelper.isNotEmpty(ref)) { 211 throw new IllegalArgumentException("Both uri and name is provided, only either one is allowed: uri=" + uri + ", ref=" + ref); 212 } 213 214 Endpoint endpoint; 215 if (isNotEmpty(uri)) { 216 endpoint = camelContext.getEndpoint(uri); 217 } else { 218 // if a ref is given then it should be possible to lookup 219 // otherwise we do not catch situations where there is a typo etc 220 if (isNotEmpty(ref)) { 221 endpoint = mandatoryLookup(camelContext, ref, Endpoint.class); 222 } else { 223 if (isEmpty(ref)) { 224 ref = injectionPointName; 225 } 226 if (mandatory) { 227 endpoint = mandatoryLookup(camelContext, ref, Endpoint.class); 228 } else { 229 endpoint = lookup(camelContext, ref, Endpoint.class); 230 } 231 } 232 } 233 return endpoint; 234 } 235 236 /** 237 * Gets the maximum cache pool size. 238 * <p/> 239 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_CACHE_POOL_SIZE}. 240 * If no property has been set, then it will fallback to return a size of 1000. 241 * 242 * @param camelContext the camel context 243 * @return the maximum cache size 244 * @throws IllegalArgumentException is thrown if the property is illegal 245 */ 246 public static int getMaximumCachePoolSize(CamelContext camelContext) throws IllegalArgumentException { 247 if (camelContext != null) { 248 String s = camelContext.getGlobalOption(Exchange.MAXIMUM_CACHE_POOL_SIZE); 249 if (s != null) { 250 try { 251 // we cannot use Camel type converters as they may not be ready this early 252 Integer size = Integer.valueOf(s); 253 if (size == null || size <= 0) { 254 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_CACHE_POOL_SIZE + " must be a positive number, was: " + s); 255 } 256 return size; 257 } catch (NumberFormatException e) { 258 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_CACHE_POOL_SIZE + " must be a positive number, was: " + s, e); 259 } 260 } 261 } 262 263 // 1000 is the default fallback 264 return 1000; 265 } 266 267 /** 268 * Gets the maximum endpoint cache size. 269 * <p/> 270 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_ENDPOINT_CACHE_SIZE}. 271 * If no property has been set, then it will fallback to return a size of 1000. 272 * 273 * @param camelContext the camel context 274 * @return the maximum cache size 275 * @throws IllegalArgumentException is thrown if the property is illegal 276 */ 277 public static int getMaximumEndpointCacheSize(CamelContext camelContext) throws IllegalArgumentException { 278 if (camelContext != null) { 279 String s = camelContext.getGlobalOption(Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE); 280 if (s != null) { 281 // we cannot use Camel type converters as they may not be ready this early 282 try { 283 Integer size = Integer.valueOf(s); 284 if (size == null || size <= 0) { 285 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE + " must be a positive number, was: " + s); 286 } 287 return size; 288 } catch (NumberFormatException e) { 289 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE + " must be a positive number, was: " + s, e); 290 } 291 } 292 } 293 294 // 1000 is the default fallback 295 return 1000; 296 } 297 298 /** 299 * Gets the maximum transformer cache size. 300 * <p/> 301 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_TRANSFORMER_CACHE_SIZE}. 302 * If no property has been set, then it will fallback to return a size of 1000. 303 * 304 * @param camelContext the camel context 305 * @return the maximum cache size 306 * @throws IllegalArgumentException is thrown if the property is illegal 307 */ 308 public static int getMaximumTransformerCacheSize(CamelContext camelContext) throws IllegalArgumentException { 309 if (camelContext != null) { 310 String s = camelContext.getGlobalOption(Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE); 311 if (s != null) { 312 // we cannot use Camel type converters as they may not be ready this early 313 try { 314 Integer size = Integer.valueOf(s); 315 if (size == null || size <= 0) { 316 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE + " must be a positive number, was: " + s); 317 } 318 return size; 319 } catch (NumberFormatException e) { 320 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE + " must be a positive number, was: " + s, e); 321 } 322 } 323 } 324 325 // 1000 is the default fallback 326 return 1000; 327 } 328 329 /** 330 * Gets the maximum validator cache size. 331 * <p/> 332 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_VALIDATOR_CACHE_SIZE}. 333 * If no property has been set, then it will fallback to return a size of 1000. 334 * 335 * @param camelContext the camel context 336 * @return the maximum cache size 337 * @throws IllegalArgumentException is thrown if the property is illegal 338 */ 339 public static int getMaximumValidatorCacheSize(CamelContext camelContext) throws IllegalArgumentException { 340 if (camelContext != null) { 341 String s = camelContext.getGlobalOption(Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE); 342 if (s != null) { 343 // we cannot use Camel type converters as they may not be ready this early 344 try { 345 Integer size = Integer.valueOf(s); 346 if (size == null || size <= 0) { 347 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE + " must be a positive number, was: " + s); 348 } 349 return size; 350 } catch (NumberFormatException e) { 351 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE + " must be a positive number, was: " + s, e); 352 } 353 } 354 } 355 356 // 1000 is the default fallback 357 return 1000; 358 } 359 360 /** 361 * Parses the given text and handling property placeholders as well 362 * 363 * @param camelContext the camel context 364 * @param text the text 365 * @return the parsed text, or <tt>null</tt> if the text was <tt>null</tt> 366 * @throws Exception is thrown if illegal argument 367 */ 368 public static String parseText(CamelContext camelContext, String text) throws Exception { 369 // ensure we support property placeholders 370 return camelContext.resolvePropertyPlaceholders(text); 371 } 372 373 /** 374 * Parses the given text and converts it to an Integer and handling property placeholders as well 375 * 376 * @param camelContext the camel context 377 * @param text the text 378 * @return the integer vale, or <tt>null</tt> if the text was <tt>null</tt> 379 * @throws Exception is thrown if illegal argument or type conversion not possible 380 */ 381 public static Integer parseInteger(CamelContext camelContext, String text) throws Exception { 382 // ensure we support property placeholders 383 String s = camelContext.resolvePropertyPlaceholders(text); 384 if (s != null) { 385 try { 386 return camelContext.getTypeConverter().mandatoryConvertTo(Integer.class, s); 387 } catch (NumberFormatException e) { 388 if (s.equals(text)) { 389 throw new IllegalArgumentException("Error parsing [" + s + "] as an Integer.", e); 390 } else { 391 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as an Integer.", e); 392 } 393 } 394 } 395 return null; 396 } 397 398 /** 399 * Parses the given text and converts it to an Long and handling property placeholders as well 400 * 401 * @param camelContext the camel context 402 * @param text the text 403 * @return the long vale, or <tt>null</tt> if the text was <tt>null</tt> 404 * @throws Exception is thrown if illegal argument or type conversion not possible 405 */ 406 public static Long parseLong(CamelContext camelContext, String text) throws Exception { 407 // ensure we support property placeholders 408 String s = camelContext.resolvePropertyPlaceholders(text); 409 if (s != null) { 410 try { 411 return camelContext.getTypeConverter().mandatoryConvertTo(Long.class, s); 412 } catch (NumberFormatException e) { 413 if (s.equals(text)) { 414 throw new IllegalArgumentException("Error parsing [" + s + "] as a Long.", e); 415 } else { 416 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Long.", e); 417 } 418 } 419 } 420 return null; 421 } 422 423 /** 424 * Parses the given text and converts it to a Double and handling property placeholders as well 425 * 426 * @param camelContext the camel context 427 * @param text the text 428 * @return the double vale, or <tt>null</tt> if the text was <tt>null</tt> 429 * @throws Exception is thrown if illegal argument or type conversion not possible 430 */ 431 public static Double parseDouble(CamelContext camelContext, String text) throws Exception { 432 // ensure we support property placeholders 433 String s = camelContext.resolvePropertyPlaceholders(text); 434 if (s != null) { 435 try { 436 return camelContext.getTypeConverter().mandatoryConvertTo(Double.class, s); 437 } catch (NumberFormatException e) { 438 if (s.equals(text)) { 439 throw new IllegalArgumentException("Error parsing [" + s + "] as an Integer.", e); 440 } else { 441 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as an Integer.", e); 442 } 443 } 444 } 445 return null; 446 } 447 448 /** 449 * Parses the given text and converts it to an Boolean and handling property placeholders as well 450 * 451 * @param camelContext the camel context 452 * @param text the text 453 * @return the boolean vale, or <tt>null</tt> if the text was <tt>null</tt> 454 * @throws Exception is thrown if illegal argument or type conversion not possible 455 */ 456 public static Boolean parseBoolean(CamelContext camelContext, String text) throws Exception { 457 // ensure we support property placeholders 458 String s = camelContext.resolvePropertyPlaceholders(text); 459 if (s != null) { 460 s = s.trim().toLowerCase(Locale.ENGLISH); 461 if (s.equals("true") || s.equals("false")) { 462 return "true".equals(s) ? Boolean.TRUE : Boolean.FALSE; 463 } else { 464 if (s.equals(text)) { 465 throw new IllegalArgumentException("Error parsing [" + s + "] as a Boolean."); 466 } else { 467 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Boolean."); 468 } 469 } 470 } 471 return null; 472 } 473 474 /** 475 * Finds all possible Components on the classpath, already registered in {@link org.apache.camel.CamelContext}, 476 * and from the {@link org.apache.camel.spi.Registry}. 477 */ 478 public static SortedMap<String, Properties> findComponents(CamelContext camelContext) throws LoadPropertiesException { 479 ClassResolver resolver = camelContext.getClassResolver(); 480 LOG.debug("Finding all components using class resolver: {} -> {}", new Object[]{resolver}); 481 Enumeration<URL> iter = resolver.loadAllResourcesAsURL(COMPONENT_DESCRIPTOR); 482 return findComponents(camelContext, iter); 483 } 484 485 public static SortedMap<String, Properties> findComponents(CamelContext camelContext, Enumeration<URL> componentDescriptionIter) 486 throws LoadPropertiesException { 487 488 SortedMap<String, Properties> map = new TreeMap<String, Properties>(); 489 while (componentDescriptionIter != null && componentDescriptionIter.hasMoreElements()) { 490 URL url = componentDescriptionIter.nextElement(); 491 LOG.trace("Finding components in url: {}", url); 492 try { 493 Properties properties = new Properties(); 494 properties.load(url.openStream()); 495 String names = properties.getProperty("components"); 496 if (names != null) { 497 StringTokenizer tok = new StringTokenizer(names); 498 while (tok.hasMoreTokens()) { 499 String name = tok.nextToken(); 500 501 // try to find the class name for this component 502 String className = null; 503 InputStream is = null; 504 try { 505 // now load the component name resource so we can grab its properties and the class name 506 Enumeration<URL> urls = camelContext.getClassResolver().loadAllResourcesAsURL(COMPONENT_BASE + name); 507 if (urls != null && urls.hasMoreElements()) { 508 is = urls.nextElement().openStream(); 509 } 510 if (is != null) { 511 Properties compProperties = new Properties(); 512 compProperties.load(is); 513 if (!compProperties.isEmpty()) { 514 className = compProperties.getProperty("class"); 515 } 516 } 517 } catch (Exception e) { 518 // ignore 519 } finally { 520 IOHelper.close(is); 521 } 522 523 // inherit properties we loaded first, as it has maven details 524 Properties prop = new Properties(); 525 prop.putAll(properties); 526 if (camelContext.hasComponent(name) != null) { 527 prop.put("component", camelContext.getComponent(name)); 528 } 529 if (className != null) { 530 prop.put("class", className); 531 } 532 prop.put("name", name); 533 map.put(name, prop); 534 } 535 } 536 } catch (IOException e) { 537 throw new LoadPropertiesException(url, e); 538 } 539 } 540 541 // lets see what other components are registered on camel context 542 List<String> names = camelContext.getComponentNames(); 543 for (String name : names) { 544 if (!map.containsKey(name)) { 545 Component component = camelContext.getComponent(name); 546 if (component != null) { 547 Properties properties = new Properties(); 548 properties.put("component", component); 549 properties.put("class", component.getClass().getName()); 550 properties.put("name", name); 551 // override default component if name clash 552 map.put(name, properties); 553 } 554 } 555 } 556 557 // lets see what other components are in the registry 558 Map<String, Component> beanMap = camelContext.getRegistry().findByTypeWithName(Component.class); 559 Set<Map.Entry<String, Component>> entries = beanMap.entrySet(); 560 for (Map.Entry<String, Component> entry : entries) { 561 String name = entry.getKey(); 562 if (!map.containsKey(name)) { 563 Component component = entry.getValue(); 564 if (component != null) { 565 Properties properties = new Properties(); 566 properties.put("component", component); 567 properties.put("class", component.getClass().getName()); 568 properties.put("name", name); 569 map.put(name, properties); 570 } 571 } 572 } 573 return map; 574 } 575 576 /** 577 * Find information about all the EIPs from camel-core. 578 */ 579 public static SortedMap<String, Properties> findEips(CamelContext camelContext) throws LoadPropertiesException { 580 SortedMap<String, Properties> answer = new TreeMap<String, Properties>(); 581 582 ClassResolver resolver = camelContext.getClassResolver(); 583 LOG.debug("Finding all EIPs using class resolver: {} -> {}", new Object[]{resolver}); 584 URL url = resolver.loadResourceAsURL(MODEL_DESCRIPTOR); 585 if (url != null) { 586 InputStream is = null; 587 try { 588 is = url.openStream(); 589 String all = IOHelper.loadText(is); 590 String[] lines = all.split("\n"); 591 for (String line : lines) { 592 if (line.startsWith("#")) { 593 continue; 594 } 595 596 Properties prop = new Properties(); 597 prop.put("name", line); 598 599 String description = null; 600 String label = null; 601 String javaType = null; 602 String title = null; 603 604 // enrich with more meta-data 605 String json = camelContext.explainEipJson(line, false); 606 if (json != null) { 607 List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("model", json, false); 608 609 for (Map<String, String> row : rows) { 610 if (row.get("title") != null) { 611 title = row.get("title"); 612 } 613 if (row.get("description") != null) { 614 description = row.get("description"); 615 } 616 if (row.get("label") != null) { 617 label = row.get("label"); 618 } 619 if (row.get("javaType") != null) { 620 javaType = row.get("javaType"); 621 } 622 } 623 } 624 625 if (title != null) { 626 prop.put("title", title); 627 } 628 if (description != null) { 629 prop.put("description", description); 630 } 631 if (label != null) { 632 prop.put("label", label); 633 } 634 if (javaType != null) { 635 prop.put("class", javaType); 636 } 637 638 answer.put(line, prop); 639 } 640 } catch (IOException e) { 641 throw new LoadPropertiesException(url, e); 642 } finally { 643 IOHelper.close(is); 644 } 645 } 646 647 return answer; 648 } 649 650 /** 651 * Gets the route startup order for the given route id 652 * 653 * @param camelContext the camel context 654 * @param routeId the id of the route 655 * @return the startup order, or <tt>0</tt> if not possible to determine 656 */ 657 public static int getRouteStartupOrder(CamelContext camelContext, String routeId) { 658 for (RouteStartupOrder order : camelContext.getRouteStartupOrder()) { 659 if (order.getRoute().getId().equals(routeId)) { 660 return order.getStartupOrder(); 661 } 662 } 663 return 0; 664 } 665 666 /** 667 * Lookup the {@link org.apache.camel.component.properties.PropertiesComponent} from the {@link org.apache.camel.CamelContext}. 668 * <p/> 669 * @param camelContext the camel context 670 * @param autoCreate whether to automatic create a new default {@link org.apache.camel.component.properties.PropertiesComponent} if no custom component 671 * has been configured. 672 * @return the properties component, or <tt>null</tt> if none has been defined, and auto create is <tt>false</tt>. 673 */ 674 public static Component lookupPropertiesComponent(CamelContext camelContext, boolean autoCreate) { 675 // no existing properties component so lookup and add as component if possible 676 PropertiesComponent answer = (PropertiesComponent) camelContext.hasComponent("properties"); 677 if (answer == null) { 678 // lookup what is stored under properties, as it may not be the Camel properties component 679 Object found = camelContext.getRegistry().lookupByName("properties"); 680 if (found != null && found instanceof PropertiesComponent) { 681 answer = (PropertiesComponent) found; 682 camelContext.addComponent("properties", answer); 683 } 684 } 685 if (answer == null && autoCreate) { 686 // create a default properties component to be used as there may be default values we can use 687 LOG.info("No existing PropertiesComponent has been configured, creating a new default PropertiesComponent with name: properties"); 688 // do not auto create using getComponent as spring auto-wire by constructor causes a side effect 689 answer = new PropertiesComponent(true); 690 camelContext.addComponent("properties", answer); 691 } 692 return answer; 693 } 694 695 /** 696 * Checks if any of the Camel routes is using an EIP with the given name 697 * 698 * @param camelContext the Camel context 699 * @param name the name of the EIP 700 * @return <tt>true</tt> if in use, <tt>false</tt> if not 701 */ 702 public static boolean isEipInUse(CamelContext camelContext, String name) { 703 for (RouteDefinition route : camelContext.getRouteDefinitions()) { 704 for (FromDefinition from : route.getInputs()) { 705 if (name.equals(from.getShortName())) { 706 return true; 707 } 708 } 709 Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class); 710 while (it.hasNext()) { 711 ProcessorDefinition def = it.next(); 712 if (name.equals(def.getShortName())) { 713 return true; 714 } 715 } 716 } 717 return false; 718 } 719 720 /** 721 * Inspects the given object and resolves any property placeholders from its properties. 722 * <p/> 723 * This implementation will check all the getter/setter pairs on this instance and for all the values 724 * (which is a String type) will be property placeholder resolved. 725 * 726 * @param camelContext the Camel context 727 * @param target the object that should have the properties (eg getter/setter) resolved 728 * @throws Exception is thrown if property placeholders was used and there was an error resolving them 729 * @see org.apache.camel.CamelContext#resolvePropertyPlaceholders(String) 730 * @see org.apache.camel.component.properties.PropertiesComponent 731 */ 732 public static void resolvePropertyPlaceholders(CamelContext camelContext, Object target) throws Exception { 733 LOG.trace("Resolving property placeholders for: {}", target); 734 735 // find all getter/setter which we can use for property placeholders 736 Map<String, Object> properties = new HashMap<String, Object>(); 737 IntrospectionSupport.getProperties(target, properties, null); 738 739 Map<String, Object> changedProperties = new HashMap<String, Object>(); 740 if (!properties.isEmpty()) { 741 LOG.trace("There are {} properties on: {}", properties.size(), target); 742 // lookup and resolve properties for String based properties 743 for (Map.Entry<String, Object> entry : properties.entrySet()) { 744 // the name is always a String 745 String name = entry.getKey(); 746 Object value = entry.getValue(); 747 if (value instanceof String) { 748 // value must be a String, as a String is the key for a property placeholder 749 String text = (String) value; 750 text = camelContext.resolvePropertyPlaceholders(text); 751 if (text != value) { 752 // invoke setter as the text has changed 753 boolean changed = IntrospectionSupport.setProperty(camelContext.getTypeConverter(), target, name, text); 754 if (!changed) { 755 throw new IllegalArgumentException("No setter to set property: " + name + " to: " + text + " on: " + target); 756 } 757 changedProperties.put(name, value); 758 if (LOG.isDebugEnabled()) { 759 LOG.debug("Changed property [{}] from: {} to: {}", new Object[]{name, value, text}); 760 } 761 } 762 } 763 } 764 } 765 } 766 767}