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.impl;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import org.apache.camel.AsyncProcessor;
024    import org.apache.camel.CamelContext;
025    import org.apache.camel.Endpoint;
026    import org.apache.camel.Exchange;
027    import org.apache.camel.NoSuchEndpointException;
028    import org.apache.camel.Processor;
029    import org.apache.camel.Route;
030    import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
031    import org.apache.camel.model.FromType;
032    import org.apache.camel.model.ProcessorType;
033    import org.apache.camel.model.RouteType;
034    import org.apache.camel.processor.Interceptor;
035    import org.apache.camel.processor.Pipeline;
036    import org.apache.camel.processor.ProceedProcessor;
037    import org.apache.camel.processor.UnitOfWorkProcessor;
038    
039    /**
040     * The context used to activate new routing rules
041     *
042     * @version $Revision: 36321 $
043     */
044    public class RouteContext {
045        private RouteType route;
046        private FromType from;
047        private Collection<Route> routes;
048        private Endpoint<? extends Exchange> endpoint;
049        private List<Processor> eventDrivenProcessors = new ArrayList<Processor>();
050        private Interceptor lastInterceptor;
051        private CamelContext camelContext;
052    
053        public RouteContext(RouteType route, FromType from, Collection<Route> routes) {
054            this.route = route;
055            this.from = from;
056            this.routes = routes;
057        }
058    
059        /**
060         * Only used for lazy construction from inside ExpressionType
061         */
062        public RouteContext(CamelContext camelContext) {
063            this.camelContext = camelContext;
064            routes = new ArrayList<Route>();
065            route = new RouteType("temporary");
066        }
067    
068        public Endpoint<? extends Exchange> getEndpoint() {
069            if (endpoint == null) {
070                endpoint = from.resolveEndpoint(this);
071            }
072            return endpoint;
073        }
074    
075        public FromType getFrom() {
076            return from;
077        }
078    
079        public RouteType getRoute() {
080            return route;
081        }
082    
083        public CamelContext getCamelContext() {
084            if (camelContext == null) {
085                camelContext = getRoute().getCamelContext();
086            }
087            return camelContext;
088        }
089    
090        public Processor createProcessor(ProcessorType node) throws Exception {
091            return node.createOutputsProcessor(this);
092        }
093    
094        public Endpoint<? extends Exchange> resolveEndpoint(String uri) {
095            return route.resolveEndpoint(uri);
096        }
097    
098        /**
099         * Resolves an endpoint from either a URI or a named reference
100         */
101        public Endpoint<? extends Exchange> resolveEndpoint(String uri, String ref) {
102            Endpoint<? extends Exchange> endpoint = null;
103            if (uri != null) {
104                endpoint = resolveEndpoint(uri);
105                if (endpoint == null) {
106                    throw new NoSuchEndpointException(uri);
107                }
108            }
109            if (ref != null) {
110                endpoint = lookup(ref, Endpoint.class);
111                if (endpoint == null) {
112                    throw new NoSuchEndpointException("ref:" + ref);
113                }
114            }
115            if (endpoint == null) {
116                throw new IllegalArgumentException("Either 'uri' or 'ref' must be specified on: " + this);
117            } else {
118                return endpoint;
119            }
120        }
121    
122        /**
123         * lookup an object by name and type
124         */
125        public <T> T lookup(String name, Class<T> type) {
126            return getCamelContext().getRegistry().lookup(name, type);
127        }
128    
129        /**
130         * Lets complete the route creation, creating a single event driven route
131         * for the current from endpoint with any processors required
132         */
133        public void commit() {
134            // now lets turn all of the event driven consumer processors into a
135            // single route
136            if (!eventDrivenProcessors.isEmpty()) {
137                Processor processor = Pipeline.newInstance(eventDrivenProcessors);
138    
139                // lets create the async processor
140                final AsyncProcessor asyncProcessor = AsyncProcessorTypeConverter.convert(processor);
141                Processor unitOfWorkProcessor = new UnitOfWorkProcessor(asyncProcessor);
142    
143                // TODO: hz: move all this into the lifecycle strategy! (used by jmx naming strategy)
144                Route edcr = new EventDrivenConsumerRoute(getEndpoint(), unitOfWorkProcessor);
145                edcr.getProperties().put(Route.PARENT_PROPERTY, Integer.toHexString(route.hashCode()));
146                if (route.getGroup() != null) {
147                    edcr.getProperties().put(Route.GROUP_PROPERTY, route.getGroup());
148                }
149                routes.add(edcr);
150            }
151        }
152    
153        public void addEventDrivenProcessor(Processor processor) {
154            eventDrivenProcessors.add(processor);
155        }
156    
157        public void intercept(Interceptor interceptor) {
158    /*
159            InterceptorRef block = new InterceptorRef(interceptor);
160            RouteType route = getRoute();
161            List<ProcessorType<?>> list = route.getOutputs();
162            for (ProcessorType<?> processorType : list) {
163                block.addOutput(processorType);
164            }
165            route.clearOutput();
166            route.addInterceptor(block);
167    */
168    
169            //getRoute().getInterceptors().add(new InterceptorRef(interceptor));
170            lastInterceptor = interceptor;
171        }
172    
173        public Processor createProceedProcessor() {
174            if (lastInterceptor == null) {
175                throw new IllegalArgumentException("Cannot proceed() from outside of an interceptor!");
176            } else {
177                return new ProceedProcessor(lastInterceptor);
178            }
179        }
180    }