package org.marketcetera.util.except;
import java.io.InterruptedIOException;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.FileLockInterruptionException;
import javax.naming.InterruptedNamingException;
import org.apache.commons.lang.ObjectUtils;
import org.marketcetera.util.log.I18NBoundMessage;
import org.marketcetera.util.misc.ClassVersion;
/**
* General-purpose utilities.
*
* @author tlerios@marketcetera.com
* @since 0.5.0
* @version $Id: ExceptUtils.java 16154 2012-07-14 16:34:05Z colin $
*/
/* $License$ */
@ClassVersion("$Id: ExceptUtils.java 16154 2012-07-14 16:34:05Z colin $")
public final class ExceptUtils
{
// CLASS METHODS.
/**
* Checks whether the calling thread has been interrupted, and, if
* so, throws an {@link InterruptedException} with the default
* interruption message and no underlying cause. The interrupted
* status of the thread is cleared.
*
* @throws InterruptedException Thrown if the calling thread
* was interrupted.
*/
public static void checkInterruption()
throws InterruptedException
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException
(Messages.THREAD_INTERRUPTED.getText());
}
}
/**
* Checks whether the calling thread has been interrupted, and, if
* so, throws an {@link InterruptedException} with the given
* interruption message, but without an underlying cause. The
* interrupted status of the thread is cleared.
*
* @param message The message.
*
* @throws InterruptedException Thrown if the calling thread
* was interrupted.
*/
public static void checkInterruption
(String message)
throws InterruptedException
{
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException(message);
}
}
/**
* Checks whether the calling thread has been interrupted, and, if
* so, throws an {@link InterruptedException} with the default
* interruption message and the given underlying cause. The given
* underlying cause is set on the thrown exception. The
* interrupted status of the thread is cleared.
*
* @param cause The cause.
*
* @throws InterruptedException Thrown if the calling thread
* was interrupted.
*/
public static void checkInterruption
(Throwable cause)
throws InterruptedException
{
if (Thread.currentThread().isInterrupted()) {
InterruptedException ex=new InterruptedException
(Messages.THREAD_INTERRUPTED.getText());
ex.initCause(cause);
throw ex;
}
}
/**
* Checks whether the calling thread has been interrupted, and, if
* so, throws an {@link InterruptedException} with the given
* interruption message and the given underlying cause. The given
* underlying cause is set on the thrown exception. The
* interrupted status of the thread is cleared.
*
* @param cause The cause.
* @param message The message.
*
* @throws InterruptedException Thrown if the calling thread
* was interrupted.
*/
public static void checkInterruption
(Throwable cause,
String message)
throws InterruptedException
{
if (Thread.currentThread().isInterrupted()) {
InterruptedException ex=new InterruptedException(message);
ex.initCause(cause);
throw ex;
}
}
/**
* Checks if the given throwable is an instance of {@link
* InterruptedException}, {@link InterruptedIOException}, {@link
* I18NInterruptedException}, or {@link
* I18NInterruptedRuntimeException}.
*
* @param throwable The throwable.
*
* @return True if so.
*/
public static boolean isInterruptException
(Throwable throwable)
{
return ((throwable instanceof InterruptedException) ||
(throwable instanceof InterruptedIOException) ||
(throwable instanceof ClosedByInterruptException) ||
(throwable instanceof FileLockInterruptionException) ||
(throwable instanceof InterruptedNamingException) ||
(throwable instanceof I18NInterruptedException) ||
(throwable instanceof I18NInterruptedRuntimeException));
}
/**
* If the given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the calling thread is
* interrupted. Otherwise, this is a no-op.
*
* @param throwable The throwable.
*
* @return True if the calling thread was interrupted.
*/
public static boolean interrupt
(Throwable throwable)
{
if (isInterruptException(throwable)) {
Thread.currentThread().interrupt();
return true;
}
return false;
}
/**
* Swallows the given throwable. It logs the given parameterized
* message and throwable under the given logging category at the
* warning level. Also, if the given throwable is an interruption
* exception per {@link #isInterruptException(Throwable)}, then
* the calling thread is interrupted.
*
* @param throwable The throwable.
* @param category The category.
* @param message The message.
*
* @return True if the calling thread was interrupted.
*/
public static boolean swallow
(Throwable throwable,
Object category,
I18NBoundMessage message)
{
message.warn(category,throwable);
return interrupt(throwable);
}
/**
* Swallows the given throwable. It logs a default message
* alongside the throwable at the warning level. Also, if the
* given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the calling thread is
* interrupted.
*
* @param throwable The throwable.
*
* @return True if the calling thread was interrupted.
*/
public static boolean swallow
(Throwable throwable)
{
return swallow(throwable,ExceptUtils.class,Messages.THROWABLE_IGNORED);
}
/**
* If the given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the throwable is
* wrapped inside a {@link I18NInterruptedException}, and this
* exception is returned; also, the calling thread is
* interrupted. Otherwise, an {@link I18NException} is used to
* wrap the throwable, and returned. All arguments are passed
* as-is into the constructor of the wrapping exception.
*
* @param throwable The throwable.
* @param message The message.
*
* @return The wrapping exception.
*/
public static I18NException wrap
(Throwable throwable,
I18NBoundMessage message)
{
if (isInterruptException(throwable)) {
Thread.currentThread().interrupt();
return new I18NInterruptedException(throwable,message);
}
return new I18NException(throwable,message);
}
/**
* If the given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the throwable is
* wrapped inside a {@link I18NInterruptedException}, and this
* exception is returned; also, the calling thread is
* interrupted. Otherwise, an {@link I18NException} is used to
* wrap the throwable, and returned. All arguments are passed
* as-is into the constructor of the wrapping exception.
*
* @param throwable The throwable.
*
* @return The wrapping exception.
*/
public static I18NException wrap
(Throwable throwable)
{
if (isInterruptException(throwable)) {
Thread.currentThread().interrupt();
return new I18NInterruptedException(throwable);
}
return new I18NException(throwable);
}
/**
* If the given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the throwable is
* wrapped inside a {@link I18NInterruptedRuntimeException}, and
* this exception is thrown; also, the calling thread is
* interrupted. Otherwise, an {@link I18NRuntimeException} is used
* to wrap the throwable. All arguments are passed as-is into the
* constructor of the wrapping exception.
*
* @param throwable The throwable.
* @param message The message.
*
* @return The wrapping exception.
*/
public static I18NRuntimeException wrapRuntime
(Throwable throwable,
I18NBoundMessage message)
{
if (isInterruptException(throwable)) {
Thread.currentThread().interrupt();
return new I18NInterruptedRuntimeException(throwable,message);
}
return new I18NRuntimeException(throwable,message);
}
/**
* If the given throwable is an interruption exception per {@link
* #isInterruptException(Throwable)}, then the throwable is
* wrapped inside a {@link I18NInterruptedRuntimeException}, and
* this exception is thrown; also, the calling thread is
* interrupted. Otherwise, an {@link I18NRuntimeException} is used
* to wrap the throwable. All arguments are passed as-is into the
* constructor of the wrapping exception.
*
* @param throwable The throwable.
*
* @return The wrapping exception.
*/
public static I18NRuntimeException wrapRuntime
(Throwable throwable)
{
if (isInterruptException(throwable)) {
Thread.currentThread().interrupt();
return new I18NInterruptedRuntimeException(throwable);
}
return new I18NRuntimeException(throwable);
}
/**
* Returns the hash code of the given throwable. The result
* matches the equality definition of {@link
* #areEqual(Throwable,Object)}.
*
* @param t The throwable.
*
* @return The hash code.
*/
public static int getHashCode
(Throwable t)
{
if (t==null) {
return 0;
}
int code=ObjectUtils.hashCode(t.getClass());
if (t instanceof I18NThrowable) {
code+=ObjectUtils.hashCode
(((I18NThrowable)t).getI18NBoundMessage());
} else {
code+=ObjectUtils.hashCode(t.getMessage());
}
code+=getHashCode(t.getCause());
return code;
}
/**
* Checks whether the given throwable is equal to the given
* object. Equality requires identical classes, equal messages,
* and equal causes.
*
* @param t The throwable. It may be null.
* @param o The object. It may be null.
*
* @return True if so.
*/
public static boolean areEqual
(Throwable t,
Object o)
{
if (t==o) {
return true;
}
if ((o==null) || (t==null) || !t.getClass().equals(o.getClass())) {
return false;
}
Throwable to=(Throwable)o;
if (o instanceof I18NThrowable) {
if (!ObjectUtils.equals
(((I18NThrowable)t).getI18NBoundMessage(),
((I18NThrowable)o).getI18NBoundMessage())) {
return false;
}
} else {
if (!ObjectUtils.equals(t.getMessage(),to.getMessage())) {
return false;
}
}
return areEqual(t.getCause(),to.getCause());
}
// CONSTRUCTORS.
/**
* Constructor. It is private so that no instances can be created.
*/
private ExceptUtils() {}
}