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.flow;
018
019 import java.util.concurrent.locks.ReadWriteLock;
020 import java.util.concurrent.locks.ReentrantReadWriteLock;
021
022 import javax.jbi.JBIException;
023 import javax.jbi.management.LifeCycleMBean;
024 import javax.jbi.messaging.MessageExchange;
025 import javax.jbi.messaging.MessageExchange.Role;
026 import javax.jbi.messaging.MessagingException;
027 import javax.jbi.servicedesc.ServiceEndpoint;
028 import javax.management.JMException;
029 import javax.management.MBeanAttributeInfo;
030 import javax.management.ObjectName;
031
032 import org.apache.commons.logging.Log;
033 import org.apache.commons.logging.LogFactory;
034 import org.apache.servicemix.JbiConstants;
035 import org.apache.servicemix.executors.ExecutorFactory;
036 import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
037 import org.apache.servicemix.jbi.framework.ComponentNameSpace;
038 import org.apache.servicemix.jbi.management.AttributeInfoHelper;
039 import org.apache.servicemix.jbi.management.BaseLifeCycle;
040 import org.apache.servicemix.jbi.messaging.ExchangePacket;
041 import org.apache.servicemix.jbi.messaging.MessageExchangeImpl;
042 import org.apache.servicemix.jbi.nmr.Broker;
043 import org.apache.servicemix.jbi.servicedesc.InternalEndpoint;
044
045 /**
046 * A simple Straight through flow
047 *
048 * @version $Revision: 644037 $
049 */
050 public abstract class AbstractFlow extends BaseLifeCycle implements Flow {
051
052 protected final Log log = LogFactory.getLog(getClass());
053 protected Broker broker;
054 protected ExecutorFactory executorFactory;
055 private ReadWriteLock lock = new ReentrantReadWriteLock();
056 private Thread suspendThread;
057 private String name;
058
059 /**
060 * Initialize the Region
061 *
062 * @param br
063 * @throws JBIException
064 */
065 public void init(Broker br) throws JBIException {
066 this.broker = br;
067 this.executorFactory = br.getContainer().getExecutorFactory();
068 // register self with the management context
069 ObjectName objectName = br.getContainer().getManagementContext().createObjectName(this);
070 try {
071 br.getContainer().getManagementContext().registerMBean(objectName, this, LifeCycleMBean.class);
072 } catch (JMException e) {
073 throw new JBIException("Failed to register MBean with the ManagementContext", e);
074 }
075 }
076
077 /**
078 * start the flow
079 * @throws JBIException
080 */
081 public void start() throws JBIException {
082 super.start();
083 }
084
085 /**
086 * stop the flow
087 * @throws JBIException
088 */
089 public void stop() throws JBIException {
090 if (log.isDebugEnabled()) {
091 log.debug("Called Flow stop");
092 }
093 if (suspendThread != null) {
094 suspendThread.interrupt();
095 }
096 super.stop();
097 }
098
099 /**
100 * shutDown the flow
101 * @throws JBIException
102 */
103 public void shutDown() throws JBIException {
104 if (log.isDebugEnabled()) {
105 log.debug("Called Flow shutdown");
106 }
107 broker.getContainer().getManagementContext().unregisterMBean(this);
108 super.shutDown();
109 }
110
111 /**
112 * Distribute an ExchangePacket
113 * @param packet
114 * @throws JBIException
115 */
116 public void send(MessageExchange me) throws JBIException {
117 if (log.isDebugEnabled()) {
118 log.debug("Called Flow send");
119 }
120 // do send
121 try {
122 lock.readLock().lock();
123 doSend((MessageExchangeImpl) me);
124 } finally {
125 lock.readLock().unlock();
126 }
127 }
128
129 /**
130 * suspend the flow to prevent any message exchanges
131 */
132 public synchronized void suspend() {
133 if (log.isDebugEnabled()) {
134 log.debug("Called Flow suspend");
135 }
136 lock.writeLock().lock();
137 suspendThread = Thread.currentThread();
138 }
139
140 /**
141 * resume message exchange processing
142 */
143 public synchronized void resume() {
144 if (log.isDebugEnabled()) {
145 log.debug("Called Flow resume");
146 }
147 lock.writeLock().unlock();
148 suspendThread = null;
149 }
150
151 /**
152 * Do the Flow specific routing
153 * @param packet
154 * @throws JBIException
155 */
156 protected abstract void doSend(MessageExchangeImpl me) throws JBIException;
157
158 /**
159 * Distribute an ExchangePacket
160 *
161 * @param packet
162 * @throws MessagingException
163 */
164 protected void doRouting(MessageExchangeImpl me) throws MessagingException {
165 ComponentNameSpace id = me.getRole() == Role.PROVIDER ? me.getDestinationId() : me.getSourceId();
166 //As the MessageExchange could come from another container - ensure we get the local Component
167 ComponentMBeanImpl lcc = broker.getContainer().getRegistry().getComponent(id.getName());
168 if (lcc != null) {
169 if (lcc.getDeliveryChannel() != null) {
170 try {
171 lock.readLock().lock();
172 lcc.getDeliveryChannel().processInBound(me);
173 } finally {
174 lock.readLock().unlock();
175 }
176 } else {
177 throw new MessagingException("Component " + id.getName() + " is shut down");
178 }
179 } else {
180 throw new MessagingException("No component named " + id.getName() + " - Couldn't route MessageExchange " + me);
181 }
182 }
183
184 /**
185 * Get an array of MBeanAttributeInfo
186 *
187 * @return array of AttributeInfos
188 * @throws JMException
189 */
190 public MBeanAttributeInfo[] getAttributeInfos() throws JMException {
191 AttributeInfoHelper helper = new AttributeInfoHelper();
192 helper.addAttribute(getObjectToManage(), "description", "The type of flow");
193 return AttributeInfoHelper.join(super.getAttributeInfos(), helper.getAttributeInfos());
194 }
195
196 /**
197 * Check if the given packet should be persisted or not.
198 * @param packet
199 * @return
200 */
201 protected boolean isPersistent(MessageExchange me) {
202 ExchangePacket packet = ((MessageExchangeImpl) me).getPacket();
203 if (packet.getPersistent() != null) {
204 return packet.getPersistent().booleanValue();
205 } else {
206 return broker.getContainer().isPersistent();
207 }
208 }
209
210 protected boolean isTransacted(MessageExchange me) {
211 return me.getProperty(MessageExchange.JTA_TRANSACTION_PROPERTY_NAME) != null;
212 }
213
214 protected boolean isSynchronous(MessageExchange me) {
215 Boolean sync = (Boolean) me.getProperty(JbiConstants.SEND_SYNC);
216 return sync != null && sync.booleanValue();
217 }
218
219 protected boolean isClustered(MessageExchange me) {
220 MessageExchangeImpl mei = (MessageExchangeImpl) me;
221 if (mei.getDestinationId() == null) {
222 ServiceEndpoint se = me.getEndpoint();
223 if (se instanceof InternalEndpoint) {
224 return ((InternalEndpoint) se).isClustered();
225 // Unknown: assume this is not clustered
226 } else {
227 return false;
228 }
229 } else {
230 String destination = mei.getDestinationId().getContainerName();
231 String source = mei.getSourceId().getContainerName();
232 return !source.equals(destination);
233 }
234 }
235
236 public Broker getBroker() {
237 return broker;
238 }
239
240 /**
241 * Get the type of the item
242 * @return the type
243 */
244 public String getType() {
245 return "Flow";
246 }
247
248 /**
249 * Get the name of the item
250 * @return the name
251 */
252 public String getName() {
253 if (this.name == null) {
254 String n = super.getName();
255 if (n.endsWith("Flow")) {
256 n = n.substring(0, n.length() - 4);
257 }
258 return n;
259 } else {
260 return this.name;
261 }
262 }
263
264 public void setName(String name) {
265 this.name = name;
266 }
267
268 /**
269 * @return the executorFactory
270 */
271 public ExecutorFactory getExecutorFactory() {
272 return executorFactory;
273 }
274
275 }