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.servicemix.camel;
018    
019    import java.net.URISyntaxException;
020    import java.util.Map;
021    import java.util.Set;
022    import java.util.concurrent.ConcurrentHashMap;
023    
024    import javax.jbi.management.DeploymentException;
025    import javax.jbi.messaging.ExchangeStatus;
026    import javax.jbi.messaging.MessageExchange;
027    import javax.jbi.messaging.MessagingException;
028    import javax.jbi.messaging.NormalizedMessage;
029    import javax.xml.namespace.QName;
030    
031    import org.apache.camel.AsyncCallback;
032    import org.apache.camel.AsyncProcessor;
033    import org.apache.camel.Exchange;
034    import org.apache.camel.Message;
035    import org.apache.servicemix.common.endpoints.ConsumerEndpoint;
036    import org.apache.servicemix.id.IdGenerator;
037    import org.apache.servicemix.jbi.FaultException;
038    import org.apache.servicemix.jbi.resolver.URIResolver;
039    
040    /**
041     * A consumer endpoint that will be used to send JBI exchanges
042     * originating from camel.
043     */
044    public class CamelConsumerEndpoint extends ConsumerEndpoint implements AsyncProcessor {
045    
046        public static final QName SERVICE_NAME = new QName("http://activemq.apache.org/camel/schema/jbi", "consumer");
047    
048        private JbiBinding binding;
049    
050        private JbiEndpoint jbiEndpoint;
051        
052        private Map<String, AsyncCallback> callbacks = new ConcurrentHashMap<String, AsyncCallback>();
053        private Map<String, Exchange> exchanges = new ConcurrentHashMap<String, Exchange>();
054    
055        public CamelConsumerEndpoint(JbiBinding binding, JbiEndpoint jbiEndpoint) {
056            setService(SERVICE_NAME);
057            setEndpoint(new IdGenerator().generateId());
058            this.binding = binding;
059            this.jbiEndpoint = jbiEndpoint;
060        }
061    
062        public void process(MessageExchange messageExchange) throws Exception {
063            Exchange exchange = exchanges.remove(messageExchange.getExchangeId());
064            if (exchange == null) {
065                String message = String.format("Unable to find Camel Exchange for JBI MessageExchange %s", messageExchange.getExchangeId());
066                logger.warn(message);
067                if (messageExchange.getStatus() == ExchangeStatus.ACTIVE) {
068                    fail(messageExchange, new JbiException(message));
069                }
070            } else {
071                processReponse(messageExchange, exchange);
072            }
073            
074            AsyncCallback asyncCallback = callbacks.remove(messageExchange.getExchangeId());
075            if (asyncCallback == null) {
076                logger.warn(String.format("Unable to find Camel AsyncCallback for JBI MessageExchange %s", messageExchange.getExchangeId()));
077            } else {
078                asyncCallback.done(false);
079            }
080        }
081    
082        public boolean process(Exchange exchange, AsyncCallback asyncCallback) {
083            try {
084                MessageExchange messageExchange = binding.makeJbiMessageExchange(exchange, getExchangeFactory(), jbiEndpoint.getMep());
085    
086                if (jbiEndpoint.getOperation() != null) {
087                    messageExchange.setOperation(QName.valueOf(jbiEndpoint.getOperation()));
088                }
089    
090                URIResolver.configureExchange(messageExchange, getContext(), jbiEndpoint.getDestinationUri());
091                exchanges.put(messageExchange.getExchangeId(), exchange);
092                callbacks.put(messageExchange.getExchangeId(), asyncCallback);
093    
094                send(messageExchange);
095                return false;
096            } catch (Exception e) {
097                exchange.setException(e);
098                asyncCallback.done(true);
099                return true;
100            }
101        }
102    
103        public void process(Exchange exchange) throws Exception {
104            try {
105                MessageExchange messageExchange = binding.makeJbiMessageExchange(exchange, getExchangeFactory(), jbiEndpoint.getMep());
106    
107                if (jbiEndpoint.getOperation() != null) {
108                    messageExchange.setOperation(QName.valueOf(jbiEndpoint.getOperation()));
109                }
110    
111                URIResolver.configureExchange(messageExchange, getContext(), jbiEndpoint.getDestinationUri());
112    
113                sendSync(messageExchange);
114    
115                processReponse(messageExchange, exchange);
116    
117            } catch (MessagingException e) {
118                exchange.setException(e);
119                throw new JbiException(e);
120            } catch (URISyntaxException e) {
121                exchange.setException(e);
122                throw new JbiException(e);
123            }
124        }
125    
126        public String getLocationURI() {
127            return null;
128        }    
129    
130        private void processReponse(MessageExchange messageExchange, Exchange exchange) throws MessagingException {
131            if (messageExchange.getStatus() == ExchangeStatus.ERROR) {
132                exchange.setException(messageExchange.getError());
133            } else if (messageExchange.getStatus() == ExchangeStatus.ACTIVE) {
134                addHeaders(messageExchange, exchange);
135                if (messageExchange.getFault() != null) {
136                    exchange.getFault().setBody(new FaultException("Fault occured for " + exchange.getPattern() + " exchange", 
137                            messageExchange, messageExchange.getFault()));
138                    addHeaders(messageExchange.getFault(), exchange.getFault());
139                    addAttachments(messageExchange.getFault(), exchange.getFault());
140                } else if (messageExchange.getMessage("out") != null) {
141                    exchange.getOut().setBody(messageExchange.getMessage("out").getContent());
142                    addHeaders(messageExchange.getMessage("out"), exchange.getOut());
143                    addAttachments(messageExchange.getMessage("out"), exchange.getOut());
144                }
145                done(messageExchange);
146            }
147        }
148    
149        @Override
150        public void validate() throws DeploymentException {
151            // No validation required
152        }
153    
154        @SuppressWarnings("unchecked")
155        private void addHeaders(MessageExchange messageExchange, Exchange camelExchange) {
156            Set entries = messageExchange.getPropertyNames();
157            for (Object o : entries) {
158                String key = o.toString();
159                camelExchange.setProperty(key, messageExchange.getProperty(key));
160            }
161        }
162    
163        @SuppressWarnings("unchecked")
164        private void addHeaders(NormalizedMessage normalizedMessage, Message camelMessage) {
165            Set entries = normalizedMessage.getPropertyNames();
166            for (Object o : entries) {
167                String key = o.toString();
168                camelMessage.setHeader(key, normalizedMessage.getProperty(key));
169            }
170        }
171    
172        @SuppressWarnings("unchecked")
173        private void addAttachments(NormalizedMessage normalizedMessage, Message camelMessage) {
174            Set entries = normalizedMessage.getAttachmentNames();
175            for (Object o : entries) {
176                String id = o.toString();
177                camelMessage.addAttachment(id, normalizedMessage.getAttachment(id));
178            }
179        }
180    
181    }