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.HashMap;
020    import java.util.Map;
021    
022    import org.apache.camel.AsyncCallback;
023    import org.apache.camel.Endpoint;
024    import org.apache.camel.Exchange;
025    import org.apache.camel.ExchangePattern;
026    import org.apache.camel.FailedToCreateProducerException;
027    import org.apache.camel.Processor;
028    import org.apache.camel.Producer;
029    import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
030    import org.apache.camel.util.ServiceHelper;
031    import org.apache.commons.logging.Log;
032    import org.apache.commons.logging.LogFactory;
033    
034    import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException;
035    
036    
037    /**
038     * Cache containing created {@link Producer}.
039     *
040     * @version $Revision: 1242 $
041     */
042    public class ProducerCache<E extends Exchange> extends ServiceSupport {
043        private static final transient Log LOG = LogFactory.getLog(ProducerCache.class);
044    
045        private Map<String, Producer<E>> producers = new HashMap<String, Producer<E>>();
046    
047        public synchronized Producer<E> getProducer(Endpoint<E> endpoint) {
048            String key = endpoint.getEndpointUri();
049            Producer<E> answer = producers.get(key);
050            if (answer == null) {
051                try {
052                    answer = endpoint.createProducer();
053                    answer.start();
054                } catch (Exception e) {
055                    throw new FailedToCreateProducerException(endpoint, e);
056                }
057                producers.put(key, answer);
058            }
059            return answer;
060        }
061    
062        /**
063         * Sends the exchange to the given endpoint
064         *
065         * @param endpoint the endpoint to send the exchange to
066         * @param exchange the exchange to send
067         */
068        public void send(Endpoint<E> endpoint, E exchange) {
069            try {
070                Producer<E> producer = getProducer(endpoint);
071                producer.process(exchange);
072            } catch (Exception e) {
073                throw wrapRuntimeCamelException(e);
074            }
075        }
076    
077        /**
078         * Sends an exchange to an endpoint using a supplied
079         * {@link Processor} to populate the exchange
080         *
081         * @param endpoint the endpoint to send the exchange to
082         * @param processor the transformer used to populate the new exchange
083         */
084        public E send(Endpoint<E> endpoint, Processor processor) {
085            try {
086                Producer<E> producer = getProducer(endpoint);
087                E exchange = producer.createExchange();
088                return sendExchange(endpoint, producer, processor, exchange);
089            } catch (Exception e) {
090                throw wrapRuntimeCamelException(e);
091            }
092        }
093    
094        /**
095         * Sends an exchange to an endpoint using a supplied
096         * {@link Processor} to populate the exchange.  The callback
097         * will be called when the exchange is completed.
098         *
099         * @param endpoint the endpoint to send the exchange to
100         * @param processor the transformer used to populate the new exchange
101         */
102        public E send(Endpoint<E> endpoint, Processor processor, AsyncCallback callback) {
103            try {
104                Producer<E> producer = getProducer(endpoint);
105                E exchange = producer.createExchange();
106                boolean sync = sendExchange(endpoint, producer, processor, exchange, callback);
107                setProcessedSync(exchange, sync);
108                return exchange;
109            } catch (Exception e) {
110                throw wrapRuntimeCamelException(e);
111            }
112        }
113    
114        public static boolean isProcessedSync(Exchange exchange) {
115            Boolean rc = exchange.getProperty(ProducerCache.class.getName() + ".SYNC", Boolean.class);
116            return rc == null ? false : rc;
117        }
118    
119        public static void setProcessedSync(Exchange exchange, boolean b) {
120            exchange.setProperty(ProducerCache.class.getName() + ".SYNC", b ? Boolean.TRUE : Boolean.FALSE);
121        }
122    
123        /**
124         * Sends an exchange to an endpoint using a supplied
125         * {@link Processor} to populate the exchange
126         *
127         * @param endpoint the endpoint to send the exchange to
128         * @param pattern the message {@link ExchangePattern} such as
129         *   {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
130         * @param processor the transformer used to populate the new exchange
131         */
132        public E send(Endpoint<E> endpoint, ExchangePattern pattern, Processor processor) {
133            try {
134                Producer<E> producer = getProducer(endpoint);
135                E exchange = producer.createExchange(pattern);
136                return sendExchange(endpoint, producer, processor, exchange);
137            } catch (Exception e) {
138                throw wrapRuntimeCamelException(e);
139            }
140        }
141    
142    
143        protected E sendExchange(Endpoint<E> endpoint, Producer<E> producer, Processor processor, E exchange) throws Exception {
144            // lets populate using the processor callback
145            processor.process(exchange);
146    
147            // now lets dispatch
148            if (LOG.isDebugEnabled()) {
149                LOG.debug(">>>> " + endpoint + " " + exchange);
150            }
151            producer.process(exchange);
152            return exchange;
153        }
154    
155        protected boolean sendExchange(Endpoint<E> endpoint, Producer<E> producer, Processor processor, E exchange, AsyncCallback callback) throws Exception {
156            // lets populate using the processor callback
157            processor.process(exchange);
158    
159            // now lets dispatch
160            if (LOG.isDebugEnabled()) {
161                LOG.debug(">>>> " + endpoint + " " + exchange);
162            }
163            return AsyncProcessorTypeConverter.convert(producer).process(exchange, callback);
164        }
165    
166        protected void doStop() throws Exception {
167            ServiceHelper.stopServices(producers.values());
168            producers.clear();
169        }
170    
171        protected void doStart() throws Exception {
172        }
173    }