/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util.queue; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.api.exception.MuleException; import org.mule.runtime.api.store.ObjectStoreException; import org.mule.runtime.core.util.store.DeserializationPostInitialisable; import java.io.Serializable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Queue implementation that executes operations: - If there is no transaction context then executes the operation directly to the * queue. - If there is a transaction context then executes the operation through the transaction context. - During queue dispose * a {@link QueueStoreCacheListener} will be notified */ public class TransactionAwareQueueStore implements Queue { protected transient Logger logger = LoggerFactory.getLogger(getClass()); private final MuleContext muleContext; private final TransactionContextProvider transactionContextProvider; private final QueueStore queue; public TransactionAwareQueueStore(QueueStore queue, TransactionContextProvider transactionContextProvider, MuleContext muleContext) { this.queue = queue; this.transactionContextProvider = transactionContextProvider; this.muleContext = muleContext; } @Override public void put(Serializable item) throws InterruptedException, ObjectStoreException { offer(item, Long.MAX_VALUE); } @Override public void clear() throws InterruptedException { if (transactionContextProvider.isTransactional()) { transactionContextProvider.getTransactionalContext().clear(queue); } else { queue.clear(); } } @Override public boolean offer(Serializable item, long timeout) throws InterruptedException, ObjectStoreException { if (transactionContextProvider.isTransactional()) { return transactionContextProvider.getTransactionalContext().offer(queue, item, timeout); } else { return queue.offer(item, 0, timeout); } } @Override public Serializable take() throws InterruptedException { return poll(Long.MAX_VALUE); } @Override public void untake(Serializable item) throws InterruptedException, ObjectStoreException { if (transactionContextProvider.isTransactional()) { transactionContextProvider.getTransactionalContext().untake(queue, item); } else { queue.untake(item); } } @Override public Serializable poll(long timeout) throws InterruptedException { try { if (transactionContextProvider.isTransactional()) { Serializable item = transactionContextProvider.getTransactionalContext().poll(queue, timeout); return postProcessIfNeeded(item); } else { return postProcessIfNeeded(queue.poll(timeout)); } } catch (InterruptedException iex) { if (!muleContext.isStopping()) { throw iex; } // if stopping, ignore return null; } } @Override public Serializable peek() throws InterruptedException { if (transactionContextProvider.isTransactional()) { Serializable item = transactionContextProvider.getTransactionalContext().peek(queue); return postProcessIfNeeded(item); } else { return postProcessIfNeeded(queue.peek()); } } @Override public void dispose() throws MuleException, InterruptedException { queue.dispose(); } @Override public int size() { if (transactionContextProvider.isTransactional()) { return transactionContextProvider.getTransactionalContext().size(queue); } else { return queue.getSize(); } } @Override public String getName() { return queue.getName(); } /** * Note -- this must handle null items */ private Serializable postProcessIfNeeded(Serializable item) { try { if (item instanceof DeserializationPostInitialisable) { DeserializationPostInitialisable.Implementation.init(item, muleContext); } return item; } catch (Exception e) { logger.warn("Unable to deserialize message", e); return null; } } }