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