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.spring; 018 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Map; 022 023import javax.xml.bind.annotation.XmlAccessType; 024import javax.xml.bind.annotation.XmlAccessorType; 025import javax.xml.bind.annotation.XmlAttribute; 026import javax.xml.bind.annotation.XmlElement; 027import javax.xml.bind.annotation.XmlElements; 028import javax.xml.bind.annotation.XmlRootElement; 029import javax.xml.bind.annotation.XmlTransient; 030 031import org.apache.camel.CamelContext; 032import org.apache.camel.LoggingLevel; 033import org.apache.camel.RoutesBuilder; 034import org.apache.camel.RuntimeCamelException; 035import org.apache.camel.ShutdownRoute; 036import org.apache.camel.ShutdownRunningTask; 037import org.apache.camel.TypeConverterExists; 038import org.apache.camel.builder.RouteBuilder; 039import org.apache.camel.component.properties.PropertiesComponent; 040import org.apache.camel.core.xml.AbstractCamelContextFactoryBean; 041import org.apache.camel.core.xml.AbstractCamelFactoryBean; 042import org.apache.camel.core.xml.CamelJMXAgentDefinition; 043import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition; 044import org.apache.camel.core.xml.CamelProxyFactoryDefinition; 045import org.apache.camel.core.xml.CamelServiceExporterDefinition; 046import org.apache.camel.core.xml.CamelStreamCachingStrategyDefinition; 047import org.apache.camel.model.ContextScanDefinition; 048import org.apache.camel.model.FaultToleranceConfigurationDefinition; 049import org.apache.camel.model.GlobalOptionsDefinition; 050import org.apache.camel.model.HystrixConfigurationDefinition; 051import org.apache.camel.model.InterceptDefinition; 052import org.apache.camel.model.InterceptFromDefinition; 053import org.apache.camel.model.InterceptSendToEndpointDefinition; 054import org.apache.camel.model.OnCompletionDefinition; 055import org.apache.camel.model.OnExceptionDefinition; 056import org.apache.camel.model.PackageScanDefinition; 057import org.apache.camel.model.Resilience4jConfigurationDefinition; 058import org.apache.camel.model.RestContextRefDefinition; 059import org.apache.camel.model.RouteBuilderDefinition; 060import org.apache.camel.model.RouteContextRefDefinition; 061import org.apache.camel.model.RouteDefinition; 062import org.apache.camel.model.ThreadPoolProfileDefinition; 063import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 064import org.apache.camel.model.dataformat.DataFormatsDefinition; 065import org.apache.camel.model.rest.RestConfigurationDefinition; 066import org.apache.camel.model.rest.RestDefinition; 067import org.apache.camel.model.transformer.TransformersDefinition; 068import org.apache.camel.model.validator.ValidatorsDefinition; 069import org.apache.camel.spi.Metadata; 070import org.apache.camel.spi.PackageScanFilter; 071import org.apache.camel.spi.Registry; 072import org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer; 073import org.apache.camel.spring.spi.XmlCamelContextConfigurer; 074import org.apache.camel.support.CamelContextHelper; 075import org.apache.camel.util.StopWatch; 076import org.slf4j.Logger; 077import org.slf4j.LoggerFactory; 078import org.springframework.beans.factory.DisposableBean; 079import org.springframework.beans.factory.FactoryBean; 080import org.springframework.beans.factory.InitializingBean; 081import org.springframework.beans.factory.config.BeanPostProcessor; 082import org.springframework.context.ApplicationContext; 083import org.springframework.context.ApplicationContextAware; 084import org.springframework.context.ApplicationListener; 085import org.springframework.context.Lifecycle; 086import org.springframework.context.Phased; 087import org.springframework.context.event.ContextRefreshedEvent; 088import org.springframework.core.Ordered; 089 090import static org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException; 091 092/** 093 * CamelContext using XML configuration. 094 */ 095@Metadata(label = "spring,configuration") 096@XmlRootElement(name = "camelContext") 097@XmlAccessorType(XmlAccessType.FIELD) 098public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<SpringCamelContext> 099 implements FactoryBean<SpringCamelContext>, InitializingBean, DisposableBean, ApplicationContextAware, Lifecycle, 100 Phased, ApplicationListener<ContextRefreshedEvent>, Ordered { 101 102 private static final Logger LOG = LoggerFactory.getLogger(CamelContextFactoryBean.class); 103 104 @XmlAttribute(name = "depends-on") @Metadata(displayName = "Depends On") 105 private String dependsOn; 106 @XmlAttribute 107 private String trace; 108 @XmlAttribute 109 private String backlogTrace; 110 @XmlAttribute 111 private String tracePattern; 112 @XmlAttribute 113 private String debug; 114 @XmlAttribute @Metadata(defaultValue = "false") 115 private String messageHistory; 116 @XmlAttribute @Metadata(defaultValue = "false") 117 private String logMask; 118 @XmlAttribute 119 private String logExhaustedMessageBody; 120 @XmlAttribute 121 private String streamCache; 122 @XmlAttribute 123 private String delayer; 124 @XmlAttribute 125 private String errorHandlerRef; 126 @XmlAttribute @Metadata(defaultValue = "true") 127 private String autoStartup; 128 @XmlAttribute @Metadata(defaultValue = "true") 129 private String shutdownEager; 130 @XmlAttribute @Metadata(displayName = "Use MDC Logging") 131 private String useMDCLogging; 132 @XmlAttribute @Metadata(displayName = "MDC Logging Keys Pattern") 133 private String mdcLoggingKeysPattern; 134 @XmlAttribute 135 private String useDataType; 136 @XmlAttribute 137 private String useBreadcrumb; 138 @XmlAttribute 139 private String allowUseOriginalMessage; 140 @XmlAttribute 141 private String caseInsensitiveHeaders; 142 @XmlAttribute 143 private String runtimeEndpointRegistryEnabled; 144 @XmlAttribute @Metadata(defaultValue = "#name#") 145 private String managementNamePattern; 146 @XmlAttribute @Metadata(defaultValue = "Camel (#camelId#) thread ##counter# - #name#") 147 private String threadNamePattern; 148 @XmlAttribute @Metadata(defaultValue = "Default") 149 private ShutdownRoute shutdownRoute; 150 @XmlAttribute @Metadata(defaultValue = "CompleteCurrentTaskOnly") 151 private ShutdownRunningTask shutdownRunningTask; 152 @XmlAttribute @Metadata(defaultValue = "true") 153 private String loadTypeConverters; 154 @XmlAttribute 155 private String typeConverterStatisticsEnabled; 156 @XmlAttribute 157 private String inflightRepositoryBrowseEnabled; 158 @XmlAttribute @Metadata(defaultValue = "Override") 159 private TypeConverterExists typeConverterExists; 160 @XmlAttribute @Metadata(defaultValue = "WARN") 161 private LoggingLevel typeConverterExistsLoggingLevel; 162 @XmlElement(name = "globalOptions") 163 private GlobalOptionsDefinition globalOptions; 164 @XmlElement(name = "propertyPlaceholder", type = CamelPropertyPlaceholderDefinition.class) 165 private CamelPropertyPlaceholderDefinition camelPropertyPlaceholder; 166 @XmlElement(name = "package") 167 private String[] packages = {}; 168 @XmlElement(name = "packageScan", type = PackageScanDefinition.class) 169 private PackageScanDefinition packageScan; 170 @XmlElement(name = "contextScan", type = ContextScanDefinition.class) 171 private ContextScanDefinition contextScan; 172 @XmlElement(name = "streamCaching", type = CamelStreamCachingStrategyDefinition.class) 173 private CamelStreamCachingStrategyDefinition camelStreamCachingStrategy; 174 @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class) @Metadata(displayName = "JMX Agent") 175 private CamelJMXAgentDefinition camelJMXAgent; 176 @XmlElements({ 177 @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class), 178 @XmlElement(name = "fluentTemplate", type = CamelFluentProducerTemplateFactoryBean.class), 179 @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class)}) 180 private List<AbstractCamelFactoryBean<?>> beansFactory; 181 @XmlElements({ 182 @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class), 183 @XmlElement(name = "export", type = CamelServiceExporterDefinition.class), 184 @XmlElement(name = "errorHandler", type = ErrorHandlerDefinition.class) }) 185 private List<?> beans; 186 @XmlElement(name = "defaultServiceCallConfiguration") 187 private ServiceCallConfigurationDefinition defaultServiceCallConfiguration; 188 @XmlElement(name = "serviceCallConfiguration", type = ServiceCallConfigurationDefinition.class) 189 private List<ServiceCallConfigurationDefinition> serviceCallConfigurations; 190 @XmlElement(name = "defaultHystrixConfiguration") 191 private HystrixConfigurationDefinition defaultHystrixConfiguration; 192 @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class) 193 private List<HystrixConfigurationDefinition> hystrixConfigurations; 194 @XmlElement(name = "defaultResilience4jConfiguration") 195 private Resilience4jConfigurationDefinition defaultResilience4jConfiguration; 196 @XmlElement(name = "resilience4jConfiguration", type = Resilience4jConfigurationDefinition.class) 197 private List<Resilience4jConfigurationDefinition> resilience4jConfigurations; 198 @XmlElement(name = "defaultFaultToleranceConfiguration") 199 private FaultToleranceConfigurationDefinition defaultFaultToleranceConfiguration; 200 @XmlElement(name = "faultToleranceConfiguration", type = Resilience4jConfigurationDefinition.class) 201 private List<FaultToleranceConfigurationDefinition> faultToleranceConfigurations; 202 @XmlElement(name = "routeBuilder") 203 private List<RouteBuilderDefinition> builderRefs = new ArrayList<>(); 204 @XmlElement(name = "routeContextRef") 205 private List<RouteContextRefDefinition> routeRefs = new ArrayList<>(); 206 @XmlElement(name = "restContextRef") 207 private List<RestContextRefDefinition> restRefs = new ArrayList<>(); 208 @XmlElement(name = "threadPoolProfile") 209 private List<ThreadPoolProfileDefinition> threadPoolProfiles; 210 @XmlElement(name = "threadPool") 211 private List<CamelThreadPoolFactoryBean> threadPools; 212 @XmlElement(name = "endpoint") 213 private List<CamelEndpointFactoryBean> endpoints; 214 @XmlElement(name = "dataFormats") 215 private DataFormatsDefinition dataFormats; 216 @XmlElement(name = "transformers") 217 private TransformersDefinition transformers; 218 @XmlElement(name = "validators") 219 private ValidatorsDefinition validators; 220 @XmlElement(name = "redeliveryPolicyProfile") 221 private List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies; 222 @XmlElement(name = "onException") 223 private List<OnExceptionDefinition> onExceptions = new ArrayList<>(); 224 @XmlElement(name = "onCompletion") 225 private List<OnCompletionDefinition> onCompletions = new ArrayList<>(); 226 @XmlElement(name = "intercept") 227 private List<InterceptDefinition> intercepts = new ArrayList<>(); 228 @XmlElement(name = "interceptFrom") 229 private List<InterceptFromDefinition> interceptFroms = new ArrayList<>(); 230 @XmlElement(name = "interceptSendToEndpoint") 231 private List<InterceptSendToEndpointDefinition> interceptSendToEndpoints = new ArrayList<>(); 232 @XmlElement(name = "restConfiguration") 233 private RestConfigurationDefinition restConfiguration; 234 @XmlElement(name = "rest") 235 private List<RestDefinition> rests = new ArrayList<>(); 236 @XmlElement(name = "route") 237 private List<RouteDefinition> routes = new ArrayList<>(); 238 @XmlTransient 239 private SpringCamelContext context; 240 @XmlTransient 241 private ClassLoader contextClassLoaderOnStart; 242 @XmlTransient 243 private ApplicationContext applicationContext; 244 @XmlTransient 245 private BeanPostProcessor beanPostProcessor; 246 @XmlTransient 247 private boolean implicitId; 248 249 @Override 250 public Class<SpringCamelContext> getObjectType() { 251 return SpringCamelContext.class; 252 } 253 254 @Override 255 protected <S> S getBeanForType(Class<S> clazz) { 256 S bean = null; 257 String[] names = getApplicationContext().getBeanNamesForType(clazz, true, true); 258 if (names.length == 1) { 259 bean = getApplicationContext().getBean(names[0], clazz); 260 } 261 if (bean == null) { 262 ApplicationContext parentContext = getApplicationContext().getParent(); 263 if (parentContext != null) { 264 names = parentContext.getBeanNamesForType(clazz, true, true); 265 if (names.length == 1) { 266 bean = parentContext.getBean(names[0], clazz); 267 } 268 } 269 } 270 return bean; 271 } 272 273 @Override 274 protected void findRouteBuildersByPackageScan(String[] packages, PackageScanFilter filter, List<RoutesBuilder> builders) throws Exception { 275 // add filter to class resolver which then will filter 276 getContext().getPackageScanClassResolver().addFilter(filter); 277 278 PackageScanRouteBuilderFinder finder = new PackageScanRouteBuilderFinder(getContext(), packages, getContextClassLoaderOnStart(), 279 getBeanPostProcessor(), getContext().getPackageScanClassResolver()); 280 finder.appendBuilders(builders); 281 282 // and remove the filter 283 getContext().getPackageScanClassResolver().removeFilter(filter); 284 } 285 286 @Override 287 protected void findRouteBuildersByContextScan(PackageScanFilter filter, boolean includeNonSingletons, List<RoutesBuilder> builders) throws Exception { 288 ContextScanRouteBuilderFinder finder = new ContextScanRouteBuilderFinder(getContext(), filter, includeNonSingletons); 289 finder.appendBuilders(builders); 290 } 291 292 @Override 293 protected void initBeanPostProcessor(SpringCamelContext context) { 294 if (beanPostProcessor != null) { 295 if (beanPostProcessor instanceof ApplicationContextAware) { 296 ((ApplicationContextAware) beanPostProcessor).setApplicationContext(applicationContext); 297 } 298 if (beanPostProcessor instanceof CamelBeanPostProcessor) { 299 ((CamelBeanPostProcessor) beanPostProcessor).setCamelContext(getContext()); 300 } 301 // register the bean post processor on camel context 302 if (beanPostProcessor instanceof org.apache.camel.spi.CamelBeanPostProcessor) { 303 context.setBeanPostProcessor((org.apache.camel.spi.CamelBeanPostProcessor) beanPostProcessor); 304 } 305 } 306 } 307 308 @Override 309 protected void postProcessBeforeInit(RouteBuilder builder) { 310 if (beanPostProcessor != null) { 311 // Inject the annotated resource 312 beanPostProcessor.postProcessBeforeInitialization(builder, builder.toString()); 313 } 314 } 315 316 @Override 317 public void afterPropertiesSet() throws Exception { 318 StopWatch watch = new StopWatch(); 319 320 super.afterPropertiesSet(); 321 322 Boolean shutdownEager = CamelContextHelper.parseBoolean(getContext(), getShutdownEager()); 323 if (shutdownEager != null) { 324 LOG.debug("Using shutdownEager: {}", shutdownEager); 325 getContext().setShutdownEager(shutdownEager); 326 } 327 328 LOG.debug("afterPropertiesSet() took {} millis", watch.taken()); 329 } 330 331 @Override 332 protected void initCustomRegistry(SpringCamelContext context) { 333 Registry registry = getBeanForType(Registry.class); 334 if (registry != null) { 335 LOG.info("Using custom Registry: {}", registry); 336 context.setRegistry(registry); 337 } 338 } 339 340 @Override 341 protected void initPropertyPlaceholder() throws Exception { 342 super.initPropertyPlaceholder(); 343 344 Map<String, BridgePropertyPlaceholderConfigurer> beans = applicationContext.getBeansOfType(BridgePropertyPlaceholderConfigurer.class); 345 if (beans.size() == 1) { 346 // setup properties component that uses this beans 347 BridgePropertyPlaceholderConfigurer configurer = beans.values().iterator().next(); 348 String id = beans.keySet().iterator().next(); 349 LOG.info("Bridging Camel and Spring property placeholder configurer with id: {}", id); 350 351 // get properties component 352 PropertiesComponent pc = (PropertiesComponent) getContext().getPropertiesComponent(); 353 // use the spring system properties mode which has a different value than Camel may have 354 pc.setSystemPropertiesMode(configurer.getSystemPropertiesMode()); 355 356 // replace existing resolver with us 357 configurer.setParser(pc.getPropertiesParser()); 358 // use the bridge to handle the resolve and parsing 359 pc.setPropertiesParser(configurer); 360 // use the bridge as property source 361 pc.addPropertiesSource(configurer); 362 363 } else if (beans.size() > 1) { 364 LOG.warn("Cannot bridge Camel and Spring property placeholders, as exact only 1 bean of type BridgePropertyPlaceholderConfigurer" 365 + " must be defined, was {} beans defined.", beans.size()); 366 } 367 } 368 369 @Override 370 public void start() { 371 try { 372 setupRoutes(); 373 } catch (Exception e) { 374 throw wrapRuntimeCamelException(e); 375 } 376 377 // when the routes are setup we need to start the Camel context 378 context.start(); 379 } 380 381 @Override 382 public void stop() { 383 if (context != null) { 384 context.stop(); 385 } 386 } 387 388 @Override 389 public boolean isRunning() { 390 return context != null && context.isRunning(); 391 } 392 393 @Override 394 public int getPhase() { 395 // the factory starts the context from 396 // onApplicationEvent(ContextRefreshedEvent) so the phase we're 397 // in only influences when the context is to be stopped, and 398 // we want the CamelContext to be first in line to get stopped 399 // if we wanted the phase to be considered while starting, we 400 // would need to implement SmartLifecycle (see 401 // DefaultLifecycleProcessor::startBeans) 402 // we use LOWEST_PRECEDENCE here as this is taken into account 403 // only when stopping and then in reversed order 404 return LOWEST_PRECEDENCE - 1; 405 } 406 407 @Override 408 public int getOrder() { 409 // CamelContextFactoryBean implements Ordered so that it's the 410 // second to last in ApplicationListener to receive events, 411 // SpringCamelContext should be the last one, this is important 412 // for startup as we want all resources to be ready and all 413 // routes added to the context (see setupRoutes() and 414 // org.apache.camel.spring.boot.RoutesCollector) 415 return LOWEST_PRECEDENCE - 1; 416 } 417 418 @Override 419 public void onApplicationEvent(final ContextRefreshedEvent event) { 420 // start the CamelContext when the Spring ApplicationContext is 421 // done initializing, as the last step in ApplicationContext 422 // being started/refreshed, there could be a race condition with 423 // other ApplicationListeners that react to 424 // ContextRefreshedEvent but this is the best that we can do 425 start(); 426 } 427 428 // Properties 429 // ------------------------------------------------------------------------- 430 431 public ApplicationContext getApplicationContext() { 432 if (applicationContext == null) { 433 throw new IllegalArgumentException("No applicationContext has been injected!"); 434 } 435 return applicationContext; 436 } 437 438 @Override 439 public void setApplicationContext(ApplicationContext applicationContext) { 440 this.applicationContext = applicationContext; 441 } 442 443 public void setBeanPostProcessor(BeanPostProcessor postProcessor) { 444 this.beanPostProcessor = postProcessor; 445 } 446 447 public BeanPostProcessor getBeanPostProcessor() { 448 return beanPostProcessor; 449 } 450 451 // Implementation methods 452 // ------------------------------------------------------------------------- 453 454 /** 455 * Create the context 456 */ 457 protected SpringCamelContext createContext() { 458 SpringCamelContext ctx = newCamelContext(); 459 ctx.setName(getId()); 460 461 return ctx; 462 } 463 464 /** 465 * Apply additional configuration to the context 466 */ 467 protected void configure(SpringCamelContext ctx) { 468 try { 469 // allow any custom configuration, such as when running in camel-spring-boot 470 if (applicationContext.containsBean("xmlCamelContextConfigurer")) { 471 XmlCamelContextConfigurer configurer = applicationContext.getBean("xmlCamelContextConfigurer", XmlCamelContextConfigurer.class); 472 if (configurer != null) { 473 configurer.configure(applicationContext, ctx); 474 } 475 } 476 } catch (Exception e) { 477 // error during configuration 478 throw RuntimeCamelException.wrapRuntimeCamelException(e); 479 } 480 } 481 482 protected SpringCamelContext newCamelContext() { 483 return new SpringCamelContext(getApplicationContext()); 484 } 485 486 @Override 487 public SpringCamelContext getContext(boolean create) { 488 if (context == null && create) { 489 context = createContext(); 490 configure(context); 491 context.build(); 492 } 493 return context; 494 } 495 496 public void setContext(SpringCamelContext context) { 497 this.context = context; 498 } 499 500 @Override 501 public List<RouteDefinition> getRoutes() { 502 return routes; 503 } 504 505 /** 506 * Contains the Camel routes 507 */ 508 @Override 509 public void setRoutes(List<RouteDefinition> routes) { 510 this.routes = routes; 511 } 512 513 @Override 514 public List<RestDefinition> getRests() { 515 return rests; 516 } 517 518 /** 519 * Contains the rest services defined using the rest-dsl 520 */ 521 @Override 522 public void setRests(List<RestDefinition> rests) { 523 this.rests = rests; 524 } 525 526 @Override 527 public RestConfigurationDefinition getRestConfiguration() { 528 return restConfiguration; 529 } 530 531 /** 532 * Configuration for rest-dsl 533 */ 534 public void setRestConfiguration(RestConfigurationDefinition restConfiguration) { 535 this.restConfiguration = restConfiguration; 536 } 537 538 @Override 539 public List<CamelEndpointFactoryBean> getEndpoints() { 540 return endpoints; 541 } 542 543 /** 544 * Configuration of endpoints 545 */ 546 public void setEndpoints(List<CamelEndpointFactoryBean> endpoints) { 547 this.endpoints = endpoints; 548 } 549 550 @Override 551 public List<CamelRedeliveryPolicyFactoryBean> getRedeliveryPolicies() { 552 return redeliveryPolicies; 553 } 554 555 @Override 556 public List<InterceptDefinition> getIntercepts() { 557 return intercepts; 558 } 559 560 /** 561 * Configuration of interceptors. 562 */ 563 public void setIntercepts(List<InterceptDefinition> intercepts) { 564 this.intercepts = intercepts; 565 } 566 567 @Override 568 public List<InterceptFromDefinition> getInterceptFroms() { 569 return interceptFroms; 570 } 571 572 /** 573 * Configuration of interceptors that triggers from the beginning of routes. 574 */ 575 public void setInterceptFroms(List<InterceptFromDefinition> interceptFroms) { 576 this.interceptFroms = interceptFroms; 577 } 578 579 @Override 580 public List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints() { 581 return interceptSendToEndpoints; 582 } 583 584 /** 585 * Configuration of interceptors that triggers sending messages to endpoints. 586 */ 587 public void setInterceptSendToEndpoints(List<InterceptSendToEndpointDefinition> interceptSendToEndpoints) { 588 this.interceptSendToEndpoints = interceptSendToEndpoints; 589 } 590 591 @Override 592 public GlobalOptionsDefinition getGlobalOptions() { 593 return globalOptions; 594 } 595 596 /** 597 * Configuration of CamelContext properties such as limit of debug logging 598 * and other general options. 599 */ 600 public void setGlobalOptions(GlobalOptionsDefinition globalOptions) { 601 this.globalOptions = globalOptions; 602 } 603 604 @Override 605 public String[] getPackages() { 606 return packages; 607 } 608 609 /** 610 * Sets the package names to be recursively searched for Java classes which 611 * extend {@link org.apache.camel.builder.RouteBuilder} to be auto-wired up to the 612 * {@link CamelContext} as a route. Note that classes are excluded if 613 * they are specifically configured in the spring.xml 614 * <p/> 615 * A more advanced configuration can be done using {@link #setPackageScan(org.apache.camel.model.PackageScanDefinition)} 616 * 617 * @param packages the package names which are recursively searched 618 * @see #setPackageScan(org.apache.camel.model.PackageScanDefinition) 619 */ 620 public void setPackages(String[] packages) { 621 this.packages = packages; 622 } 623 624 @Override 625 public PackageScanDefinition getPackageScan() { 626 return packageScan; 627 } 628 629 /** 630 * Sets the package scanning information. Package scanning allows for the 631 * automatic discovery of certain camel classes at runtime for inclusion 632 * e.g. {@link org.apache.camel.builder.RouteBuilder} implementations 633 * 634 * @param packageScan the package scan 635 */ 636 @Override 637 public void setPackageScan(PackageScanDefinition packageScan) { 638 this.packageScan = packageScan; 639 } 640 641 @Override 642 public ContextScanDefinition getContextScan() { 643 return contextScan; 644 } 645 646 /** 647 * Sets the context scanning (eg Spring's ApplicationContext) information. 648 * Context scanning allows for the automatic discovery of Camel routes runtime for inclusion 649 * e.g. {@link org.apache.camel.builder.RouteBuilder} implementations 650 * 651 * @param contextScan the context scan 652 */ 653 @Override 654 public void setContextScan(ContextScanDefinition contextScan) { 655 this.contextScan = contextScan; 656 } 657 658 @Override 659 public CamelPropertyPlaceholderDefinition getCamelPropertyPlaceholder() { 660 return camelPropertyPlaceholder; 661 } 662 663 /** 664 * Configuration of property placeholder 665 */ 666 public void setCamelPropertyPlaceholder(CamelPropertyPlaceholderDefinition camelPropertyPlaceholder) { 667 this.camelPropertyPlaceholder = camelPropertyPlaceholder; 668 } 669 670 @Override 671 public CamelStreamCachingStrategyDefinition getCamelStreamCachingStrategy() { 672 return camelStreamCachingStrategy; 673 } 674 675 /** 676 * Configuration of stream caching. 677 */ 678 public void setCamelStreamCachingStrategy(CamelStreamCachingStrategyDefinition camelStreamCachingStrategy) { 679 this.camelStreamCachingStrategy = camelStreamCachingStrategy; 680 } 681 682 /** 683 * Configuration of JMX Agent. 684 */ 685 public void setCamelJMXAgent(CamelJMXAgentDefinition agent) { 686 camelJMXAgent = agent; 687 } 688 689 @Override 690 public String getTrace() { 691 return trace; 692 } 693 694 /** 695 * Sets whether tracing is enabled or not. 696 * 697 * To use tracing then this must be enabled on startup to be installed in the CamelContext. 698 */ 699 public void setTrace(String trace) { 700 this.trace = trace; 701 } 702 703 @Override 704 public String getBacklogTrace() { 705 return backlogTrace; 706 } 707 708 /** 709 * Sets whether backlog tracing is enabled or not. 710 * 711 * To use backlog tracing then this must be enabled on startup to be installed in the CamelContext. 712 */ 713 public void setBacklogTrace(String backlogTrace) { 714 this.backlogTrace = backlogTrace; 715 } 716 717 @Override 718 public String getDebug() { 719 return debug; 720 } 721 722 /** 723 * Sets whether debugging is enabled or not. 724 * 725 * To use debugging then this must be enabled on startup to be installed in the CamelContext. 726 */ 727 public void setDebug(String debug) { 728 this.debug = debug; 729 } 730 731 @Override 732 public String getTracePattern() { 733 return tracePattern; 734 } 735 736 /** 737 * Tracing pattern to match which node EIPs to trace. 738 * For example to match all To EIP nodes, use to*. 739 * The pattern matches by node and route id's 740 * Multiple patterns can be separated by comma. 741 */ 742 public void setTracePattern(String tracePattern) { 743 this.tracePattern = tracePattern; 744 } 745 746 @Override 747 public String getMessageHistory() { 748 return messageHistory; 749 } 750 751 /** 752 * Sets whether message history is enabled or not. 753 */ 754 public void setMessageHistory(String messageHistory) { 755 this.messageHistory = messageHistory; 756 } 757 758 @Override 759 public String getLogMask() { 760 return logMask; 761 } 762 763 /** 764 * Sets whether security mask for Logging is enabled or not. 765 */ 766 public void setLogMask(String logMask) { 767 this.logMask = logMask; 768 } 769 770 @Override 771 public String getLogExhaustedMessageBody() { 772 return logExhaustedMessageBody; 773 } 774 775 /** 776 * Sets whether to log exhausted message body with message history. 777 */ 778 public void setLogExhaustedMessageBody(String logExhaustedMessageBody) { 779 this.logExhaustedMessageBody = logExhaustedMessageBody; 780 } 781 782 @Override 783 public String getStreamCache() { 784 return streamCache; 785 } 786 787 /** 788 * Sets whether stream caching is enabled or not. 789 */ 790 public void setStreamCache(String streamCache) { 791 this.streamCache = streamCache; 792 } 793 794 @Override 795 public String getDelayer() { 796 return delayer; 797 } 798 799 /** 800 * Sets a delay value in millis that a message is delayed at every step it takes in the route path, 801 * slowing the process down to better observe what is occurring 802 */ 803 public void setDelayer(String delayer) { 804 this.delayer = delayer; 805 } 806 807 @Override 808 public String getAutoStartup() { 809 return autoStartup; 810 } 811 812 /** 813 * Sets whether the object should automatically start when Camel starts. 814 * <p/> 815 * <b>Important:</b> Currently only routes can be disabled, as {@link CamelContext}s are always started. 816 * <br/> 817 * <b>Note:</b> When setting auto startup <tt>false</tt> on {@link CamelContext} then that takes precedence 818 * and <i>no</i> routes is started. You would need to start {@link CamelContext} explicit using 819 * the {@link org.apache.camel.CamelContext#start()} method, to start the context, and then 820 * you would need to start the routes manually using {@link org.apache.camel.spi.RouteController#startRoute(String)}. 821 */ 822 public void setAutoStartup(String autoStartup) { 823 this.autoStartup = autoStartup; 824 } 825 826 public String getShutdownEager() { 827 return shutdownEager; 828 } 829 830 /** 831 * Whether to shutdown CamelContext eager when Spring is shutting down. 832 * This ensure a cleaner shutdown of Camel, as dependent bean's are not shutdown at this moment. 833 * The bean's will then be shutdown after camelContext. 834 */ 835 public void setShutdownEager(String shutdownEager) { 836 this.shutdownEager = shutdownEager; 837 } 838 839 @Override 840 public String getUseMDCLogging() { 841 return useMDCLogging; 842 } 843 844 /** 845 * Set whether <a href="http://www.slf4j.org/api/org/slf4j/MDC.html">MDC</a> is enabled. 846 */ 847 public void setUseMDCLogging(String useMDCLogging) { 848 this.useMDCLogging = useMDCLogging; 849 } 850 851 public String getMDCLoggingKeysPattern() { 852 return mdcLoggingKeysPattern; 853 } 854 855 /** 856 * Sets the pattern used for determine which custom MDC keys to propagate during message routing when 857 * the routing engine continues routing asynchronously for the given message. Setting this pattern to * will 858 * propagate all custom keys. Or setting the pattern to foo*,bar* will propagate any keys starting with 859 * either foo or bar. 860 * Notice that a set of standard Camel MDC keys are always propagated which starts with camel. as key name. 861 * 862 * The match rules are applied in this order (case insensitive): 863 * 864 * 1. exact match, returns true 865 * 2. wildcard match (pattern ends with a * and the name starts with the pattern), returns true 866 * 3. regular expression match, returns true 867 * 4. otherwise returns false 868 */ 869 public void setMDCLoggingKeysPattern(String mdcLoggingKeysPattern) { 870 this.mdcLoggingKeysPattern = mdcLoggingKeysPattern; 871 } 872 873 @Override 874 public String getUseDataType() { 875 return useDataType; 876 } 877 878 /** 879 * Whether to enable using data type on Camel messages. 880 * <p/> 881 * Data type are automatic turned on if: 882 * <ul> 883 * <li>one ore more routes has been explicit configured with input and output types</li> 884 * <li>when using rest-dsl with binding turned on</li> 885 * </ul> 886 * Otherwise data type is default off. 887 */ 888 public void setUseDataType(String useDataType) { 889 this.useDataType = useDataType; 890 } 891 892 @Override 893 public String getUseBreadcrumb() { 894 return useBreadcrumb; 895 } 896 897 /** 898 * Set whether breadcrumb is enabled. 899 */ 900 public void setUseBreadcrumb(String useBreadcrumb) { 901 this.useBreadcrumb = useBreadcrumb; 902 } 903 904 @Override 905 public String getAllowUseOriginalMessage() { 906 return allowUseOriginalMessage; 907 } 908 909 /** 910 * Sets whether to allow access to the original message from Camel's error handler, 911 * or from {@link org.apache.camel.spi.UnitOfWork#getOriginalInMessage()}. 912 * <p/> 913 * Turning this off can optimize performance, as defensive copy of the original message is not needed. 914 */ 915 public void setAllowUseOriginalMessage(String allowUseOriginalMessage) { 916 this.allowUseOriginalMessage = allowUseOriginalMessage; 917 } 918 919 @Override 920 public String getCaseInsensitiveHeaders() { 921 return caseInsensitiveHeaders; 922 } 923 924 /** 925 * Whether to use case sensitive or insensitive headers. 926 * 927 * Important: When using case sensitive (this is set to false). 928 * Then the map is case sensitive which means headers such as content-type and Content-Type are 929 * two different keys which can be a problem for some protocols such as HTTP based, which rely on case insensitive headers. 930 * However case sensitive implementations can yield faster performance. Therefore use case sensitive implementation with care. 931 * 932 * Default is true. 933 */ 934 public void setCaseInsensitiveHeaders(String caseInsensitiveHeaders) { 935 this.caseInsensitiveHeaders = caseInsensitiveHeaders; 936 } 937 938 @Override 939 public String getRuntimeEndpointRegistryEnabled() { 940 return runtimeEndpointRegistryEnabled; 941 } 942 943 /** 944 * Sets whether {@link org.apache.camel.spi.RuntimeEndpointRegistry} is enabled. 945 */ 946 public void setRuntimeEndpointRegistryEnabled(String runtimeEndpointRegistryEnabled) { 947 this.runtimeEndpointRegistryEnabled = runtimeEndpointRegistryEnabled; 948 } 949 950 @Override 951 public String getInflightRepositoryBrowseEnabled() { 952 return inflightRepositoryBrowseEnabled; 953 } 954 955 /** 956 * Sets whether the inflight repository should allow browsing each inflight exchange. 957 * 958 * This is by default disabled as there is a very slight performance overhead when enabled. 959 */ 960 public void setInflightRepositoryBrowseEnabled(String inflightRepositoryBrowseEnabled) { 961 this.inflightRepositoryBrowseEnabled = inflightRepositoryBrowseEnabled; 962 } 963 964 @Override 965 public String getManagementNamePattern() { 966 return managementNamePattern; 967 } 968 969 /** 970 * The naming pattern for creating the CamelContext management name. 971 */ 972 public void setManagementNamePattern(String managementNamePattern) { 973 this.managementNamePattern = managementNamePattern; 974 } 975 976 @Override 977 public String getThreadNamePattern() { 978 return threadNamePattern; 979 } 980 981 /** 982 * Sets the thread name pattern used for creating the full thread name. 983 * <p/> 984 * The default pattern is: <tt>Camel (#camelId#) thread ##counter# - #name#</tt> 985 * <p/> 986 * Where <tt>#camelId#</tt> is the name of the {@link org.apache.camel.CamelContext} 987 * <br/>and <tt>#counter#</tt> is a unique incrementing counter. 988 * <br/>and <tt>#name#</tt> is the regular thread name. 989 * <br/>You can also use <tt>#longName#</tt> is the long thread name which can includes endpoint parameters etc. 990 */ 991 public void setThreadNamePattern(String threadNamePattern) { 992 this.threadNamePattern = threadNamePattern; 993 } 994 995 @Override 996 public String getLoadTypeConverters() { 997 return loadTypeConverters; 998 } 999 1000 /** 1001 * Sets whether to load custom type converters by scanning classpath. 1002 * This can be turned off if you are only using Camel components 1003 * that does not provide type converters which is needed at runtime. 1004 * In such situations setting this option to false, can speedup starting 1005 * Camel. 1006 * 1007 * @param loadTypeConverters whether to load custom type converters. 1008 */ 1009 public void setLoadTypeConverters(String loadTypeConverters) { 1010 this.loadTypeConverters = loadTypeConverters; 1011 } 1012 1013 @Override 1014 public String getTypeConverterStatisticsEnabled() { 1015 return typeConverterStatisticsEnabled; 1016 } 1017 1018 /** 1019 * Sets whether or not type converter statistics is enabled. 1020 * <p/> 1021 * By default the type converter utilization statistics is disabled. 1022 * <b>Notice:</b> If enabled then there is a slight performance impact under very heavy load. 1023 * <p/> 1024 * You can enable/disable the statistics at runtime using the 1025 * {@link org.apache.camel.spi.TypeConverterRegistry#getStatistics()#setTypeConverterStatisticsEnabled(Boolean)} method, 1026 * or from JMX on the {@link org.apache.camel.api.management.mbean.ManagedTypeConverterRegistryMBean} mbean. 1027 */ 1028 public void setTypeConverterStatisticsEnabled(String typeConverterStatisticsEnabled) { 1029 this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled; 1030 } 1031 1032 @Override 1033 public TypeConverterExists getTypeConverterExists() { 1034 return typeConverterExists; 1035 } 1036 1037 /** 1038 * What should happen when attempting to add a duplicate type converter. 1039 * <p/> 1040 * The default behavior is to override the existing. 1041 */ 1042 public void setTypeConverterExists(TypeConverterExists typeConverterExists) { 1043 this.typeConverterExists = typeConverterExists; 1044 } 1045 1046 @Override 1047 public LoggingLevel getTypeConverterExistsLoggingLevel() { 1048 return typeConverterExistsLoggingLevel; 1049 } 1050 1051 /** 1052 * The logging level to use when logging that a type converter already exists when attempting to add a duplicate type converter. 1053 * <p/> 1054 * The default logging level is <tt>WARN</tt> 1055 */ 1056 public void setTypeConverterExistsLoggingLevel(LoggingLevel typeConverterExistsLoggingLevel) { 1057 this.typeConverterExistsLoggingLevel = typeConverterExistsLoggingLevel; 1058 } 1059 1060 @Override 1061 public CamelJMXAgentDefinition getCamelJMXAgent() { 1062 return camelJMXAgent; 1063 } 1064 1065 @Override 1066 public List<RouteBuilderDefinition> getBuilderRefs() { 1067 return builderRefs; 1068 } 1069 1070 /** 1071 * Refers to Java {@link RouteBuilder} instances to include as routes in this CamelContext. 1072 */ 1073 public void setBuilderRefs(List<RouteBuilderDefinition> builderRefs) { 1074 this.builderRefs = builderRefs; 1075 } 1076 1077 @Override 1078 public List<RouteContextRefDefinition> getRouteRefs() { 1079 return routeRefs; 1080 } 1081 1082 /** 1083 * Refers to XML routes to include as routes in this CamelContext. 1084 */ 1085 public void setRouteRefs(List<RouteContextRefDefinition> routeRefs) { 1086 this.routeRefs = routeRefs; 1087 } 1088 1089 @Override 1090 public List<RestContextRefDefinition> getRestRefs() { 1091 return restRefs; 1092 } 1093 1094 /** 1095 * Refers to XML rest-dsl to include as REST services in this CamelContext. 1096 */ 1097 public void setRestRefs(List<RestContextRefDefinition> restRefs) { 1098 this.restRefs = restRefs; 1099 } 1100 1101 @Override 1102 public String getErrorHandlerRef() { 1103 return errorHandlerRef; 1104 } 1105 1106 /** 1107 * Sets the name of the error handler object used to default the error handling strategy 1108 */ 1109 public void setErrorHandlerRef(String errorHandlerRef) { 1110 this.errorHandlerRef = errorHandlerRef; 1111 } 1112 1113 /** 1114 * Configuration of data formats. 1115 */ 1116 public void setDataFormats(DataFormatsDefinition dataFormats) { 1117 this.dataFormats = dataFormats; 1118 } 1119 1120 @Override 1121 public DataFormatsDefinition getDataFormats() { 1122 return dataFormats; 1123 } 1124 1125 /** 1126 * Configuration of transformers. 1127 */ 1128 public void setTransformers(TransformersDefinition transformers) { 1129 this.transformers = transformers; 1130 } 1131 1132 @Override 1133 public TransformersDefinition getTransformers() { 1134 return transformers; 1135 } 1136 1137 /** 1138 * Configuration of validators. 1139 */ 1140 public void setValidators(ValidatorsDefinition validators) { 1141 this.validators = validators; 1142 } 1143 1144 @Override 1145 public ValidatorsDefinition getValidators() { 1146 return validators; 1147 } 1148 1149 /** 1150 * Configuration of redelivery settings. 1151 */ 1152 public void setRedeliveryPolicies(List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies) { 1153 this.redeliveryPolicies = redeliveryPolicies; 1154 } 1155 1156 @Override 1157 public List<AbstractCamelFactoryBean<?>> getBeansFactory() { 1158 return beansFactory; 1159 } 1160 1161 /** 1162 * Miscellaneous configurations 1163 */ 1164 public void setBeansFactory(List<AbstractCamelFactoryBean<?>> beansFactory) { 1165 this.beansFactory = beansFactory; 1166 } 1167 1168 @Override 1169 public List<?> getBeans() { 1170 return beans; 1171 } 1172 1173 /** 1174 * Miscellaneous configurations 1175 */ 1176 public void setBeans(List<?> beans) { 1177 this.beans = beans; 1178 } 1179 1180 @Override 1181 public ServiceCallConfigurationDefinition getDefaultServiceCallConfiguration() { 1182 return defaultServiceCallConfiguration; 1183 } 1184 1185 /** 1186 * ServiceCall EIP default configuration 1187 */ 1188 public void setDefaultServiceCallConfiguration(ServiceCallConfigurationDefinition defaultServiceCallConfiguration) { 1189 this.defaultServiceCallConfiguration = defaultServiceCallConfiguration; 1190 } 1191 1192 @Override 1193 public List<ServiceCallConfigurationDefinition> getServiceCallConfigurations() { 1194 return serviceCallConfigurations; 1195 } 1196 1197 /** 1198 * ServiceCall EIP configurations 1199 */ 1200 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> serviceCallConfigurations) { 1201 this.serviceCallConfigurations = serviceCallConfigurations; 1202 } 1203 1204 @Override 1205 public List<HystrixConfigurationDefinition> getHystrixConfigurations() { 1206 return hystrixConfigurations; 1207 } 1208 1209 @Override 1210 public HystrixConfigurationDefinition getDefaultHystrixConfiguration() { 1211 return defaultHystrixConfiguration; 1212 } 1213 1214 /** 1215 * Hystrix EIP default configuration 1216 */ 1217 public void setDefaultHystrixConfiguration(HystrixConfigurationDefinition defaultHystrixConfiguration) { 1218 this.defaultHystrixConfiguration = defaultHystrixConfiguration; 1219 } 1220 1221 /** 1222 * Hystrix Circuit Breaker EIP configurations 1223 */ 1224 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> hystrixConfigurations) { 1225 this.hystrixConfigurations = hystrixConfigurations; 1226 } 1227 1228 @Override 1229 public Resilience4jConfigurationDefinition getDefaultResilience4jConfiguration() { 1230 return defaultResilience4jConfiguration; 1231 } 1232 1233 /** 1234 * Resilience4j EIP default configuration 1235 */ 1236 public void setDefaultResilience4jConfiguration(Resilience4jConfigurationDefinition defaultResilience4jConfiguration) { 1237 this.defaultResilience4jConfiguration = defaultResilience4jConfiguration; 1238 } 1239 1240 @Override 1241 public List<Resilience4jConfigurationDefinition> getResilience4jConfigurations() { 1242 return resilience4jConfigurations; 1243 } 1244 1245 /** 1246 * Resilience4j Circuit Breaker EIP configurations 1247 */ 1248 public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> resilience4jConfigurations) { 1249 this.resilience4jConfigurations = resilience4jConfigurations; 1250 } 1251 1252 @Override 1253 public FaultToleranceConfigurationDefinition getDefaultFaultToleranceConfiguration() { 1254 return defaultFaultToleranceConfiguration; 1255 } 1256 1257 /** 1258 * MicroProfile Fault Tolerance EIP default configuration 1259 */ 1260 public void setDefaultFaultToleranceConfiguration(FaultToleranceConfigurationDefinition defaultFaultToleranceConfiguration) { 1261 this.defaultFaultToleranceConfiguration = defaultFaultToleranceConfiguration; 1262 } 1263 1264 @Override 1265 public List<FaultToleranceConfigurationDefinition> getFaultToleranceConfigurations() { 1266 return faultToleranceConfigurations; 1267 } 1268 1269 /** 1270 * MicroProfile Circuit Breaker EIP configurations 1271 */ 1272 public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> faultToleranceConfigurations) { 1273 this.faultToleranceConfigurations = faultToleranceConfigurations; 1274 } 1275 1276 /** 1277 * Configuration of error handlers that triggers on exceptions thrown. 1278 */ 1279 public void setOnExceptions(List<OnExceptionDefinition> onExceptions) { 1280 this.onExceptions = onExceptions; 1281 } 1282 1283 @Override 1284 public List<OnExceptionDefinition> getOnExceptions() { 1285 return onExceptions; 1286 } 1287 1288 @Override 1289 public List<OnCompletionDefinition> getOnCompletions() { 1290 return onCompletions; 1291 } 1292 1293 /** 1294 * Configuration of sub routes to run at the completion of routing. 1295 */ 1296 public void setOnCompletions(List<OnCompletionDefinition> onCompletions) { 1297 this.onCompletions = onCompletions; 1298 } 1299 1300 @Override 1301 public ShutdownRoute getShutdownRoute() { 1302 return shutdownRoute; 1303 } 1304 1305 /** 1306 * Sets the ShutdownRoute option for routes. 1307 */ 1308 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 1309 this.shutdownRoute = shutdownRoute; 1310 } 1311 1312 @Override 1313 public ShutdownRunningTask getShutdownRunningTask() { 1314 return shutdownRunningTask; 1315 } 1316 1317 /** 1318 * Sets the ShutdownRunningTask option to use when shutting down a route. 1319 */ 1320 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 1321 this.shutdownRunningTask = shutdownRunningTask; 1322 } 1323 1324 @Override 1325 public List<ThreadPoolProfileDefinition> getThreadPoolProfiles() { 1326 return threadPoolProfiles; 1327 } 1328 1329 /** 1330 * Configuration of thread pool profiles. 1331 */ 1332 public void setThreadPoolProfiles(List<ThreadPoolProfileDefinition> threadPoolProfiles) { 1333 this.threadPoolProfiles = threadPoolProfiles; 1334 } 1335 1336 public List<CamelThreadPoolFactoryBean> getThreadPools() { 1337 return threadPools; 1338 } 1339 1340 /** 1341 * Configuration of thread pool 1342 */ 1343 public void setThreadPools(List<CamelThreadPoolFactoryBean> threadPools) { 1344 this.threadPools = threadPools; 1345 } 1346 1347 @Override 1348 public String getDependsOn() { 1349 return dependsOn; 1350 } 1351 1352 /** 1353 * List of other bean id's this CamelContext depends up. Multiple bean id's can be separated by comma. 1354 */ 1355 public void setDependsOn(String dependsOn) { 1356 this.dependsOn = dependsOn; 1357 } 1358 1359 public boolean isImplicitId() { 1360 return implicitId; 1361 } 1362 1363 public void setImplicitId(boolean flag) { 1364 implicitId = flag; 1365 } 1366}