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: 54143 $
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    }