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}