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.util.ArrayList;
020 import java.util.Collection;
021 import java.util.List;
022
023 import org.apache.camel.AsyncProcessor;
024 import org.apache.camel.CamelContext;
025 import org.apache.camel.Endpoint;
026 import org.apache.camel.Exchange;
027 import org.apache.camel.NoSuchEndpointException;
028 import org.apache.camel.Processor;
029 import org.apache.camel.Route;
030 import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
031 import org.apache.camel.model.FromType;
032 import org.apache.camel.model.ProcessorType;
033 import org.apache.camel.model.RouteType;
034 import org.apache.camel.processor.Interceptor;
035 import org.apache.camel.processor.Pipeline;
036 import org.apache.camel.processor.ProceedProcessor;
037 import org.apache.camel.processor.UnitOfWorkProcessor;
038
039 /**
040 * The context used to activate new routing rules
041 *
042 * @version $Revision: 36321 $
043 */
044 public class RouteContext {
045 private RouteType route;
046 private FromType from;
047 private Collection<Route> routes;
048 private Endpoint<? extends Exchange> endpoint;
049 private List<Processor> eventDrivenProcessors = new ArrayList<Processor>();
050 private Interceptor lastInterceptor;
051 private CamelContext camelContext;
052
053 public RouteContext(RouteType route, FromType from, Collection<Route> routes) {
054 this.route = route;
055 this.from = from;
056 this.routes = routes;
057 }
058
059 /**
060 * Only used for lazy construction from inside ExpressionType
061 */
062 public RouteContext(CamelContext camelContext) {
063 this.camelContext = camelContext;
064 routes = new ArrayList<Route>();
065 route = new RouteType("temporary");
066 }
067
068 public Endpoint<? extends Exchange> getEndpoint() {
069 if (endpoint == null) {
070 endpoint = from.resolveEndpoint(this);
071 }
072 return endpoint;
073 }
074
075 public FromType getFrom() {
076 return from;
077 }
078
079 public RouteType getRoute() {
080 return route;
081 }
082
083 public CamelContext getCamelContext() {
084 if (camelContext == null) {
085 camelContext = getRoute().getCamelContext();
086 }
087 return camelContext;
088 }
089
090 public Processor createProcessor(ProcessorType node) throws Exception {
091 return node.createOutputsProcessor(this);
092 }
093
094 public Endpoint<? extends Exchange> resolveEndpoint(String uri) {
095 return route.resolveEndpoint(uri);
096 }
097
098 /**
099 * Resolves an endpoint from either a URI or a named reference
100 */
101 public Endpoint<? extends Exchange> resolveEndpoint(String uri, String ref) {
102 Endpoint<? extends Exchange> endpoint = null;
103 if (uri != null) {
104 endpoint = resolveEndpoint(uri);
105 if (endpoint == null) {
106 throw new NoSuchEndpointException(uri);
107 }
108 }
109 if (ref != null) {
110 endpoint = lookup(ref, Endpoint.class);
111 if (endpoint == null) {
112 throw new NoSuchEndpointException("ref:" + ref);
113 }
114 }
115 if (endpoint == null) {
116 throw new IllegalArgumentException("Either 'uri' or 'ref' must be specified on: " + this);
117 } else {
118 return endpoint;
119 }
120 }
121
122 /**
123 * lookup an object by name and type
124 */
125 public <T> T lookup(String name, Class<T> type) {
126 return getCamelContext().getRegistry().lookup(name, type);
127 }
128
129 /**
130 * Lets complete the route creation, creating a single event driven route
131 * for the current from endpoint with any processors required
132 */
133 public void commit() {
134 // now lets turn all of the event driven consumer processors into a
135 // single route
136 if (!eventDrivenProcessors.isEmpty()) {
137 Processor processor = Pipeline.newInstance(eventDrivenProcessors);
138
139 // lets create the async processor
140 final AsyncProcessor asyncProcessor = AsyncProcessorTypeConverter.convert(processor);
141 Processor unitOfWorkProcessor = new UnitOfWorkProcessor(asyncProcessor);
142
143 // TODO: hz: move all this into the lifecycle strategy! (used by jmx naming strategy)
144 Route edcr = new EventDrivenConsumerRoute(getEndpoint(), unitOfWorkProcessor);
145 edcr.getProperties().put(Route.PARENT_PROPERTY, Integer.toHexString(route.hashCode()));
146 if (route.getGroup() != null) {
147 edcr.getProperties().put(Route.GROUP_PROPERTY, route.getGroup());
148 }
149 routes.add(edcr);
150 }
151 }
152
153 public void addEventDrivenProcessor(Processor processor) {
154 eventDrivenProcessors.add(processor);
155 }
156
157 public void intercept(Interceptor interceptor) {
158 /*
159 InterceptorRef block = new InterceptorRef(interceptor);
160 RouteType route = getRoute();
161 List<ProcessorType<?>> list = route.getOutputs();
162 for (ProcessorType<?> processorType : list) {
163 block.addOutput(processorType);
164 }
165 route.clearOutput();
166 route.addInterceptor(block);
167 */
168
169 //getRoute().getInterceptors().add(new InterceptorRef(interceptor));
170 lastInterceptor = interceptor;
171 }
172
173 public Processor createProceedProcessor() {
174 if (lastInterceptor == null) {
175 throw new IllegalArgumentException("Cannot proceed() from outside of an interceptor!");
176 } else {
177 return new ProceedProcessor(lastInterceptor);
178 }
179 }
180 }