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.jbi.nmr;
018    
019    import java.util.Iterator;
020    import java.util.List;
021    import java.util.Set;
022    
023    import javax.jbi.JBIException;
024    import javax.jbi.messaging.DeliveryChannel;
025    import javax.jbi.messaging.InOnly;
026    import javax.jbi.messaging.MessageExchange;
027    import javax.jbi.messaging.MessagingException;
028    import javax.jbi.messaging.NormalizedMessage;
029    
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.apache.servicemix.JbiConstants;
033    import org.apache.servicemix.MessageExchangeListener;
034    import org.apache.servicemix.components.util.ComponentSupport;
035    import org.apache.servicemix.jbi.framework.Registry;
036    import org.apache.servicemix.jbi.messaging.MessageExchangeImpl;
037    import org.apache.servicemix.jbi.servicedesc.InternalEndpoint;
038    
039    /**
040     * Handles publish/subscribe style messaging in the NMR.
041     * 
042     * 
043     * @version $Revision: 564607 $
044     */
045    public class SubscriptionManager extends ComponentSupport implements MessageExchangeListener {
046    
047        public static final String COMPONENT_NAME = "#SubscriptionManager#";
048    
049        private static final Log LOG = LogFactory.getLog(SubscriptionManager.class);
050    
051        // SM-229: Avoid StackOverflowException
052        private static final String FROM_SUBSCRIPTION_MANAGER = "org.apache.servicemix.jbi.nmr.from_subman";
053    
054        private Registry registry;
055    
056        private String flowName;
057    
058        /**
059         * Initialize the SubscriptionManager
060         * 
061         * @param broker
062         * @throws JBIException
063         */
064        public void init(Broker broker, Registry reg) throws JBIException {
065            this.registry = reg;
066            broker.getContainer().activateComponent(this, COMPONENT_NAME);
067        }
068    
069        /**
070         * Dispatches the given exchange to all matching subscribers
071         * 
072         * @param exchange
073         * @return true if dispatched to a matching subscriber(s)
074         * 
075         * @throws JBIException
076         */
077        protected boolean dispatchToSubscribers(MessageExchangeImpl exchange) throws JBIException {
078            Boolean source = (Boolean) exchange.getProperty(FROM_SUBSCRIPTION_MANAGER);
079            if (source == null || !source.booleanValue()) {
080                List<InternalEndpoint> list = registry.getMatchingSubscriptionEndpoints(exchange);
081                if (list != null) {
082                    for (int i = 0; i < list.size(); i++) {
083                        InternalEndpoint endpoint = list.get(i);
084                        dispatchToSubscriber(exchange, endpoint);
085                    }
086                }
087                return list != null && !list.isEmpty();
088            } else {
089                return false;
090            }
091        }
092    
093        /**
094         * Dispatches the given message exchange to the given endpoint
095         * 
096         * @param exchange
097         * @param endpoint
098         * @throws JBIException
099         */
100        protected void dispatchToSubscriber(MessageExchangeImpl exchange, InternalEndpoint endpoint) throws JBIException {
101            if (LOG.isDebugEnabled() && endpoint != null) {
102                LOG.debug("Subscription Endpoint: " + endpoint.getEndpointName());
103            }
104            // SM-229: Avoid StackOverflowException
105            Boolean source = (Boolean) exchange.getProperty(FROM_SUBSCRIPTION_MANAGER);
106            if (source == null || !source.booleanValue()) {
107                DeliveryChannel channel = getDeliveryChannel();
108                InOnly me = channel.createExchangeFactory().createInOnlyExchange();
109                // SM-229: Avoid StackOverflowException
110                me.setProperty(FROM_SUBSCRIPTION_MANAGER, Boolean.TRUE);
111                NormalizedMessage in = me.createMessage();
112                getMessageTransformer().transform(me, exchange.getInMessage(), in);
113                me.setInMessage(in);
114                me.setEndpoint(endpoint);
115                Set names = exchange.getPropertyNames();
116                for (Iterator iter = names.iterator(); iter.hasNext();) {
117                    String name = (String) iter.next();
118                    me.setProperty(name, exchange.getProperty(name));
119                }
120                if (Boolean.TRUE.equals(exchange.getProperty(JbiConstants.SEND_SYNC))) {
121                    channel.sendSync(me);
122                } else {
123                    channel.send(me);
124                }
125            }
126        }
127    
128        public String getFlowName() {
129            return flowName;
130        }
131    
132        public void setFlowName(String flowName) {
133            this.flowName = flowName;
134        }
135    
136        public void onMessageExchange(MessageExchange exchange) throws MessagingException {
137            // We should only receive done exchanges from subscribers
138            // but we need that so that they can be dequeued
139        }
140    
141    }