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