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