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.concurrent.ExecutorService;
023import java.util.function.Function;
024
025import org.apache.camel.AsyncProcessor;
026import org.apache.camel.CatalogCamelContext;
027import org.apache.camel.Processor;
028import org.apache.camel.health.HealthCheckRegistry;
029import org.apache.camel.impl.engine.AbstractCamelContext;
030import org.apache.camel.impl.engine.BaseRouteService;
031import org.apache.camel.impl.engine.DefaultTransformerRegistry;
032import org.apache.camel.impl.engine.DefaultValidatorRegistry;
033import org.apache.camel.impl.transformer.TransformerKey;
034import org.apache.camel.impl.validator.ValidatorKey;
035import org.apache.camel.model.DataFormatDefinition;
036import org.apache.camel.model.HystrixConfigurationDefinition;
037import org.apache.camel.model.Model;
038import org.apache.camel.model.ModelCamelContext;
039import org.apache.camel.model.ProcessorDefinition;
040import org.apache.camel.model.Resilience4jConfigurationDefinition;
041import org.apache.camel.model.RouteDefinition;
042import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
043import org.apache.camel.model.rest.RestDefinition;
044import org.apache.camel.model.transformer.TransformerDefinition;
045import org.apache.camel.model.validator.ValidatorDefinition;
046import org.apache.camel.processor.MulticastProcessor;
047import org.apache.camel.reifier.dataformat.DataFormatReifier;
048import org.apache.camel.spi.DataFormat;
049import org.apache.camel.spi.Registry;
050import org.apache.camel.spi.TransformerRegistry;
051import org.apache.camel.spi.ValidatorRegistry;
052import org.apache.camel.support.CamelContextHelper;
053import org.slf4j.Logger;
054import org.slf4j.LoggerFactory;
055
056/**
057 * Represents the context used to configure routes and the policies to use.
058 */
059public abstract class AbstractModelCamelContext extends AbstractCamelContext implements ModelCamelContext, CatalogCamelContext {
060
061    private static final Logger LOG = LoggerFactory.getLogger(AbstractModelCamelContext.class);
062
063    private final Model model = new DefaultModel(this);
064
065    /**
066     * Creates the {@link ModelCamelContext} using
067     * {@link org.apache.camel.support.DefaultRegistry} as registry.
068     * <p/>
069     * Use one of the other constructors to force use an explicit registry.
070     */
071    public AbstractModelCamelContext() {
072        this(true);
073    }
074
075    /**
076     * Creates the {@link ModelCamelContext} using the given registry
077     *
078     * @param registry the registry
079     */
080    public AbstractModelCamelContext(Registry registry) {
081        this();
082        setRegistry(registry);
083    }
084
085    public AbstractModelCamelContext(boolean init) {
086        super(false);
087
088        setDefaultExtension(HealthCheckRegistry.class, this::createHealthCheckRegistry);
089
090        if (init) {
091            init();
092        }
093    }
094
095    @Override
096    public List<RouteDefinition> getRouteDefinitions() {
097        return model.getRouteDefinitions();
098    }
099
100    @Override
101    public RouteDefinition getRouteDefinition(String id) {
102        return model.getRouteDefinition(id);
103    }
104
105    @Override
106    public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
107        if (isStarted() && !isAllowAddingNewRoutes()) {
108            throw new IllegalArgumentException("Adding new routes after CamelContext has been started is not allowed");
109        }
110        model.addRouteDefinitions(routeDefinitions);
111    }
112
113    @Override
114    public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception {
115        if (isStarted() && !isAllowAddingNewRoutes()) {
116            throw new IllegalArgumentException("Adding new routes after CamelContext has been started is not allowed");
117        }
118        model.addRouteDefinition(routeDefinition);
119    }
120
121    @Override
122    public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
123        model.removeRouteDefinitions(routeDefinitions);
124    }
125
126    @Override
127    public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
128        model.removeRouteDefinition(routeDefinition);
129    }
130
131    @Override
132    public List<RestDefinition> getRestDefinitions() {
133        return model.getRestDefinitions();
134    }
135
136    @Override
137    public void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) throws Exception {
138        if (isStarted() && !isAllowAddingNewRoutes()) {
139            throw new IllegalArgumentException("Adding new routes after CamelContext has been started is not allowed");
140        }
141        model.addRestDefinitions(restDefinitions, addToRoutes);
142    }
143
144    @Override
145    public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
146        model.setDataFormats(dataFormats);
147    }
148
149    @Override
150    public Map<String, DataFormatDefinition> getDataFormats() {
151        return model.getDataFormats();
152    }
153
154    @Override
155    public DataFormatDefinition resolveDataFormatDefinition(String name) {
156        return model.resolveDataFormatDefinition(name);
157    }
158
159    @Override
160    public ProcessorDefinition getProcessorDefinition(String id) {
161        return model.getProcessorDefinition(id);
162    }
163
164    @Override
165    public <T extends ProcessorDefinition> T getProcessorDefinition(String id, Class<T> type) {
166        return model.getProcessorDefinition(id, type);
167    }
168
169    @Override
170    public void setValidators(List<ValidatorDefinition> validators) {
171        model.setValidators(validators);
172    }
173
174    @Override
175    public HystrixConfigurationDefinition getHystrixConfiguration(String id) {
176        return model.getHystrixConfiguration(id);
177    }
178
179    @Override
180    public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) {
181        model.setHystrixConfiguration(configuration);
182    }
183
184    @Override
185    public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) {
186        model.setHystrixConfigurations(configurations);
187    }
188
189    @Override
190    public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) {
191        model.addHystrixConfiguration(id, configuration);
192    }
193
194    @Override
195    public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) {
196        return model.getResilience4jConfiguration(id);
197    }
198
199    @Override
200    public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) {
201        model.setResilience4jConfiguration(configuration);
202    }
203
204    @Override
205    public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) {
206        model.setResilience4jConfigurations(configurations);
207    }
208
209    @Override
210    public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) {
211        model.addResilience4jConfiguration(id, configuration);
212    }
213
214    @Override
215    public List<ValidatorDefinition> getValidators() {
216        return model.getValidators();
217    }
218
219    @Override
220    public void setTransformers(List<TransformerDefinition> transformers) {
221        model.setTransformers(transformers);
222    }
223
224    @Override
225    public List<TransformerDefinition> getTransformers() {
226        return model.getTransformers();
227    }
228
229    @Override
230    public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) {
231        return model.getServiceCallConfiguration(serviceName);
232    }
233
234    @Override
235    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
236        model.setServiceCallConfiguration(configuration);
237    }
238
239    @Override
240    public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) {
241        model.setServiceCallConfigurations(configurations);
242    }
243
244    @Override
245    public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) {
246        model.addServiceCallConfiguration(serviceName, configuration);
247    }
248
249    @Override
250    public void setRouteFilterPattern(String include, String exclude) {
251        model.setRouteFilterPattern(include, exclude);
252    }
253
254    @Override
255    public void setRouteFilter(Function<RouteDefinition, Boolean> filter) {
256        model.setRouteFilter(filter);
257    }
258
259    @Override
260    public Function<RouteDefinition, Boolean> getRouteFilter() {
261        return model.getRouteFilter();
262    }
263
264    @Override
265    protected ValidatorRegistry<ValidatorKey> createValidatorRegistry() {
266        return new DefaultValidatorRegistry(this);
267    }
268
269    @Override
270    protected TransformerRegistry<TransformerKey> createTransformerRegistry() {
271        return new DefaultTransformerRegistry(this);
272    }
273
274    protected abstract HealthCheckRegistry createHealthCheckRegistry();
275
276    @Override
277    protected void doStartStandardServices() {
278        super.doStartStandardServices();
279    }
280
281    @Override
282    protected void doStartEagerServices() {
283        getExtension(HealthCheckRegistry.class);
284        super.doStartEagerServices();
285    }
286
287    @Override
288    protected void bindDataFormats() throws Exception {
289        // eager lookup data formats and bind to registry so the dataformats can
290        // be looked up and used
291        for (Map.Entry<String, DataFormatDefinition> e : model.getDataFormats().entrySet()) {
292            String id = e.getKey();
293            DataFormatDefinition def = e.getValue();
294            LOG.debug("Creating Dataformat with id: {} and definition: {}", id, def);
295            DataFormat df = DataFormatReifier.reifier(this, def).createDataFormat();
296            addService(df, true);
297            getRegistry().bind(id, df);
298        }
299    }
300
301    @Override
302    protected synchronized void shutdownRouteService(BaseRouteService routeService) throws Exception {
303        if (routeService instanceof RouteService) {
304            model.getRouteDefinitions().remove(((RouteService)routeService).getRouteDefinition());
305        }
306        super.shutdownRouteService(routeService);
307    }
308
309    @Override
310    protected boolean isStreamCachingInUse() throws Exception {
311        boolean streamCachingInUse = super.isStreamCachingInUse();
312        if (!streamCachingInUse) {
313            for (RouteDefinition route : model.getRouteDefinitions()) {
314                Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache());
315                if (routeCache != null && routeCache) {
316                    streamCachingInUse = true;
317                    break;
318                }
319            }
320        }
321        return streamCachingInUse;
322    }
323
324    @Override
325    public void startRouteDefinitions() throws Exception {
326        model.startRouteDefinitions();
327    }
328
329    @Override
330    public AsyncProcessor createMulticast(Collection<Processor> processors, ExecutorService executor, boolean shutdownExecutorService) {
331        return new MulticastProcessor(this, processors, null, true, executor, shutdownExecutorService, false, false, 0, null, false, false);
332    }
333
334}