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.impl; 018 019import java.util.Collection; 020import java.util.List; 021import java.util.Map; 022import java.util.function.Function; 023 024import org.apache.camel.CamelContext; 025import org.apache.camel.Expression; 026import org.apache.camel.FailedToStartRouteException; 027import org.apache.camel.Predicate; 028import org.apache.camel.Processor; 029import org.apache.camel.Route; 030import org.apache.camel.ValueHolder; 031import org.apache.camel.builder.AdviceWithRouteBuilder; 032import org.apache.camel.health.HealthCheckRegistry; 033import org.apache.camel.impl.engine.RouteService; 034import org.apache.camel.impl.engine.SimpleCamelContext; 035import org.apache.camel.impl.transformer.TransformerKey; 036import org.apache.camel.impl.validator.ValidatorKey; 037import org.apache.camel.model.DataFormatDefinition; 038import org.apache.camel.model.FaultToleranceConfigurationDefinition; 039import org.apache.camel.model.HystrixConfigurationDefinition; 040import org.apache.camel.model.Model; 041import org.apache.camel.model.ModelCamelContext; 042import org.apache.camel.model.ProcessorDefinition; 043import org.apache.camel.model.Resilience4jConfigurationDefinition; 044import org.apache.camel.model.RouteDefinition; 045import org.apache.camel.model.RouteDefinitionHelper; 046import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 047import org.apache.camel.model.language.ExpressionDefinition; 048import org.apache.camel.model.rest.RestDefinition; 049import org.apache.camel.model.transformer.TransformerDefinition; 050import org.apache.camel.model.validator.ValidatorDefinition; 051import org.apache.camel.reifier.RouteReifier; 052import org.apache.camel.reifier.dataformat.DataFormatReifier; 053import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier; 054import org.apache.camel.reifier.language.ExpressionReifier; 055import org.apache.camel.reifier.transformer.TransformerReifier; 056import org.apache.camel.reifier.validator.ValidatorReifier; 057import org.apache.camel.spi.BeanRepository; 058import org.apache.camel.spi.DataFormat; 059import org.apache.camel.spi.DataType; 060import org.apache.camel.spi.ExecutorServiceManager; 061import org.apache.camel.spi.Registry; 062import org.apache.camel.spi.Transformer; 063import org.apache.camel.spi.Validator; 064import org.apache.camel.support.CamelContextHelper; 065import org.apache.camel.support.DefaultRegistry; 066import org.apache.camel.util.ObjectHelper; 067import org.slf4j.Logger; 068import org.slf4j.LoggerFactory; 069 070/** 071 * Represents the context used to configure routes and the policies to use. 072 */ 073public class DefaultCamelContext extends SimpleCamelContext implements ModelCamelContext { 074 075 private static final Logger LOG = LoggerFactory.getLogger(DefaultCamelContext.class); 076 077 private Model model = new DefaultModel(this); 078 079 /** 080 * Creates the {@link ModelCamelContext} using 081 * {@link org.apache.camel.support.DefaultRegistry} as registry. 082 * <p/> 083 * Use one of the other constructors to force use an explicit registry. 084 */ 085 public DefaultCamelContext() { 086 this(true); 087 } 088 089 /** 090 * Creates the {@link CamelContext} using the given {@link BeanRepository} 091 * as first-choice repository, and the 092 * {@link org.apache.camel.support.SimpleRegistry} as fallback, via the 093 * {@link DefaultRegistry} implementation. 094 * 095 * @param repository the bean repository. 096 */ 097 public DefaultCamelContext(BeanRepository repository) { 098 this(new DefaultRegistry(repository)); 099 } 100 101 /** 102 * Creates the {@link ModelCamelContext} using the given registry 103 * 104 * @param registry the registry 105 */ 106 public DefaultCamelContext(Registry registry) { 107 this(); 108 setRegistry(registry); 109 } 110 111 public DefaultCamelContext(boolean init) { 112 super(init); 113 } 114 115 @Override 116 public List<RouteDefinition> getRouteDefinitions() { 117 return model.getRouteDefinitions(); 118 } 119 120 @Override 121 public RouteDefinition getRouteDefinition(String id) { 122 return model.getRouteDefinition(id); 123 } 124 125 @Override 126 public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 127 model.addRouteDefinitions(routeDefinitions); 128 } 129 130 @Override 131 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 132 model.addRouteDefinition(routeDefinition); 133 } 134 135 @Override 136 public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 137 model.removeRouteDefinitions(routeDefinitions); 138 } 139 140 @Override 141 public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 142 model.removeRouteDefinition(routeDefinition); 143 } 144 145 @Override 146 public List<RestDefinition> getRestDefinitions() { 147 return model.getRestDefinitions(); 148 } 149 150 @Override 151 public void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) throws Exception { 152 model.addRestDefinitions(restDefinitions, addToRoutes); 153 } 154 155 @Override 156 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 157 model.setDataFormats(dataFormats); 158 } 159 160 @Override 161 public Map<String, DataFormatDefinition> getDataFormats() { 162 return model.getDataFormats(); 163 } 164 165 @Override 166 public DataFormatDefinition resolveDataFormatDefinition(String name) { 167 return model.resolveDataFormatDefinition(name); 168 } 169 170 @Override 171 public ProcessorDefinition<?> getProcessorDefinition(String id) { 172 return model.getProcessorDefinition(id); 173 } 174 175 @Override 176 public <T extends ProcessorDefinition<T>> T getProcessorDefinition(String id, Class<T> type) { 177 return model.getProcessorDefinition(id, type); 178 } 179 180 @Override 181 public void setValidators(List<ValidatorDefinition> validators) { 182 model.setValidators(validators); 183 } 184 185 @Override 186 public HystrixConfigurationDefinition getHystrixConfiguration(String id) { 187 return model.getHystrixConfiguration(id); 188 } 189 190 @Override 191 public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) { 192 model.setHystrixConfiguration(configuration); 193 } 194 195 @Override 196 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) { 197 model.setHystrixConfigurations(configurations); 198 } 199 200 @Override 201 public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) { 202 model.addHystrixConfiguration(id, configuration); 203 } 204 205 @Override 206 public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) { 207 return model.getResilience4jConfiguration(id); 208 } 209 210 @Override 211 public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) { 212 model.setResilience4jConfiguration(configuration); 213 } 214 215 @Override 216 public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) { 217 model.setResilience4jConfigurations(configurations); 218 } 219 220 @Override 221 public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) { 222 model.addResilience4jConfiguration(id, configuration); 223 } 224 225 @Override 226 public FaultToleranceConfigurationDefinition getFaultToleranceConfiguration(String id) { 227 return model.getFaultToleranceConfiguration(id); 228 } 229 230 @Override 231 public void setFaultToleranceConfiguration(FaultToleranceConfigurationDefinition configuration) { 232 model.setFaultToleranceConfiguration(configuration); 233 } 234 235 @Override 236 public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> configurations) { 237 model.setFaultToleranceConfigurations(configurations); 238 } 239 240 @Override 241 public void addFaultToleranceConfiguration(String id, FaultToleranceConfigurationDefinition configuration) { 242 model.addFaultToleranceConfiguration(id, configuration); 243 } 244 245 @Override 246 public List<ValidatorDefinition> getValidators() { 247 return model.getValidators(); 248 } 249 250 @Override 251 public void setTransformers(List<TransformerDefinition> transformers) { 252 model.setTransformers(transformers); 253 } 254 255 @Override 256 public List<TransformerDefinition> getTransformers() { 257 return model.getTransformers(); 258 } 259 260 @Override 261 public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) { 262 return model.getServiceCallConfiguration(serviceName); 263 } 264 265 @Override 266 public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) { 267 model.setServiceCallConfiguration(configuration); 268 } 269 270 @Override 271 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) { 272 model.setServiceCallConfigurations(configurations); 273 } 274 275 @Override 276 public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) { 277 model.addServiceCallConfiguration(serviceName, configuration); 278 } 279 280 @Override 281 public void setRouteFilterPattern(String include, String exclude) { 282 model.setRouteFilterPattern(include, exclude); 283 } 284 285 @Override 286 public void setRouteFilter(Function<RouteDefinition, Boolean> filter) { 287 model.setRouteFilter(filter); 288 } 289 290 @Override 291 public Function<RouteDefinition, Boolean> getRouteFilter() { 292 return model.getRouteFilter(); 293 } 294 295 @Override 296 protected void doStartStandardServices() { 297 super.doStartStandardServices(); 298 } 299 300 @Override 301 protected void bindDataFormats() throws Exception { 302 // eager lookup data formats and bind to registry so the dataformats can 303 // be looked up and used 304 for (Map.Entry<String, DataFormatDefinition> e : model.getDataFormats().entrySet()) { 305 String id = e.getKey(); 306 DataFormatDefinition def = e.getValue(); 307 LOG.debug("Creating Dataformat with id: {} and definition: {}", id, def); 308 DataFormat df = DataFormatReifier.reifier(this, def).createDataFormat(); 309 addService(df, true); 310 getRegistry().bind(id, df); 311 } 312 } 313 314 @Override 315 protected synchronized void shutdownRouteService(RouteService routeService) throws Exception { 316 RouteDefinition rd = model.getRouteDefinition(routeService.getId()); 317 if (rd != null) { 318 model.getRouteDefinitions().remove(rd); 319 } 320 super.shutdownRouteService(routeService); 321 } 322 323 @Override 324 protected boolean isStreamCachingInUse() throws Exception { 325 boolean streamCachingInUse = super.isStreamCachingInUse(); 326 if (!streamCachingInUse) { 327 for (RouteDefinition route : model.getRouteDefinitions()) { 328 Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache()); 329 if (routeCache != null && routeCache) { 330 streamCachingInUse = true; 331 break; 332 } 333 } 334 } 335 return streamCachingInUse; 336 } 337 338 @Override 339 public void startRouteDefinitions() throws Exception { 340 List<RouteDefinition> routeDefinitions = model.getRouteDefinitions(); 341 if (routeDefinitions != null) { 342 startRouteDefinitions(routeDefinitions); 343 } 344 } 345 346 public void startRouteDefinitions(List<RouteDefinition> routeDefinitions) throws Exception { 347 // indicate we are staring the route using this thread so 348 // we are able to query this if needed 349 boolean alreadyStartingRoutes = isStartingRoutes(); 350 if (!alreadyStartingRoutes) { 351 setStartingRoutes(true); 352 } 353 try { 354 RouteDefinitionHelper.forceAssignIds(getCamelContextReference(), routeDefinitions); 355 for (RouteDefinition routeDefinition : routeDefinitions) { 356 // assign ids to the routes and validate that the id's is all unique 357 String duplicate = RouteDefinitionHelper.validateUniqueIds(routeDefinition, routeDefinitions); 358 if (duplicate != null) { 359 throw new FailedToStartRouteException(routeDefinition.getId(), "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes."); 360 } 361 362 // must ensure route is prepared, before we can start it 363 if (!routeDefinition.isPrepared()) { 364 RouteDefinitionHelper.prepareRoute(getCamelContextReference(), routeDefinition); 365 routeDefinition.markPrepared(); 366 } 367 368 Route route = new RouteReifier(getCamelContextReference(), routeDefinition).createRoute(); 369 RouteService routeService = new RouteService(route); 370 startRouteService(routeService, true); 371 } 372 } finally { 373 if (!alreadyStartingRoutes) { 374 setStartingRoutes(false); 375 } 376 } 377 } 378 379 @Override 380 protected ExecutorServiceManager createExecutorServiceManager() { 381 return new DefaultExecutorServiceManager(this); 382 } 383 384 @Override 385 public Processor createErrorHandler(Route route, Processor processor) throws Exception { 386 return ErrorHandlerReifier.reifier(route, route.getErrorHandlerFactory()) 387 .createErrorHandler(processor); 388 } 389 390 @Override 391 public Expression createExpression(ExpressionDefinition definition) { 392 return ExpressionReifier.reifier(this, definition).createExpression(); 393 } 394 395 @Override 396 public Predicate createPredicate(ExpressionDefinition definition) { 397 return ExpressionReifier.reifier(this, definition).createPredicate(); 398 } 399 400 @Override 401 public RouteDefinition adviceWith(RouteDefinition definition, AdviceWithRouteBuilder builder) throws Exception { 402 return RouteReifier.adviceWith(definition, this, builder); 403 } 404 405 @Override 406 public void registerValidator(ValidatorDefinition def) { 407 model.getValidators().add(def); 408 Validator validator = ValidatorReifier.reifier(this, def).createValidator(); 409 getValidatorRegistry().put(createValidatorKey(def), validator); 410 } 411 412 private static ValueHolder<String> createValidatorKey(ValidatorDefinition def) { 413 return new ValidatorKey(new DataType(def.getType())); 414 } 415 416 417 @Override 418 public void registerTransformer(TransformerDefinition def) { 419 model.getTransformers().add(def); 420 Transformer transformer = TransformerReifier.reifier(this, def).createTransformer(); 421 getTransformerRegistry().put(createTransformerKey(def), transformer); 422 } 423 424 private static ValueHolder<String> createTransformerKey(TransformerDefinition def) { 425 return ObjectHelper.isNotEmpty(def.getScheme()) ? new TransformerKey(def.getScheme()) : new TransformerKey(new DataType(def.getFromType()), new DataType(def.getToType())); 426 } 427 428}