/* * 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.tck.testmodels.mule; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.exception.MessagingExceptionHandler; import org.mule.runtime.core.api.exception.RollbackSourceCallback; import org.mule.runtime.core.api.exception.SystemExceptionHandler; import org.mule.runtime.core.exception.AbstractExceptionListener; import org.mule.runtime.core.exception.MessagingException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <code>TestExceptionStrategy</code> is used by the Mule test cases as a direct replacement of the * {@link org.mule.runtime.core.exception.AbstractMessagingExceptionStrategy}. This is used to test that overriding the default * Exception strategy works. */ public class TestExceptionStrategy extends AbstractExceptionListener implements MessagingExceptionHandler, SystemExceptionHandler { /** * logger used by this class */ protected final Logger logger = LoggerFactory.getLogger(getClass()); /** * This is the lock that protect both the storage of {@link #callback} and modifications of {@link #unhandled}. */ private Object callbackLock = new Object(); // @GuardedBy("callbackLock") private ExceptionCallback callback; // @GuardedBy("callbackLock") private List<Exception> unhandled = new LinkedList<Exception>(); private volatile String testProperty; public TestExceptionStrategy() {} public String getTestProperty() { return testProperty; } public void setTestProperty(String testProperty) { this.testProperty = testProperty; } public Event handleException(Exception exception, Event event, RollbackSourceCallback rollbackMethod) { ExceptionCallback callback = null; synchronized (callbackLock) { if (this.callback != null) { callback = this.callback; } else { unhandled.add(exception); } } // It is important that the call to the callback is done outside // synchronization since we don't control that code and // we could have liveness problems. logger.info("Handling exception: " + exception.getClass().getName()); if (callback != null) { logger.info("Exception caught on TestExceptionStrategy and was sent to callback.", exception); callback.onException(exception); } else { logger.info("Exception caught on TestExceptionStrategy but there was no callback set.", exception); } return event; } public Event handleException(MessagingException exception, Event event) { return handleException(exception, event, null); } public void handleException(Exception exception, RollbackSourceCallback rollbackMethod) { handleException(exception, null, rollbackMethod); } public void handleException(Exception exception) { handleException(exception, null, null); } public interface ExceptionCallback { void onException(Throwable t); } public void setExceptionCallback(ExceptionCallback exceptionCallback) { synchronized (callbackLock) { this.callback = exceptionCallback; } processUnhandled(); } protected void processUnhandled() { List<Exception> unhandledCopies = null; ExceptionCallback callback = null; synchronized (callbackLock) { if (this.callback != null) { callback = this.callback; unhandledCopies = new ArrayList<Exception>(unhandled); unhandled.clear(); } } // It is important that the call to the callback is done outside // synchronization since we don't control that code and // we could have liveness problems. if (callback != null && unhandledCopies != null) { for (Exception exception : unhandledCopies) { logger.info("Handling exception after setting the callback.", exception); callback.onException(exception); } } } }