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 */
017package org.apache.activemq.camel.component.broker;
018
019import org.apache.activemq.broker.ProducerBrokerExchange;
020import org.apache.activemq.command.ActiveMQMessage;
021import org.apache.camel.AsyncCallback;
022import org.apache.camel.Exchange;
023import org.apache.camel.Message;
024import org.apache.camel.component.jms.JmsMessage;
025import org.apache.camel.impl.DefaultAsyncProducer;
026
027import javax.jms.JMSException;
028import java.util.Map;
029
030public class BrokerProducer extends DefaultAsyncProducer {
031    private final BrokerEndpoint brokerEndpoint;
032
033    public BrokerProducer(BrokerEndpoint endpoint) {
034        super(endpoint);
035        brokerEndpoint = endpoint;
036    }
037
038    @Override
039    public boolean process(Exchange exchange, AsyncCallback callback) {
040        try {
041            //In the middle of the broker - InOut doesn't make any sense
042            //so we do in only
043            return processInOnly(exchange, callback);
044        } catch (Throwable e) {
045            // must catch exception to ensure callback is invoked as expected
046            // to let Camel error handling deal with this
047            exchange.setException(e);
048            callback.done(true);
049            return true;
050        }
051    }
052
053    protected boolean processInOnly(final Exchange exchange, final AsyncCallback callback) {
054        try {
055            ActiveMQMessage message = getMessage(exchange);
056
057            if (message != null) {
058                message.setDestination(brokerEndpoint.getDestination());
059                //if the ProducerBrokerExchange is null the broker will create it
060                ProducerBrokerExchange producerBrokerExchange = (ProducerBrokerExchange) exchange.getProperty(BrokerEndpoint.PRODUCER_BROKER_EXCHANGE);
061
062                brokerEndpoint.inject(producerBrokerExchange, message);
063            }
064        } catch (Exception e) {
065            exchange.setException(e);
066        }
067        callback.done(true);
068        return true;
069    }
070
071    private ActiveMQMessage getMessage(Exchange exchange) throws IllegalStateException, JMSException {
072        Message camelMessage = getMessageFromExchange(exchange);
073        checkOriginalMessage(camelMessage);
074        ActiveMQMessage result = (ActiveMQMessage) ((JmsMessage) camelMessage).getJmsMessage();
075        applyNewHeaders(result, camelMessage.getHeaders());
076        return result;
077    }
078
079    private Message getMessageFromExchange(Exchange exchange) {
080        if (exchange.hasOut()) {
081            return exchange.getOut();
082        }
083
084        return exchange.getIn();
085    }
086
087    private void checkOriginalMessage(Message camelMessage) throws IllegalStateException {
088        /**
089         * We purposely don't want to support injecting messages half-way through
090         * broker processing - use the activemq camel component for that - but
091         * we will support changing message headers and destinations.
092         */
093
094        if (!(camelMessage instanceof JmsMessage)) {
095            throw new IllegalStateException("Not the original message from the broker " + camelMessage);
096        }
097
098        javax.jms.Message message = ((JmsMessage) camelMessage).getJmsMessage();
099
100        if (!(message instanceof ActiveMQMessage)) {
101            throw new IllegalStateException("Not the original message from the broker " + message);
102        }
103    }
104
105    private void applyNewHeaders(ActiveMQMessage message, Map<String, Object> headers) throws JMSException {
106        for (Map.Entry<String, Object> entry : headers.entrySet()) {
107            String key = entry.getKey();
108            Object value = entry.getValue();
109            if(value == null) {
110                continue;
111            }
112            message.setObjectProperty(key, value.toString(), false);
113        }
114    }
115}