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    }