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 }