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.model;
018
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.List;
022
023 import javax.xml.bind.annotation.XmlAccessType;
024 import javax.xml.bind.annotation.XmlAccessorType;
025 import javax.xml.bind.annotation.XmlAttribute;
026 import javax.xml.bind.annotation.XmlElementRef;
027 import javax.xml.bind.annotation.XmlRootElement;
028 import javax.xml.bind.annotation.XmlTransient;
029 import javax.xml.bind.annotation.XmlType;
030
031 import org.apache.camel.CamelContext;
032 import org.apache.camel.CamelContextAware;
033 import org.apache.camel.Endpoint;
034 import org.apache.camel.NoSuchEndpointException;
035 import org.apache.camel.Route;
036 import org.apache.camel.ServiceStatus;
037 import org.apache.camel.builder.ErrorHandlerBuilder;
038 import org.apache.camel.impl.DefaultRouteContext;
039 import org.apache.camel.processor.interceptor.StreamCachingInterceptor;
040 import org.apache.camel.spi.RouteContext;
041 import org.apache.camel.util.CamelContextHelper;
042 import org.apache.commons.logging.Log;
043 import org.apache.commons.logging.LogFactory;
044
045 /**
046 * Represents an XML <route/> element
047 *
048 * @version $Revision: 751357 $
049 */
050 @XmlRootElement(name = "route")
051 @XmlType(propOrder = {"inputs", "outputs" })
052 @XmlAccessorType(XmlAccessType.PROPERTY)
053 public class RouteDefinition extends ProcessorDefinition<ProcessorDefinition> implements CamelContextAware {
054 private static final transient Log LOG = LogFactory.getLog(RouteDefinition.class);
055 private List<AbstractInterceptorDefinition> interceptors = new ArrayList<AbstractInterceptorDefinition>();
056 private List<FromDefinition> inputs = new ArrayList<FromDefinition>();
057 private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
058 private String group;
059 private CamelContext camelContext;
060 private Boolean streamCaching;
061
062 public RouteDefinition() {
063 }
064
065 public RouteDefinition(String uri) {
066 from(uri);
067 }
068
069 public RouteDefinition(Endpoint endpoint) {
070 from(endpoint);
071 }
072
073 @Override
074 public String toString() {
075 return "Route[" + inputs + " -> " + outputs + "]";
076 }
077
078
079 /**
080 * Returns the status of the route if it has been registered with a {@link CamelContext}
081 */
082 public ServiceStatus getStatus() {
083 if (camelContext != null) {
084 ServiceStatus answer = camelContext.getRouteStatus(this);
085 if (answer == null) {
086 answer = ServiceStatus.Stopped;
087 }
088 return answer;
089 }
090 return null;
091 }
092
093 public boolean isStartable() {
094 ServiceStatus status = getStatus();
095 if (status == null) {
096 return true;
097 } else {
098 return status.isStartable();
099 }
100 }
101
102 public boolean isStoppable() {
103 ServiceStatus status = getStatus();
104 if (status == null) {
105 return false;
106 } else {
107 return status.isStoppable();
108 }
109 }
110
111 public List<RouteContext> addRoutes(CamelContext context, Collection<Route> routes) throws Exception {
112 List<RouteContext> answer = new ArrayList<RouteContext>();
113 setCamelContext(context);
114
115 ErrorHandlerBuilder handler = context.getErrorHandlerBuilder();
116 if (handler != null) {
117 setErrorHandlerBuilderIfNull(handler);
118 }
119
120 for (FromDefinition fromType : inputs) {
121 RouteContext routeContext = addRoutes(routes, fromType);
122 answer.add(routeContext);
123 }
124 return answer;
125 }
126
127
128 public Endpoint resolveEndpoint(String uri) throws NoSuchEndpointException {
129 CamelContext context = getCamelContext();
130 if (context == null) {
131 throw new IllegalArgumentException("CamelContext has not been injected!");
132 }
133 return CamelContextHelper.getMandatoryEndpoint(context, uri);
134 }
135
136 // Fluent API
137 // -----------------------------------------------------------------------
138
139 /**
140 * Creates an input to the route
141 *
142 * @param uri the from uri
143 * @return the builder
144 */
145 public RouteDefinition from(String uri) {
146 getInputs().add(new FromDefinition(uri));
147 return this;
148 }
149
150 /**
151 * Creates an input to the route
152 *
153 * @param endpoint the from endpoint
154 * @return the builder
155 */
156 public RouteDefinition from(Endpoint endpoint) {
157 getInputs().add(new FromDefinition(endpoint));
158 return this;
159 }
160
161 /**
162 * Creates inputs to the route
163 *
164 * @param uris the from uris
165 * @return the builder
166 */
167 public RouteDefinition from(String... uris) {
168 for (String uri : uris) {
169 getInputs().add(new FromDefinition(uri));
170 }
171 return this;
172 }
173
174 /**
175 * Creates inputs to the route
176 *
177 * @param endpoints the from endpoints
178 * @return the builder
179 */
180 public RouteDefinition from(Endpoint... endpoints) {
181 for (Endpoint endpoint : endpoints) {
182 getInputs().add(new FromDefinition(endpoint));
183 }
184 return this;
185 }
186
187 /**
188 * Set the group name for this route
189 *
190 * @param name the group name
191 * @return the builder
192 */
193 public RouteDefinition group(String name) {
194 setGroup(name);
195 return this;
196 }
197
198 /**
199 * Disable stream caching for this route
200 *
201 * @return the builder
202 */
203 public RouteDefinition noStreamCaching() {
204 StreamCachingInterceptor.noStreamCaching(interceptors);
205 return this;
206 }
207
208 /**
209 * Enable stream caching for this route
210 *
211 * @return the builder
212 */
213 public RouteDefinition streamCaching() {
214 addInterceptor(new StreamCachingInterceptor());
215 return this;
216 }
217
218 // Properties
219 // -----------------------------------------------------------------------
220
221 public List<AbstractInterceptorDefinition> getInterceptors() {
222 return interceptors;
223 }
224
225 @XmlTransient
226 public void setInterceptors(List<AbstractInterceptorDefinition> interceptors) {
227 this.interceptors = interceptors;
228 }
229
230 public List<FromDefinition> getInputs() {
231 return inputs;
232 }
233
234 @XmlElementRef
235 public void setInputs(List<FromDefinition> inputs) {
236 this.inputs = inputs;
237 }
238
239 public List<ProcessorDefinition> getOutputs() {
240 return outputs;
241 }
242
243 @XmlElementRef
244 public void setOutputs(List<ProcessorDefinition> outputs) {
245 this.outputs = outputs;
246
247 // TODO I don't think this is called when using JAXB!
248 if (outputs != null) {
249 for (ProcessorDefinition output : outputs) {
250 configureChild(output);
251 }
252 }
253 }
254
255 public CamelContext getCamelContext() {
256 return camelContext;
257 }
258
259 @XmlTransient
260 public void setCamelContext(CamelContext camelContext) {
261 this.camelContext = camelContext;
262 }
263
264 /**
265 * The group that this route belongs to; could be the name of the RouteBuilder class
266 * or be explicitly configured in the XML.
267 *
268 * May be null.
269 */
270 public String getGroup() {
271 return group;
272 }
273
274 @XmlAttribute
275 public void setGroup(String group) {
276 this.group = group;
277 }
278
279 public Boolean getStreamCaching() {
280 return streamCaching;
281 }
282
283 /**
284 * Enable stream caching on this route
285 * @param streamCaching <code>true</code> for enabling stream caching
286 */
287 @XmlAttribute(required = false)
288 public void setStreamCaching(Boolean streamCaching) {
289 this.streamCaching = streamCaching;
290 if (streamCaching != null && streamCaching) {
291 streamCaching();
292 } else {
293 noStreamCaching();
294 }
295 }
296
297
298 // Implementation methods
299 // -------------------------------------------------------------------------
300 protected RouteContext addRoutes(Collection<Route> routes, FromDefinition fromType) throws Exception {
301 RouteContext routeContext = new DefaultRouteContext(this, fromType, routes);
302 routeContext.getEndpoint(); // force endpoint resolution
303 if (camelContext != null) {
304 camelContext.getLifecycleStrategy().onRouteContextCreate(routeContext);
305 }
306
307 List<ProcessorDefinition> list = new ArrayList<ProcessorDefinition>(outputs);
308 for (ProcessorDefinition output : list) {
309 output.addRoutes(routeContext, routes);
310 }
311
312 routeContext.commit();
313 return routeContext;
314 }
315
316 @Override
317 protected void configureChild(ProcessorDefinition output) {
318 super.configureChild(output);
319
320 if (isInheritErrorHandler()) {
321 output.setErrorHandlerBuilder(getErrorHandlerBuilder());
322 }
323
324 List<AbstractInterceptorDefinition> interceptors = getInterceptors();
325 for (AbstractInterceptorDefinition interceptor : interceptors) {
326 output.addInterceptor(interceptor);
327 }
328 }
329
330 @Override
331 public void addInterceptor(AbstractInterceptorDefinition interceptor) {
332 getInterceptors().add(interceptor);
333 }
334
335 }