Package org.jboss.internal.soa.esb.couriers.transport

Source Code of org.jboss.internal.soa.esb.couriers.transport.InVMTransport$InVMEntry

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.internal.soa.esb.couriers.transport;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.couriers.tx.InVMXAResource;
import org.jboss.internal.soa.esb.message.format.MessageSerializer;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.eprs.InVMEpr;
import org.jboss.soa.esb.common.TransactionStrategy;
import org.jboss.soa.esb.common.TransactionStrategyException;
import org.jboss.soa.esb.message.ByReferenceMessage;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.services.registry.ServiceNotFoundException;

/**
* Provide support for the InVM transports and EPRs.
*
* The InVM transport is divided into two distinct types, permanent transports which
* represent ESB aware services and temporary transports which represent default reply
* queues.
*
* This class provides the interface and support for registry queries/permanent transports
* while support for the temporary queues are through the InVMTemporaryTransport class.
*
* @author kevin
*/
public class InVMTransport
{
    /**
     * The logger for this instance.
     */
    private static final Logger LOGGER = Logger.getLogger(InVMTransport.class) ;
   
    /**
     * Mapping of service ids to entries.
     */
    private final Map<String, InVMEntry> serviceIdToEntry = new HashMap<String, InVMEntry>() ;
    /**
     * Mapping of category names to service names and entries.
     */
    private final Map<String, Map<String, InVMEntry>> categoryToNameToEntry = new HashMap<String, Map<String,InVMEntry>>() ;
    /**
     * The lock guarding access and modification to the structures.
     */
    private ReadWriteLock lock = new ReentrantReadWriteLock() ;

    /**
     * Factory singleton instance.
     */
    private static InVMTransport instance = new InVMTransport();

    /**
     * Get the InVM Transport.
     * @return The InVM Transport instance.
     */
    public static InVMTransport getInstance()
    {
        return instance;
    }

    /**
     * Register the specific EPR against the service category/name.
     *
     * @param category The service category.
     * @param name The service name.
     * @param epr The associated InVM EPR.
     *
     * @throws InVMException for InVM transport specific errors.
     */
    public void registerEPR(final String category, final String name, final InVMEpr epr)
        throws InVMException
    {
        if (epr.isTemporaryEPR())
        {
            throw new InVMException("Attempt to register temporary EPR in permanent registry") ;
        }
       
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Registering EPR " + epr + " for category " + category + ", name " + name) ;
        }
        final String serviceId = epr.getServiceId() ;
        acquireWriteLock() ;
        try
        {
            final InVMEntry existingEntry = serviceIdToEntry.get(serviceId) ;
            Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry == null)
            {
                if (existingEntry != null)
                {
                    throw new InVMException("Service " + serviceId + " registered under a multiple categories") ;
                }
                nameToEntry = new HashMap<String, InVMEntry>() ;
                categoryToNameToEntry.put(category, nameToEntry) ;
            }
           
            InVMEntry entry = nameToEntry.get(name) ;
            if (entry == null)
            {
                if (existingEntry != null)
                {
                    throw new InVMException("Service " + serviceId + " registered under a multiple names") ;
                }
                entry = new InVMEntry(serviceId) ;
                nameToEntry.put(name, entry) ;
            }
            else if ((existingEntry != null) && (existingEntry != entry))
            {
                throw new InVMException("Service " + serviceId + " registered under a multiple names") ;
            }
           
            if (entry.addEPR(epr))
            {
                serviceIdToEntry.put(serviceId, entry) ;
            }
        }
        finally
        {
            releaseWriteLock() ;
        }
    }

    /**
     * Unregister the service category/name.
     *
     * @param category The service category.
     * @param name The service name.
     * @return true if the service was removed, false otherwise
     */
    public boolean unRegisterService(final String category, final String name)
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Unregistering service category " + category + ", name " + name) ;
        }
        acquireWriteLock() ;
        try
        {
            Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry == null)
            {
                return false ;
            }
           
            InVMEntry entry = nameToEntry.remove(name) ;
            if (entry == null)
            {
                return false ;
            }
            entry.shutdown() ;
            if (nameToEntry.isEmpty())
            {
                categoryToNameToEntry.remove(category) ;
            }
            serviceIdToEntry.remove(entry.getServiceId()) ;
            return true ;
        }
        finally
        {
            releaseWriteLock() ;
        }
    }

    /**
     * Unregister the specific EPR from the service category/name.
     *
     * @param category The service category.
     * @param name The service name.
     * @param epr The associated InVM EPR.
     *
     * @throws ServiceNotFoundException if the service/EPR combination is not found.
     */
    public void unRegisterEPR(final String category, final String name, final InVMEpr epr)
        throws ServiceNotFoundException
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Unregistering EPR " + epr + " for category " + category + ", name " + name) ;
        }
        acquireWriteLock() ;
        try
        {
            Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry == null)
            {
                throw new ServiceNotFoundException("Could not locate any services for category " + category) ;
            }
           
            InVMEntry entry = nameToEntry.get(name) ;
            if (entry == null)
            {
                throw new ServiceNotFoundException("Could not locate service " + category + ", " + name) ;
            }
            if (entry.removeEPR(epr))
            {
                nameToEntry.remove(name) ;
                entry.shutdown() ;
                if (nameToEntry.isEmpty())
                {
                    categoryToNameToEntry.remove(category) ;
                }
                serviceIdToEntry.remove(entry.getServiceId()) ;
            }
        }
        finally
        {
            releaseWriteLock() ;
        }
    }

    /**
     * Retrieve a list of all known services.
     * @return The known services.
     */
    public List<String> findAllServices()
    {
        final List<String> result = new ArrayList<String>() ;
       
        acquireReadLock() ;
        try
        {
            for(Map<String, InVMEntry> nameToEntry: categoryToNameToEntry.values())
            {
                result.addAll(nameToEntry.keySet()) ;
            }
        }
        finally
        {
            releaseReadLock() ;
        }
        return result ;
    }

    /**
     * Retrieve a list of all known services in a specified category.
     * @param category The category to query.
     * @return The known services.
     */
    public List<String> findServices(final String category)
    {
        final List<String> result = new ArrayList<String>() ;
       
        acquireReadLock() ;
        try
        {
            final Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry != null)
            {
                result.addAll(nameToEntry.keySet()) ;
            }
        }
        finally
        {
            releaseReadLock() ;
        }
        return result ;
    }

    /**
     * Retrieve a list of EPRs for the specified category and name.
     * @param category The service category to query.
     * @param name The service name to query.
     * @return The known EPRs.
     */
    public List<EPR> findEPRs(final String category, final String name)
    {
        final List<EPR> result = new ArrayList<EPR>() ;
       
        acquireReadLock() ;
        try
        {
            final Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry != null)
            {
                final InVMEntry entry = nameToEntry.get(name) ;
                if (entry != null)
                {
                    result.addAll(entry.getEPRs()) ;
                }
            }
        }
        finally
        {
            releaseReadLock() ;
        }
        return result ;
    }

    /**
     * Retrieve an EPR for the specified category and name.
     * @param category The service category to query.
     * @param name The service name to query.
     * @return An EPR for the specified category and name or null if not registered.
     */
    public EPR findEPR(final String category, final String name)
    {
        acquireReadLock() ;
        try
        {
            final Map<String, InVMEntry> nameToEntry = categoryToNameToEntry.get(category) ;
            if (nameToEntry != null)
            {
                final InVMEntry entry = nameToEntry.get(name) ;
                if (entry != null)
                {
                    return entry.getEPRs().get(0) ;
                }
            }
        }
        finally
        {
            releaseReadLock() ;
        }
        return null;
    }
   
    /**
     * Deliver a message to the specified EPR.
     * @param inVMEpr The EPR to receive the message.
     * @param message The message to deliver.
     * @throws InVMException for InVM transport specific errors.
     */
    public void deliver(final InVMEpr inVMEpr, final Message message)
        throws InVMException
    {
        final String serviceId = inVMEpr.getServiceId() ;
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Delivering message to " + serviceId) ;
        }
        final InVMEntry entry ;
        final boolean passByValue ;
        final long lockstep ;
        acquireReadLock() ;
        try
        {
            entry = serviceIdToEntry.get(serviceId) ;
            if (entry == null)
            {
                throw new InVMException("Could not locate service entry for epr " + inVMEpr) ;
            }
            passByValue = entry.isPassByValue() ;
            lockstep = entry.getLockstep() ;
        }
        finally
        {
            releaseReadLock() ;
        }

        final Object addedObject = toDeliveryObject(message, passByValue);
       
        if (isTransactional())
        {
            if (LOGGER.isDebugEnabled())
            {
                LOGGER.debug("Delivering transactional message to " + serviceId) ;
            }
            /*
             * Can't do lockstep wait here because otherwise the transaction may not terminate if this
             * is the transaction controller thread!
             */
            final TransactionStrategy txStrategy = TransactionStrategy.getTransactionStrategy(true) ;
            try
            {
                txStrategy.enlistResource(new InVMXAResource(inVMEpr, addedObject, InVMXAResource.Operation.INSERT));
            }
            catch (final TransactionStrategyException tse)
            {
                throw new InVMException("Unexpected error enlisting transaction resource", tse) ;
            }
        }
        else
        {
            if (LOGGER.isDebugEnabled())
            {
                LOGGER.debug("Delivering message direct to " + serviceId + " queue") ;
            }
            entry.deliver(addedObject, lockstep) ;
        }
    }

    /**
     * Pickup a message for the specified EPR.
     * @param inVMEpr The EPR to receive the message.
     * @param millis The number of milliseconds to wait for a message.
     * @return The message or null if nothing present within the timeout.
     * @throws InVMException for InVM transport specific errors.
     */
    public Message pickup(final InVMEpr inVMEpr, final long millis)
        throws InVMException
    {
        final String serviceId = inVMEpr.getServiceId() ;
        final InVMEntry entry ;
        acquireReadLock() ;
        try
        {
            entry = serviceIdToEntry.get(serviceId) ;
        }
        finally
        {
            releaseReadLock() ;
        }
        if (entry == null)
        {
            throw new InVMException("Could not locate service entry for epr " + inVMEpr) ;
        }

        final Object msgObject = entry.pickup(millis) ;
        if (msgObject != null)
        {
            if (LOGGER.isDebugEnabled())
            {
                LOGGER.debug("Pickup of message from " + serviceId) ;
            }

            final Message message = fromDeliveryObject(msgObject, inVMEpr.getPassByValue());

            if (isTransactional())
            {
                /*
                 * Return the message, but don't remove it from the queue until the transaction
                 * commits. If the transaction rolls back then the message may not go back into the
                 * queue at the exact place it was originally: other messages may have been removed
                 * successfully by other threads. Plus, we would have to maintain a before and after
                 * image of the queue. This is more a compensation transaction.
                 */
                if (LOGGER.isDebugEnabled())
                {
                    LOGGER.debug("Pickup enlisting transactional resource for service " + serviceId) ;
                }
                final TransactionStrategy txStrategy = TransactionStrategy.getTransactionStrategy(true) ;
                try
                {
                    txStrategy.enlistResource(new InVMXAResource(inVMEpr, msgObject, InVMXAResource.Operation.REMOVE)) ;
                }
                catch (final TransactionStrategyException tse)
                {
                    throw new InVMException("Unexpected error enlisting transaction resource", tse) ;
                }
            }
            return message ;
        }
        return null ;
    }

    /**
     * Deliver an object as a consequence of a transaction.  This will either be a
     * rollback, placing the object back on the source queue, or a commit delivering
     * to a target queue.
     *
     * @param inVMEpr The EPR to receive the message.
     * @param msgObject The object to deliver.
     * @throws InVMException for InVM transport specific errors.
     */
    public void deliverTx(final InVMEpr inVMEpr, final Object msgObject)
        throws InVMException
    {
        final String serviceId = inVMEpr.getServiceId() ;
        final InVMEntry entry ;
        acquireReadLock() ;
        try
        {
            entry = serviceIdToEntry.get(serviceId) ;
        }
        finally
        {
            releaseReadLock() ;
        }
        if (entry == null)
        {
            throw new InVMException("Could not locate service entry for epr " + inVMEpr) ;
        }

        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Transactional redelivery of message to " + serviceId) ;
        }
        entry.deliver(msgObject, 0) ;
    }

    /**
     * Encode a message to an Object ready for delivery.
     * @param message The message to be encoded.
     * @param passByValue If the message will be delivered by value (as opposed to be reference).
     * @return The delivery Object.
     * @throws InVMException Error encoding message.
     */
    public static Object toDeliveryObject(Message message, boolean passByValue) throws InVMException {
        final Object object ;
        if (passByValue)
        {
            try
            {
                object = MessageSerializer.serialize(message) ;
            }
            catch (final IOException ex)
            {
                throw new InVMException("Could not serialize message to pass by value.", ex) ;
            }
        }
        else if (message instanceof ByReferenceMessage)
        {
            object = ((ByReferenceMessage)message).reference() ;
        }
        else
        {
            object = message ;
        }
        return object;
    }

    /**
     * Decode a delivery Object instance back to an ESB {@link Message} object instance.
     * @param msgObject The delivery Object to be decoded.
     * @param passByValue If the message was delivered by value (as opposed to be reference).
     * @return The ESB Message Object instance.
     * @throws InVMException Error decoding message.
     */
    public static Message fromDeliveryObject(Object msgObject, boolean passByValue) throws InVMException {
        final Message message ;
        try
        {
            if (msgObject instanceof byte[])
            {
                message = MessageSerializer.deserialize((byte[])msgObject) ;
            }
            else if (passByValue)
            {
                // pass by reference but now expecting value.
                message = ((Message)msgObject).copy() ;
            }
            else
            {
                message = (Message)msgObject ;
            }
        }
        catch (final IOException ioe)
        {
            throw new InVMException("Failed to deserialise incoming message", ioe) ;
        }
        return message;
    }

    /**
     * Acquire a read lock for accessing the data.
     */
    private void acquireReadLock()
    {
        lock.readLock().lock() ;
    }
   
    /**
     * Release a read lock for accessing the data.
     */
    private void releaseReadLock()
    {
        lock.readLock().unlock() ;
    }
   
    /**
     * Acquire a write lock for accessing the data.
     */
    private void acquireWriteLock()
    {
        lock.writeLock().lock() ;
    }
   
    /**
     * Release a write lock for accessing the data.
     */
    private void releaseWriteLock()
    {
        lock.writeLock().unlock() ;
    }
   
    /**
     * TODO this is used in a number of classes so should be a separate
     * util routine.
     */
    static boolean isTransactional()
        throws InVMException
    {
        boolean transactional;
        try
        {
            TransactionStrategy txStrategy = TransactionStrategy.getTransactionStrategy(true);
            Object txHandle = ((txStrategy == null) ? null : txStrategy.getTransaction());
            boolean isActive = ((txStrategy == null) ? false : txStrategy.isActive());

            transactional = (txHandle != null);

            /*
            * Make sure the current transaction is still active! If we
            * have previously slept, then the timeout may be longer than that
            * associated with the transaction.
            */

            if (transactional && !isActive)
            {
                throw new InVMException("Associated transaction is no longer active!");
            }
        }
        catch (final TransactionStrategyException ex)
        {
            throw new InVMException(ex);
        }
        return transactional;
    }
   
    /**
     * Data representing an entry in the message queue.
     * @author kevin
     */
    private static class InVMQueueEntry
    {
        /**
         * The value enqueued.
         */
        private final Object value ;
        /**
         * Condition associated with lockstep.
         */
        private final Condition condition ;
       
        /**
         * Construct the InVM queue entry.
         * @param value The value being enqueued.
         * @param condition The condition representing the lockstep or null if not required.
         */
        InVMQueueEntry(final Object value, final Condition condition)
        {
            this.value = value ;
            this.condition = condition ;
        }
       
        /**
         * Get the enqueued value.
         * @return The enqueued value.
         */
        Object getValue()
        {
            return value ;
        }
       
        /**
         * Get the lockstep condition.
         * @return The lockstep condition or null if not necessary.
         */
        Condition getCondition()
        {
            return condition ;
        }
    }
   
    /**
     * The InVM entries in the data structures.
     * @author kevin
     */
    private static class InVMEntry
    {
        /**
         * The lock for the queue.
         */
        private final Lock lock = new ReentrantLock() ;
        /**
         * The condition on which to await messages.
         */
        private final Condition waitingCondition = lock.newCondition() ;
        /**
         * The number of waiters on the waiting condition.
         */
        private int numWaiters ;
        /**
         * Flag indicating service has been shutdown.
         */
        private boolean shutdown ;
        /**
         * Entries in the queue.
         */
        private final Queue<InVMQueueEntry> entries = new LinkedList<InVMQueueEntry>() ;
        /**
         * Current EPRs.
         */
        private final List<InVMEpr> eprs = new LinkedList<InVMEpr>() ;
        /**
         * The service id for this entry.
         */
        private final String serviceId ;
        /**
         * The number of EPRs supporting pass by value.
         */
        private int numPassByValue ;
        /**
         * The maximum lockstep value.
         */
        private long lockstep ;
       
        /**
         * Create an entry with the specified service id.
         * @param serviceId The service id.
         */
        InVMEntry(final String serviceId)
        {
            this.serviceId = serviceId ;
        }
       
        /**
         * Get the service id associated with this entry.
         * @return The service id.
         */
        String getServiceId()
        {
            return serviceId ;
        }
       
        /**
         * Get the EPRs associated with this entry.
         * Must hold external lock before accessing.
         *
         * @return the service EPRs.
         */
        List<InVMEpr> getEPRs()
        {
            return eprs ;
        }
       
        /**
         * Add an EPR into this entry.
         * Must hold external write lock before accessing.
         *
         * @param epr the EPR to register with this entry.
         * @return true if this is the first epr, false otherwise.
         */
        boolean addEPR(final InVMEpr epr)
        {
            boolean result = eprs.isEmpty() ;
            eprs.add(epr) ;
            if (epr.getPassByValue())
            {
                numPassByValue ++ ;
            }
            if (epr.getLockstep())
            {
                final long eprLockstep = epr.getLockstepWaitTime() ;
                if (eprLockstep > lockstep)
                {
                    lockstep = eprLockstep ;
                }
            }
            return result ;
        }
       
        /**
         * Remove an EPR from this entry.
         * Must hold external write lock before accessing.
         *
         * @param epr the EPR to remove from this entry.
         * @return true if this is the last epr, false otherwise.
         * @throws ServiceNotFoundException if the EPR cannot be located.
         */
        boolean removeEPR(final InVMEpr epr)
            throws ServiceNotFoundException
        {
            if (!eprs.remove(epr))
            {
                throw new ServiceNotFoundException("Could not locate the EPR in the current service") ;
            }
            if (epr.getPassByValue())
            {
                numPassByValue-- ;
            }
            if (epr.getLockstep())
            {
                if (epr.getLockstepWaitTime() == lockstep)
                {
                    lockstep = 0 ;
                    for(InVMEpr inVMEpr: eprs)
                    {
                        if (inVMEpr.getLockstep())
                        {
                            final long eprLockstep = inVMEpr.getLockstepWaitTime() ;
                            if (eprLockstep > lockstep)
                            {
                                lockstep = eprLockstep ;
                            }
                        }
                    }
                }
            }
            return eprs.isEmpty() ;
        }
       
        /**
         * Shutdown this entry, releasing any waiters.
         * Can hold external write lock before accessing.
         */
        public void shutdown()
        {
            lock.lock() ;
            try
            {
                shutdown = true ;
                if (numWaiters > 0)
                {
                    waitingCondition.signalAll() ;
                }
            }
            finally
            {
                lock.unlock() ;
            }
        }
       
        /**
         * Should we pass the message by value?
         * Must hold external lock before querying.
         *
         * @return true if should pass by value, false otherwise.
         */
        public boolean isPassByValue()
        {
            return numPassByValue > 0 ;
        }
       
        /**
         * Get the lockstep value.
         * Must hold external lock before querying.
         *
         * @return the lockstep value or 0 if not active.
         */
        public long getLockstep()
        {
            return lockstep ;
        }
       
        /**
         * Deliver the specified value onto the queue.
         *
         * N.B. Must not hold external lock while calling this method.
         *
         * @param value The value being appended to the queue.
         * @param lockstep The lockstep timeout or 0 if not required.
         *
         * @throws InVMException for InVM transport specific errors.
         */
        public void deliver(final Object value, final long lockstep)
            throws InVMException
        {
            lock.lock() ;
            try
            {
                if (shutdown)
                {
                    throw new InVMException("InVM Transport already shutdown") ;
                }
                final Condition condition = (lockstep > 0 ? lock.newCondition() : null) ;
                final InVMQueueEntry queueEntry = new InVMQueueEntry(value, condition) ;
                if (!entries.offer(queueEntry))
                {
                    throw new InVMException("Failed to append message to InVM queue") ;
                }
                if (numWaiters > 0)
                {
                    waitingCondition.signal() ;
                }
               
                if (condition != null)
                {
                    try
                    {
                        condition.await(lockstep, TimeUnit.MILLISECONDS) ;
                    }
                    catch (final InterruptedException ie)
                    {
                        LOGGER.warn("Waiting delivery thread interupted while waiting on message pickup on InVM queue '" + serviceId + "'.  Exiting pickup wait state.") ;
                    }
                }
            }
            finally
            {
                lock.unlock() ;
            }
        }
       
        /**
         * Pickup an entry from the queue.
         *
         * N.B. Must not hold external lock while calling this method.
         *
         * @param millis The number of milliseconds to wait for a message.
         * @return The message or null if nothing present within the timeout.
         *
         * @throws InVMException for InVM transport specific errors.
         */
        public Object pickup(final long millis)
            throws InVMException
        {
            final long end = System.currentTimeMillis() + millis ;
            lock.lock() ;
            try
            {
                if (shutdown)
                {
                    throw new InVMException("InVM Transport already shutdown") ;
                }
                if (entries.isEmpty())
                {
                    final long delay = end - System.currentTimeMillis() ;
                    if (delay > 0)
                    {
                        numWaiters++ ;
                        try
                        {
                            waitingCondition.await(delay, TimeUnit.MILLISECONDS) ;
                        }
                        catch (final InterruptedException ioe)
                        {
                            throw new InVMException("Interrupted during wait") ;
                        }
                    }
                }
                final InVMQueueEntry entry = entries.poll() ;
                if (entry != null)
                {
                    final Object result = entry.getValue() ;
                    final Condition condition = entry.getCondition() ;
                    if (condition != null)
                    {
                        condition.signal() ;
                    }
                    return result ;
                }
                return null ;
            }
            finally
            {
                lock.unlock() ;
            }
        }
    }
}
TOP

Related Classes of org.jboss.internal.soa.esb.couriers.transport.InVMTransport$InVMEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
d', 'pageview');