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.builder.ErrorHandlerBuilder;
037 import org.apache.camel.impl.DefaultCamelContext;
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: 705880 $
049 */
050 @XmlRootElement(name = "route")
051 @XmlType(propOrder = {"inputs", "outputs" })
052 @XmlAccessorType(XmlAccessType.PROPERTY)
053 public class RouteType extends ProcessorType<ProcessorType> implements CamelContextAware {
054 private static final transient Log LOG = LogFactory.getLog(RouteType.class);
055 private List<InterceptorType> interceptors = new ArrayList<InterceptorType>();
056 private List<FromType> inputs = new ArrayList<FromType>();
057 private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>();
058 private String group;
059 private CamelContext camelContext;
060 private Boolean streamCaching;
061
062 public RouteType() {
063 }
064
065 public RouteType(String uri) {
066 from(uri);
067 }
068
069 public RouteType(Endpoint endpoint) {
070 from(endpoint);
071 }
072
073 @Override
074 public String toString() {
075 return "Route[" + inputs + " -> " + outputs + "]";
076 }
077
078 public void addRoutes(CamelContext context, Collection<Route> routes) throws Exception {
079 setCamelContext(context);
080
081 if (context instanceof CamelContext) {
082 ErrorHandlerBuilder handler = context.getErrorHandlerBuilder();
083 if (handler != null) {
084 setErrorHandlerBuilderIfNull(handler);
085 }
086 }
087
088 for (FromType fromType : inputs) {
089 addRoutes(routes, fromType);
090 }
091 }
092
093
094 public Endpoint resolveEndpoint(String uri) throws NoSuchEndpointException {
095 CamelContext context = getCamelContext();
096 if (context == null) {
097 throw new IllegalArgumentException("No CamelContext has been injected!");
098 }
099 return CamelContextHelper.getMandatoryEndpoint(context, uri);
100 }
101
102 // Fluent API
103 // -----------------------------------------------------------------------
104
105 /**
106 * Creates an input to the route
107 */
108 public RouteType from(String uri) {
109 getInputs().add(new FromType(uri));
110 return this;
111 }
112
113 /**
114 * Creates an input to the route
115 */
116 public RouteType from(Endpoint endpoint) {
117 getInputs().add(new FromType(endpoint));
118 return this;
119 }
120
121 /**
122 * Set the group name for this route
123 */
124 public RouteType group(String name) {
125 setGroup(name);
126 return this;
127 }
128
129 // Properties
130 // -----------------------------------------------------------------------
131
132 public List<InterceptorType> getInterceptors() {
133 return interceptors;
134 }
135
136 @XmlTransient
137 public void setInterceptors(List<InterceptorType> interceptors) {
138 this.interceptors = interceptors;
139 }
140
141 public List<FromType> getInputs() {
142 return inputs;
143 }
144
145 @XmlElementRef
146 public void setInputs(List<FromType> inputs) {
147 this.inputs = inputs;
148 }
149
150 public List<ProcessorType<?>> getOutputs() {
151 return outputs;
152 }
153
154 @XmlElementRef
155 public void setOutputs(List<ProcessorType<?>> outputs) {
156 this.outputs = outputs;
157
158 // TODO I don't think this is called when using JAXB!
159 if (outputs != null) {
160 for (ProcessorType output : outputs) {
161 configureChild(output);
162 }
163 }
164 }
165
166 public CamelContext getCamelContext() {
167 return camelContext;
168 }
169
170 @XmlTransient
171 public void setCamelContext(CamelContext camelContext) {
172 this.camelContext = camelContext;
173 }
174
175 /**
176 * The group that this route belongs to; could be the name of the RouteBuilder class
177 * or be explicitly configured in the XML.
178 *
179 * May be null.
180 */
181 public String getGroup() {
182 return group;
183 }
184
185 @XmlAttribute
186 public void setGroup(String group) {
187 this.group = group;
188 }
189
190 public Boolean getStreamCaching() {
191 return streamCaching;
192 }
193
194 /**
195 * Enable stream caching on this route
196 * @param streamCaching <code>true</code> for enabling stream caching
197 */
198 @XmlAttribute(required = false)
199 public void setStreamCaching(Boolean streamCaching) {
200 this.streamCaching = streamCaching;
201 if (streamCaching != null && streamCaching) {
202 streamCaching();
203 } else {
204 noStreamCaching();
205 }
206 }
207
208
209 // Implementation methods
210 // -------------------------------------------------------------------------
211 protected void addRoutes(Collection<Route> routes, FromType fromType) throws Exception {
212 RouteContext routeContext = new DefaultRouteContext(this, fromType, routes);
213 routeContext.getEndpoint(); // force endpoint resolution
214 if (camelContext != null) {
215 camelContext.getLifecycleStrategy().onRouteContextCreate(routeContext);
216 }
217
218 List<ProcessorType<?>> list = new ArrayList<ProcessorType<?>>(outputs);
219 for (ProcessorType output : list) {
220 output.addRoutes(routeContext, routes);
221 }
222
223 routeContext.commit();
224 }
225
226 @Override
227 protected void configureChild(ProcessorType output) {
228 super.configureChild(output);
229
230 if (isInheritErrorHandler()) {
231 output.setErrorHandlerBuilder(getErrorHandlerBuilder());
232 }
233
234 List<InterceptorType> interceptors = getInterceptors();
235 for (InterceptorType interceptor : interceptors) {
236 output.addInterceptor(interceptor);
237 }
238 /*
239 List<InterceptorType> list = output.getInterceptors();
240 if (list == null) {
241 LOG.warn("No interceptor collection: " + output);
242 } else {
243 list.addAll(getInterceptors());
244 }
245 */
246 }
247
248 /**
249 * Disable stream caching for this Route.
250 */
251 public RouteType noStreamCaching() {
252 StreamCachingInterceptor.noStreamCaching(interceptors);
253 return this;
254 }
255
256 /**
257 * Enable stream caching for this Route.
258 */
259 public RouteType streamCaching() {
260 addInterceptor(new StreamCachingInterceptor());
261 return this;
262 }
263
264 @Override
265 public void addInterceptor(InterceptorType interceptor) {
266 getInterceptors().add(interceptor);
267 }
268 }