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 */
017 package org.apache.camel.impl;
018
019 import java.io.IOException;
020 import java.lang.reflect.Constructor;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.concurrent.Callable;
027
028 import javax.naming.Context;
029
030 import org.apache.camel.CamelContext;
031 import org.apache.camel.Component;
032 import org.apache.camel.Endpoint;
033 import org.apache.camel.Exchange;
034 import org.apache.camel.Processor;
035 import org.apache.camel.ProducerTemplate;
036 import org.apache.camel.ResolveEndpointFailedException;
037 import org.apache.camel.Route;
038 import org.apache.camel.Routes;
039 import org.apache.camel.RuntimeCamelException;
040 import org.apache.camel.Service;
041 import org.apache.camel.TypeConverter;
042 import org.apache.camel.builder.ErrorHandlerBuilder;
043 import org.apache.camel.impl.converter.DefaultTypeConverter;
044 import org.apache.camel.management.InstrumentationLifecycleStrategy;
045 import org.apache.camel.management.JmxSystemPropertyKeys;
046 import org.apache.camel.model.RouteType;
047 import org.apache.camel.model.dataformat.DataFormatType;
048 import org.apache.camel.processor.interceptor.Delayer;
049 import org.apache.camel.processor.interceptor.TraceFormatter;
050 import org.apache.camel.processor.interceptor.Tracer;
051 import org.apache.camel.spi.ComponentResolver;
052 import org.apache.camel.spi.ExchangeConverter;
053 import org.apache.camel.spi.Injector;
054 import org.apache.camel.spi.InterceptStrategy;
055 import org.apache.camel.spi.Language;
056 import org.apache.camel.spi.LanguageResolver;
057 import org.apache.camel.spi.LifecycleStrategy;
058 import org.apache.camel.spi.Registry;
059 import org.apache.camel.util.FactoryFinder;
060 import org.apache.camel.util.LRUCache;
061 import org.apache.camel.util.NoFactoryAvailableException;
062 import org.apache.camel.util.ObjectHelper;
063 import org.apache.camel.util.ReflectionInjector;
064 import org.apache.camel.util.SystemHelper;
065 import org.apache.commons.logging.Log;
066 import org.apache.commons.logging.LogFactory;
067
068 import static org.apache.camel.util.ServiceHelper.startServices;
069 import static org.apache.camel.util.ServiceHelper.stopServices;
070
071 /**
072 * Represents the context used to configure routes and the policies to use.
073 *
074 * @version $Revision: 14007 $
075 */
076 public class DefaultCamelContext extends ServiceSupport implements CamelContext, Service {
077 private static final transient Log LOG = LogFactory.getLog(DefaultCamelContext.class);
078 private static final String NAME_PREFIX = "camel-";
079 private static int nameSuffix;
080 private boolean routeDefinitionInitiated;
081 private String name;
082 private final Map<String, Endpoint> endpoints = new LRUCache<String, Endpoint>(1000);
083 private final Map<String, Component> components = new HashMap<String, Component>();
084 private List<Route> routes;
085 private List<Service> servicesToClose = new ArrayList<Service>();
086 private TypeConverter typeConverter;
087 private ExchangeConverter exchangeConverter;
088 private Injector injector;
089 private ComponentResolver componentResolver;
090 private boolean autoCreateComponents = true;
091 private LanguageResolver languageResolver = new DefaultLanguageResolver();
092 private Registry registry;
093 private LifecycleStrategy lifecycleStrategy;
094 private List<RouteType> routeDefinitions = new ArrayList<RouteType>();
095 private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
096 private Boolean trace;
097 private Long delay;
098 private ErrorHandlerBuilder errorHandlerBuilder;
099 private Map<String, DataFormatType> dataFormats = new HashMap<String, DataFormatType>();
100 private Map<String, String> properties = new HashMap<String, String>();
101 private Class<? extends FactoryFinder> factoryFinderClass = FactoryFinder.class;
102
103 public DefaultCamelContext() {
104 name = NAME_PREFIX + ++nameSuffix;
105
106 if (Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)) {
107 LOG.info("JMX is disabled. Using DefaultLifecycleStrategy.");
108 lifecycleStrategy = new DefaultLifecycleStrategy();
109 } else {
110 try {
111 LOG.info("JMX enabled. Using InstrumentationLifecycleStrategy.");
112 lifecycleStrategy = new InstrumentationLifecycleStrategy();
113 } catch (NoClassDefFoundError e) {
114 // if we can't instantiate the JMX enabled strategy then fallback to default
115 // could be because of missing .jars on the classpath
116 LOG.warn("Could not find needed classes for JMX lifecycle strategy."
117 + " Needed class is in spring-context.jar using Spring 2.5 or newer ("
118 + " spring-jmx.jar using Spring 2.0.x)."
119 + " NoClassDefFoundError: " + e.getMessage());
120 } catch (Exception e) {
121 LOG.warn("Could not create JMX lifecycle strategy, caused by: " + e.getMessage());
122 }
123 // if not created then fallback to default
124 if (lifecycleStrategy == null) {
125 LOG.warn("Not possible to use JMX lifecycle strategy. Using DefaultLifecycleStrategy instead.");
126 lifecycleStrategy = new DefaultLifecycleStrategy();
127 }
128 }
129 }
130
131 /**
132 * Creates the {@link CamelContext} using the given JNDI context as the
133 * registry
134 */
135 public DefaultCamelContext(Context jndiContext) {
136 this();
137 setJndiContext(jndiContext);
138 }
139
140 /**
141 * Creates the {@link CamelContext} using the given registry
142 */
143 public DefaultCamelContext(Registry registry) {
144 this();
145 this.registry = registry;
146 }
147
148 public String getName() {
149 return name;
150 }
151
152 /**
153 * Sets the name of the this context.
154 */
155 public void setName(String name) {
156 this.name = name;
157 }
158
159 public void addComponent(String componentName, final Component component) {
160 if (component == null) {
161 throw new IllegalArgumentException("Component cannot be null");
162 }
163 synchronized (components) {
164 if (components.containsKey(componentName)) {
165 throw new IllegalArgumentException("Component previously added: " + componentName);
166 }
167 component.setCamelContext(this);
168 components.put(componentName, component);
169 }
170 }
171
172 public Component getComponent(String name) {
173 // synchronize the look up and auto create so that 2 threads can't
174 // concurrently auto create the same component.
175 synchronized (components) {
176 Component component = components.get(name);
177 if (component == null && autoCreateComponents) {
178 try {
179 component = getComponentResolver().resolveComponent(name, this);
180 if (component != null) {
181 addComponent(name, component);
182 if (isStarted() || isStarting()) {
183 // If the component is looked up after the context
184 // is started,
185 // lets start it up.
186 startServices(component);
187 }
188 }
189 } catch (Exception e) {
190 throw new RuntimeCamelException("Could not auto create component: " + name, e);
191 }
192 }
193 return component;
194 }
195 }
196
197 public <T extends Component> T getComponent(String name, Class<T> componentType) {
198 Component component = getComponent(name);
199 if (componentType.isInstance(component)) {
200 return componentType.cast(component);
201 } else {
202 throw new IllegalArgumentException("The component is not of type: " + componentType + " but is: "
203 + component);
204 }
205 }
206
207 public Component removeComponent(String componentName) {
208 synchronized (components) {
209 return components.remove(componentName);
210 }
211 }
212
213 public Component getOrCreateComponent(String componentName, Callable<Component> factory) {
214 synchronized (components) {
215 Component component = components.get(componentName);
216 if (component == null) {
217 try {
218 component = factory.call();
219 if (component == null) {
220 throw new RuntimeCamelException("Factory failed to create the " + componentName
221 + " component, it returned null.");
222 }
223 components.put(componentName, component);
224 component.setCamelContext(this);
225 } catch (Exception e) {
226 throw new RuntimeCamelException("Factory failed to create the " + componentName
227 + " component", e);
228 }
229 }
230 return component;
231 }
232 }
233
234 // Endpoint Management Methods
235 // -----------------------------------------------------------------------
236
237 public Collection<Endpoint> getEndpoints() {
238 synchronized (endpoints) {
239 return new ArrayList<Endpoint>(endpoints.values());
240 }
241 }
242
243 public Map<String, Endpoint> getEndpointMap() {
244 synchronized (endpoints) {
245 return new HashMap<String, Endpoint>(endpoints);
246 }
247 }
248
249 public Collection<Endpoint> getEndpoints(String uri) {
250 Collection<Endpoint> answer = new ArrayList<Endpoint>();
251 Collection<Endpoint> coll;
252 synchronized (endpoints) {
253 Endpoint ep = endpoints.get(uri);
254 if (ep != null) {
255 answer.add(ep);
256 return answer;
257 }
258 coll = new ArrayList<Endpoint>(endpoints.values());
259 }
260 for (Endpoint ep : coll) {
261 if (!ep.isSingleton() && uri.equals(ep.getEndpointUri())) {
262 answer.add(ep);
263 }
264 }
265 return answer;
266 }
267
268 public Collection<Endpoint> getSingletonEndpoints() {
269 Collection<Endpoint> answer = new ArrayList<Endpoint>();
270 Collection<Endpoint> coll = getEndpoints();
271 for (Endpoint ep : coll) {
272 if (ep.isSingleton()) {
273 answer.add(ep);
274 }
275 }
276 return answer;
277 }
278
279 public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
280 Endpoint oldEndpoint;
281 synchronized (endpoints) {
282 startServices(endpoint);
283 oldEndpoint = endpoints.remove(uri);
284 endpoints.put(getEndpointKey(uri, endpoint), endpoint);
285 if (oldEndpoint != null) {
286 stopServices(oldEndpoint);
287 }
288 }
289 return oldEndpoint;
290 }
291
292 public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
293 Collection<Endpoint> answer = new ArrayList<Endpoint>();
294 synchronized (endpoints) {
295 Endpoint oldEndpoint = endpoints.remove(uri);
296 if (oldEndpoint != null) {
297 answer.add(oldEndpoint);
298 stopServices(oldEndpoint);
299 } else {
300 for (Map.Entry entry : endpoints.entrySet()) {
301 oldEndpoint = (Endpoint)entry.getValue();
302 if (!oldEndpoint.isSingleton() && uri.equals(oldEndpoint.getEndpointUri())) {
303 answer.add(oldEndpoint);
304 stopServices(oldEndpoint);
305 endpoints.remove(entry.getKey());
306 }
307 }
308 }
309 }
310 return answer;
311 }
312
313 public Endpoint addSingletonEndpoint(String uri, Endpoint endpoint) throws Exception {
314 return addEndpoint(uri, endpoint);
315 }
316
317 public Endpoint removeSingletonEndpoint(String uri) throws Exception {
318 Collection<Endpoint> answer = removeEndpoints(uri);
319 return (Endpoint) (answer.size() > 0 ? answer.toArray()[0] : null);
320 }
321
322 public Endpoint getEndpoint(String uri) {
323 Endpoint<?> answer;
324 synchronized (endpoints) {
325 answer = endpoints.get(uri);
326 if (answer == null) {
327 try {
328
329 // Use the URI prefix to find the component.
330 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2);
331 if (splitURI[1] != null) {
332 String scheme = splitURI[0];
333 Component<?> component = getComponent(scheme);
334
335 // Ask the component to resolve the endpoint.
336 if (component != null) {
337 // Have the component create the endpoint if it can.
338 answer = component.createEndpoint(uri);
339
340 if (answer != null && LOG.isDebugEnabled()) {
341 LOG.debug(uri + " converted to endpoint: " + answer + " by component: " + component);
342 }
343 }
344 }
345 if (answer == null) {
346 answer = createEndpoint(uri);
347 }
348
349 // If it's a singleton then auto register it.
350 if (answer != null) {
351 addService(answer);
352
353 endpoints.put(getEndpointKey(uri, answer), answer);
354 lifecycleStrategy.onEndpointAdd(answer);
355 }
356 } catch (Exception e) {
357 LOG.debug("Failed to resolve endpoint " + uri + ". Reason: " + e, e);
358 throw new ResolveEndpointFailedException(uri, e);
359 }
360 }
361 }
362 return answer;
363 }
364
365 public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) {
366 Endpoint endpoint = getEndpoint(name);
367 if (endpointType.isInstance(endpoint)) {
368 return endpointType.cast(endpoint);
369 } else {
370 throw new IllegalArgumentException("The endpoint is not of type: " + endpointType + " but is: "
371 + endpoint);
372 }
373 }
374
375 // Route Management Methods
376 // -----------------------------------------------------------------------
377 public List<Route> getRoutes() {
378 if (routes == null) {
379 routes = new ArrayList<Route>();
380 }
381 return routes;
382 }
383
384 public void setRoutes(List<Route> routes) {
385 this.routes = routes;
386 throw new UnsupportedOperationException("overriding existing routes is not supported yet, use addRoutes instead");
387 }
388
389 public void addRoutes(Collection<Route> routes) throws Exception {
390 if (this.routes == null) {
391 this.routes = new ArrayList<Route>();
392 }
393
394 if (routes != null) {
395 this.routes.addAll(routes);
396 lifecycleStrategy.onRoutesAdd(routes);
397 if (shouldStartRoutes()) {
398 startRoutes(routes);
399 }
400 }
401 }
402
403 public void addRoutes(Routes builder) throws Exception {
404 // lets now add the routes from the builder
405 builder.setContext(this);
406 List<Route> routeList = builder.getRouteList();
407 if (LOG.isDebugEnabled()) {
408 LOG.debug("Adding routes from: " + builder + " routes: " + routeList);
409 }
410 addRoutes(routeList);
411 }
412
413 public void addRouteDefinitions(Collection<RouteType> routeDefinitions) throws Exception {
414 this.routeDefinitions.addAll(routeDefinitions);
415 if (shouldStartRoutes()) {
416 startRouteDefinitions(routeDefinitions);
417 }
418
419 }
420
421 /**
422 * Adds a service, starting it so that it will be stopped with this context
423 */
424 public void addService(Object object) throws Exception {
425 if (object instanceof Service) {
426 Service service = (Service) object;
427 getLifecycleStrategy().onServiceAdd(this, service);
428 service.start();
429 servicesToClose.add(service);
430 }
431 }
432
433 // Helper methods
434 // -----------------------------------------------------------------------
435
436 public Language resolveLanguage(String language) {
437 return getLanguageResolver().resolveLanguage(language, this);
438 }
439
440 // Properties
441 // -----------------------------------------------------------------------
442 public ExchangeConverter getExchangeConverter() {
443 if (exchangeConverter == null) {
444 exchangeConverter = createExchangeConverter();
445 }
446 return exchangeConverter;
447 }
448
449 public void setExchangeConverter(ExchangeConverter exchangeConverter) {
450 this.exchangeConverter = exchangeConverter;
451 }
452
453 public TypeConverter getTypeConverter() {
454 if (typeConverter == null) {
455 typeConverter = createTypeConverter();
456 }
457 return typeConverter;
458 }
459
460 public void setTypeConverter(TypeConverter typeConverter) {
461 this.typeConverter = typeConverter;
462 }
463
464 public Injector getInjector() {
465 if (injector == null) {
466 injector = createInjector();
467 }
468 return injector;
469 }
470
471 public void setInjector(Injector injector) {
472 this.injector = injector;
473 }
474
475 public ComponentResolver getComponentResolver() {
476 if (componentResolver == null) {
477 componentResolver = createComponentResolver();
478 }
479 return componentResolver;
480 }
481
482 public void setComponentResolver(ComponentResolver componentResolver) {
483 this.componentResolver = componentResolver;
484 }
485
486 public LanguageResolver getLanguageResolver() {
487 return languageResolver;
488 }
489
490 public void setLanguageResolver(LanguageResolver languageResolver) {
491 this.languageResolver = languageResolver;
492 }
493
494 public boolean isAutoCreateComponents() {
495 return autoCreateComponents;
496 }
497
498 public void setAutoCreateComponents(boolean autoCreateComponents) {
499 this.autoCreateComponents = autoCreateComponents;
500 }
501
502 public Registry getRegistry() {
503 if (registry == null) {
504 registry = createRegistry();
505 }
506 return registry;
507 }
508
509 /**
510 * Sets the registry to the given JNDI context
511 *
512 * @param jndiContext is the JNDI context to use as the registry
513 *
514 * @see #setRegistry(org.apache.camel.spi.Registry)
515 */
516 public void setJndiContext(Context jndiContext) {
517 setRegistry(new JndiRegistry(jndiContext));
518 }
519
520 public void setRegistry(Registry registry) {
521 this.registry = registry;
522 }
523
524 public LifecycleStrategy getLifecycleStrategy() {
525 return lifecycleStrategy;
526 }
527
528 public void setLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
529 this.lifecycleStrategy = lifecycleStrategy;
530 }
531
532 public List<RouteType> getRouteDefinitions() {
533 return routeDefinitions;
534 }
535
536 public List<InterceptStrategy> getInterceptStrategies() {
537 return interceptStrategies;
538 }
539
540 public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
541 this.interceptStrategies = interceptStrategies;
542 }
543
544 public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
545 getInterceptStrategies().add(interceptStrategy);
546 }
547
548 /**
549 * Returns true if tracing has been enabled or disabled via the {@link #setTrace(Boolean)} method
550 * or it has not been specified then default to the <b>camel.trace</b> system property
551 */
552 public boolean getTrace() {
553 final Boolean value = getTracing();
554 if (value != null) {
555 return value;
556 } else {
557 return SystemHelper.isSystemProperty("camel.trace");
558 }
559 }
560
561 public Boolean getTracing() {
562 return trace;
563 }
564
565 public void setTrace(Boolean trace) {
566 this.trace = trace;
567 }
568
569 /**
570 * Returns the delay in millis if delaying has been enabled or disabled via the {@link #setDelay(Long)} method
571 * or it has not been specified then default to the <b>camel.delay</b> system property
572 */
573 public long getDelay() {
574 final Long value = getDelaying();
575 if (value != null) {
576 return value;
577 } else {
578 String prop = SystemHelper.getSystemProperty("camel.delay");
579 return prop != null ? Long.getLong(prop) : 0;
580 }
581 }
582
583 public Long getDelaying() {
584 return delay;
585 }
586
587 public void setDelay(Long delay) {
588 this.delay = delay;
589 }
590
591 public <E extends Exchange> ProducerTemplate<E> createProducerTemplate() {
592 return new DefaultProducerTemplate<E>(this);
593 }
594
595 public ErrorHandlerBuilder getErrorHandlerBuilder() {
596 return errorHandlerBuilder;
597 }
598
599 /**
600 * Sets the default error handler builder which is inherited by the routes
601 */
602 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
603 this.errorHandlerBuilder = errorHandlerBuilder;
604 }
605
606 public void start() throws Exception {
607 super.start();
608
609 // the context is now considered started (i.e. isStarted() == true))
610 // starting routes is done after, not during context startup
611 synchronized (this) {
612 startRoutes(routes);
613 }
614
615 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") started");
616 }
617
618 // Implementation methods
619 // -----------------------------------------------------------------------
620
621 protected void doStart() throws Exception {
622 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is starting");
623
624 if (getTrace()) {
625 // only add a new tracer if not already configued
626 if (Tracer.getTracer(this) == null) {
627 Tracer tracer = new Tracer();
628 // lets see if we have a formatter if so use it
629 TraceFormatter formatter = this.getRegistry().lookup("traceFormatter", TraceFormatter.class);
630 if (formatter != null) {
631 tracer.setFormatter(formatter);
632 }
633 addInterceptStrategy(tracer);
634 }
635 }
636
637 if (getDelay() > 0) {
638 // only add a new delayer if not already configued
639 if (Delayer.getDelayer(this) == null) {
640 addInterceptStrategy(new Delayer(getDelay()));
641 }
642 }
643
644 try {
645 lifecycleStrategy.onContextStart(this);
646 } catch (Exception e) {
647 // not all containers allow access to its MBeanServer (such as OC4j)
648 LOG.warn("Cannot start lifecycleStrategy: " + lifecycleStrategy + ". Cause: " + e.getMessage());
649 if (lifecycleStrategy instanceof InstrumentationLifecycleStrategy) {
650 // fallback to non JMX lifecycle to allow Camel to startup
651 LOG.warn("Will fallback to use default (non JMX) lifecycle strategy");
652 lifecycleStrategy = new DefaultLifecycleStrategy();
653 lifecycleStrategy.onContextStart(this);
654 }
655 }
656
657 forceLazyInitialization();
658 if (components != null) {
659 for (Component component : components.values()) {
660 startServices(component);
661 }
662 }
663 // To avoid initiating the routeDefinitions after stopping the camel context
664 if (!routeDefinitionInitiated) {
665 startRouteDefinitions(routeDefinitions);
666 routeDefinitionInitiated = true;
667 }
668 }
669
670 protected void startRouteDefinitions(Collection<RouteType> list) throws Exception {
671 if (list != null) {
672 Collection<Route> routes = new ArrayList<Route>();
673 for (RouteType route : list) {
674 route.addRoutes(this, routes);
675 }
676 addRoutes(routes);
677 }
678 }
679
680 protected void doStop() throws Exception {
681 stopServices(servicesToClose);
682 if (components != null) {
683 for (Component component : components.values()) {
684 stopServices(component);
685 }
686 }
687 servicesToClose.clear();
688 }
689
690 protected void startRoutes(Collection<Route> routeList) throws Exception {
691 if (routeList != null) {
692 for (Route<Exchange> route : routeList) {
693 List<Service> services = route.getServicesForRoute();
694 for (Service service : services) {
695 addService(service);
696 }
697 }
698 }
699 }
700
701 /**
702 * Lets force some lazy initialization to occur upfront before we start any
703 * components and create routes
704 */
705 protected void forceLazyInitialization() {
706 getExchangeConverter();
707 getInjector();
708 getLanguageResolver();
709 getTypeConverter();
710 }
711
712 /**
713 * Lazily create a default implementation
714 */
715 protected ExchangeConverter createExchangeConverter() {
716 return new DefaultExchangeConverter();
717 }
718
719 /**
720 * Lazily create a default implementation
721 */
722 protected TypeConverter createTypeConverter() {
723 return new DefaultTypeConverter(getInjector());
724 }
725
726 /**
727 * Lazily create a default implementation
728 */
729 protected Injector createInjector() {
730 FactoryFinder finder = createFactoryFinder();
731 try {
732 return (Injector) finder.newInstance("Injector");
733 } catch (NoFactoryAvailableException e) {
734 // lets use the default
735 return new ReflectionInjector();
736 } catch (IllegalAccessException e) {
737 throw new RuntimeCamelException(e);
738 } catch (InstantiationException e) {
739 throw new RuntimeCamelException(e);
740 } catch (IOException e) {
741 throw new RuntimeCamelException(e);
742 } catch (ClassNotFoundException e) {
743 throw new RuntimeCamelException(e);
744 }
745 }
746
747 /**
748 * Lazily create a default implementation
749 */
750 protected ComponentResolver createComponentResolver() {
751 return new DefaultComponentResolver();
752 }
753
754 /**
755 * Lazily create a default implementation
756 */
757 protected Registry createRegistry() {
758 return new JndiRegistry();
759 }
760
761 /**
762 * A pluggable strategy to allow an endpoint to be created without requiring
763 * a component to be its factory, such as for looking up the URI inside some
764 * {@link Registry}
765 *
766 * @param uri the uri for the endpoint to be created
767 * @return the newly created endpoint or null if it could not be resolved
768 */
769 protected Endpoint createEndpoint(String uri) {
770 Object value = getRegistry().lookup(uri);
771 if (value instanceof Endpoint) {
772 return (Endpoint) value;
773 } else if (value instanceof Processor) {
774 return new ProcessorEndpoint(uri, this, (Processor) value);
775 } else if (value != null) {
776 return convertBeanToEndpoint(uri, value);
777 }
778 return null;
779 }
780
781 /**
782 * Attempt to convert the bean from a {@link Registry} to an endpoint using
783 * some kind of transformation or wrapper
784 *
785 * @param uri the uri for the endpoint (and name in the registry)
786 * @param bean the bean to be converted to an endpoint, which will be not null
787 * @return a new endpoint
788 */
789 protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
790 throw new IllegalArgumentException("uri: " + uri + " bean: " + bean
791 + " could not be converted to an Endpoint");
792 }
793
794 /**
795 * Should we start newly added routes?
796 */
797 protected boolean shouldStartRoutes() {
798 return isStarted() && !isStarting();
799 }
800
801 public void setDataFormats(Map<String, DataFormatType> dataFormats) {
802 this.dataFormats = dataFormats;
803 }
804
805 public Map<String, DataFormatType> getDataFormats() {
806 return dataFormats;
807 }
808
809 public void setFactoryFinderClass(Class<? extends FactoryFinder> finderClass) {
810 factoryFinderClass = finderClass;
811 }
812
813 public Map<String, String> getProperties() {
814 return properties;
815 }
816
817 public void setProperties(Map<String, String> properties) {
818 this.properties = properties;
819 }
820
821 public FactoryFinder createFactoryFinder() {
822 try {
823 return factoryFinderClass.newInstance();
824 } catch (Exception e) {
825 throw new RuntimeCamelException(e);
826 }
827 }
828
829 public FactoryFinder createFactoryFinder(String path) {
830 try {
831 Constructor<? extends FactoryFinder> constructor;
832 constructor = factoryFinderClass.getConstructor(String.class);
833 return constructor.newInstance(path);
834 } catch (Exception e) {
835 throw new RuntimeCamelException(e);
836 }
837
838 }
839
840
841 protected synchronized String getEndpointKey(String uri, Endpoint endpoint) {
842 if (endpoint.isSingleton()) {
843 return uri;
844 } else {
845 // lets try find the first endpoint key which is free
846 for (int counter = 0; true; counter++) {
847 String key = (counter > 0) ? uri + ":" + counter : uri;
848 if (!endpoints.containsKey(key)) {
849 return key;
850 }
851 }
852 }
853 }
854
855 }