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.ArrayList; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Iterator; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027import java.util.function.Function; 028 029import org.apache.camel.CamelContext; 030import org.apache.camel.ExtendedCamelContext; 031import org.apache.camel.model.DataFormatDefinition; 032import org.apache.camel.model.FaultToleranceConfigurationDefinition; 033import org.apache.camel.model.HystrixConfigurationDefinition; 034import org.apache.camel.model.Model; 035import org.apache.camel.model.ModelCamelContext; 036import org.apache.camel.model.ProcessorDefinition; 037import org.apache.camel.model.ProcessorDefinitionHelper; 038import org.apache.camel.model.Resilience4jConfigurationDefinition; 039import org.apache.camel.model.RouteDefinition; 040import org.apache.camel.model.RouteFilters; 041import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 042import org.apache.camel.model.rest.RestDefinition; 043import org.apache.camel.model.transformer.TransformerDefinition; 044import org.apache.camel.model.validator.ValidatorDefinition; 045 046public class DefaultModel implements Model { 047 048 private final CamelContext camelContext; 049 050 private final List<RouteDefinition> routeDefinitions = new ArrayList<>(); 051 private final List<RestDefinition> restDefinitions = new ArrayList<>(); 052 private Map<String, DataFormatDefinition> dataFormats = new HashMap<>(); 053 private List<TransformerDefinition> transformers = new ArrayList<>(); 054 private List<ValidatorDefinition> validators = new ArrayList<>(); 055 private Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>(); 056 private Map<String, HystrixConfigurationDefinition> hystrixConfigurations = new ConcurrentHashMap<>(); 057 private Map<String, Resilience4jConfigurationDefinition> resilience4jConfigurations = new ConcurrentHashMap<>(); 058 private Map<String, FaultToleranceConfigurationDefinition> faultToleranceConfigurations = new ConcurrentHashMap<>(); 059 private Function<RouteDefinition, Boolean> routeFilter; 060 061 public DefaultModel(CamelContext camelContext) { 062 this.camelContext = camelContext; 063 } 064 065 public CamelContext getCamelContext() { 066 return camelContext; 067 } 068 069 @Override 070 public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 071 if (routeDefinitions == null || routeDefinitions.isEmpty()) { 072 return; 073 } 074 List<RouteDefinition> list = new ArrayList<>(); 075 routeDefinitions.forEach(r -> { 076 if (routeFilter == null || routeFilter.apply(r)) { 077 list.add(r); 078 } 079 }); 080 081 removeRouteDefinitions(list); 082 this.routeDefinitions.addAll(list); 083 if (shouldStartRoutes()) { 084 getCamelContext().adapt(ModelCamelContext.class).startRouteDefinitions(list); 085 } 086 } 087 088 @Override 089 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 090 addRouteDefinitions(Collections.singletonList(routeDefinition)); 091 } 092 093 @Override 094 public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 095 for (RouteDefinition routeDefinition : routeDefinitions) { 096 removeRouteDefinition(routeDefinition); 097 } 098 } 099 100 @Override 101 public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 102 RouteDefinition toBeRemoved = routeDefinition; 103 String id = routeDefinition.getId(); 104 if (id != null) { 105 // remove existing route 106 camelContext.getRouteController().stopRoute(id); 107 camelContext.removeRoute(id); 108 toBeRemoved = getRouteDefinition(id); 109 } 110 this.routeDefinitions.remove(toBeRemoved); 111 } 112 113 @Override 114 public synchronized List<RouteDefinition> getRouteDefinitions() { 115 return routeDefinitions; 116 } 117 118 @Override 119 public synchronized RouteDefinition getRouteDefinition(String id) { 120 for (RouteDefinition route : routeDefinitions) { 121 if (route.idOrCreate(camelContext.adapt(ExtendedCamelContext.class).getNodeIdFactory()).equals(id)) { 122 return route; 123 } 124 } 125 return null; 126 } 127 128 @Override 129 public synchronized List<RestDefinition> getRestDefinitions() { 130 return restDefinitions; 131 } 132 133 @Override 134 public synchronized void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) throws Exception { 135 if (restDefinitions == null || restDefinitions.isEmpty()) { 136 return; 137 } 138 139 this.restDefinitions.addAll(restDefinitions); 140 if (addToRoutes) { 141 // rests are also routes so need to add them there too 142 for (final RestDefinition restDefinition : restDefinitions) { 143 List<RouteDefinition> routeDefinitions = restDefinition.asRouteDefinition(camelContext); 144 addRouteDefinitions(routeDefinitions); 145 } 146 } 147 } 148 149 @Override 150 public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) { 151 if (serviceName == null) { 152 serviceName = ""; 153 } 154 155 return serviceCallConfigurations.get(serviceName); 156 } 157 158 @Override 159 public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) { 160 serviceCallConfigurations.put("", configuration); 161 } 162 163 @Override 164 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) { 165 if (configurations != null) { 166 for (ServiceCallConfigurationDefinition configuration : configurations) { 167 serviceCallConfigurations.put(configuration.getId(), configuration); 168 } 169 } 170 } 171 172 @Override 173 public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) { 174 serviceCallConfigurations.put(serviceName, configuration); 175 } 176 177 @Override 178 public HystrixConfigurationDefinition getHystrixConfiguration(String id) { 179 if (id == null) { 180 id = ""; 181 } 182 183 return hystrixConfigurations.get(id); 184 } 185 186 @Override 187 public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) { 188 hystrixConfigurations.put("", configuration); 189 } 190 191 @Override 192 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) { 193 if (configurations != null) { 194 for (HystrixConfigurationDefinition configuration : configurations) { 195 hystrixConfigurations.put(configuration.getId(), configuration); 196 } 197 } 198 } 199 200 @Override 201 public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) { 202 hystrixConfigurations.put(id, configuration); 203 } 204 205 @Override 206 public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) { 207 if (id == null) { 208 id = ""; 209 } 210 211 return resilience4jConfigurations.get(id); 212 } 213 214 @Override 215 public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) { 216 resilience4jConfigurations.put("", configuration); 217 } 218 219 @Override 220 public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) { 221 if (configurations != null) { 222 for (Resilience4jConfigurationDefinition configuration : configurations) { 223 resilience4jConfigurations.put(configuration.getId(), configuration); 224 } 225 } 226 } 227 228 @Override 229 public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) { 230 resilience4jConfigurations.put(id, configuration); 231 } 232 233 @Override 234 public FaultToleranceConfigurationDefinition getFaultToleranceConfiguration(String id) { 235 if (id == null) { 236 id = ""; 237 } 238 239 return faultToleranceConfigurations.get(id); 240 } 241 242 @Override 243 public void setFaultToleranceConfiguration(FaultToleranceConfigurationDefinition configuration) { 244 faultToleranceConfigurations.put("", configuration); 245 } 246 247 @Override 248 public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> configurations) { 249 if (configurations != null) { 250 for (FaultToleranceConfigurationDefinition configuration : configurations) { 251 faultToleranceConfigurations.put(configuration.getId(), configuration); 252 } 253 } 254 } 255 256 @Override 257 public void addFaultToleranceConfiguration(String id, FaultToleranceConfigurationDefinition configuration) { 258 faultToleranceConfigurations.put(id, configuration); 259 } 260 261 @Override 262 public DataFormatDefinition resolveDataFormatDefinition(String name) { 263 // lookup type and create the data format from it 264 DataFormatDefinition type = lookup(camelContext, name, DataFormatDefinition.class); 265 if (type == null && getDataFormats() != null) { 266 type = getDataFormats().get(name); 267 } 268 return type; 269 } 270 271 @SuppressWarnings("rawtypes") 272 @Override 273 public ProcessorDefinition<?> getProcessorDefinition(String id) { 274 for (RouteDefinition route : getRouteDefinitions()) { 275 Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class); 276 while (it.hasNext()) { 277 ProcessorDefinition<?> proc = it.next(); 278 if (id.equals(proc.getId())) { 279 return proc; 280 } 281 } 282 } 283 return null; 284 } 285 286 @Override 287 public <T extends ProcessorDefinition<T>> T getProcessorDefinition(String id, Class<T> type) { 288 ProcessorDefinition<?> answer = getProcessorDefinition(id); 289 if (answer != null) { 290 return type.cast(answer); 291 } 292 return null; 293 } 294 295 @Override 296 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 297 this.dataFormats = dataFormats; 298 } 299 300 @Override 301 public Map<String, DataFormatDefinition> getDataFormats() { 302 return dataFormats; 303 } 304 305 @Override 306 public void setTransformers(List<TransformerDefinition> transformers) { 307 this.transformers = transformers; 308 } 309 310 @Override 311 public List<TransformerDefinition> getTransformers() { 312 return transformers; 313 } 314 315 @Override 316 public void setValidators(List<ValidatorDefinition> validators) { 317 this.validators = validators; 318 } 319 320 @Override 321 public List<ValidatorDefinition> getValidators() { 322 return validators; 323 } 324 325 @Override 326 public void setRouteFilterPattern(String include, String exclude) { 327 setRouteFilter(RouteFilters.filterByPattern(include, exclude)); 328 } 329 330 @Override 331 public Function<RouteDefinition, Boolean> getRouteFilter() { 332 return routeFilter; 333 } 334 335 @Override 336 public void setRouteFilter(Function<RouteDefinition, Boolean> routeFilter) { 337 this.routeFilter = routeFilter; 338 } 339 340 /** 341 * Should we start newly added routes? 342 */ 343 protected boolean shouldStartRoutes() { 344 return camelContext.isStarted() && !camelContext.isStarting(); 345 } 346 347 protected static <T> T lookup(CamelContext context, String ref, Class<T> type) { 348 try { 349 return context.getRegistry().lookupByNameAndType(ref, type); 350 } catch (Exception e) { 351 // need to ignore not same type and return it as null 352 return null; 353 } 354 } 355 356}