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 }