package org.jboss.resteasy.core;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.specimpl.BuiltResponse;
import org.jboss.resteasy.spi.ApplicationException;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.NoLogWebApplicationException;
import org.jboss.resteasy.spi.ReaderException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.UnhandledException;
import org.jboss.resteasy.spi.WriterException;
import org.jboss.resteasy.spi.InternalServerErrorException;
import org.jboss.resteasy.util.HttpResponseCodes;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.BadRequestException;
import java.util.HashSet;
import java.util.Set;
public class ExceptionHandler
{
protected ResteasyProviderFactory providerFactory;
protected Set<String> unwrappedExceptions = new HashSet<String>();
protected boolean mapperExecuted;
public ExceptionHandler(final ResteasyProviderFactory providerFactory, final Set<String> unwrappedExceptions)
{
this.providerFactory = providerFactory;
this.unwrappedExceptions = unwrappedExceptions;
}
public boolean isMapperExecuted()
{
return mapperExecuted;
}
@SuppressWarnings(value = "unchecked")
public Response executeExactExceptionMapper(Throwable exception)
{
ExceptionMapper mapper = providerFactory.getExceptionMappers().get(exception.getClass());
if (mapper == null) return null;
mapperExecuted = true;
return mapper.toResponse(exception);
}
@SuppressWarnings(value = "unchecked")
public Response executeExceptionMapperForClass(Throwable exception, Class clazz)
{
ExceptionMapper mapper = providerFactory.getExceptionMappers().get(clazz);
if (mapper == null) return null;
mapperExecuted = true;
return mapper.toResponse(exception);
}
protected Response handleApplicationException(HttpRequest request, ApplicationException e)
{
Response jaxrsResponse = null;
if ((jaxrsResponse = executeExceptionMapperForClass(e, ApplicationException.class)) != null) {
return jaxrsResponse;
}
jaxrsResponse = unwrapException(request, e);
if (jaxrsResponse == null) {
throw new UnhandledException(e.getCause());
}
return jaxrsResponse;
}
@SuppressWarnings(value = "unchecked")
public Response executeExceptionMapper(Throwable exception)
{
ExceptionMapper mapper = null;
Class causeClass = exception.getClass();
while (mapper == null) {
if (causeClass == null) break;
mapper = providerFactory.getExceptionMappers().get(causeClass);
if (mapper == null) causeClass = causeClass.getSuperclass();
}
if (mapper != null) {
mapperExecuted = true;
Response jaxrsResponse = mapper.toResponse(exception);
if (jaxrsResponse == null) {
jaxrsResponse = Response.status(204).build();
}
return jaxrsResponse;
}
return null;
}
protected Response unwrapException(HttpRequest request, Throwable e)
{
Response jaxrsResponse = null;
Throwable unwrappedException = e.getCause();
if (unwrappedException instanceof WebApplicationException) {
WebApplicationException wae = (WebApplicationException) unwrappedException;
Response response = wae.getResponse();
if (response != null) {
try {
if (response.getEntity() != null) return response;
} catch(IllegalStateException ise) {
return response;
}
}
}
if ((jaxrsResponse = executeExceptionMapper(unwrappedException)) != null) {
return jaxrsResponse;
}
if (unwrappedException instanceof WebApplicationException) {
return handleWebApplicationException((WebApplicationException) unwrappedException);
}
else if (unwrappedException instanceof Failure) {
return handleFailure(request, (Failure) unwrappedException);
}
else {
if (unwrappedExceptions.contains(unwrappedException.getClass().getName()) && unwrappedException.getCause() != null) {
return unwrapException(request, unwrappedException);
}
else {
return null;
}
}
}
protected Response handleFailure(HttpRequest request, Failure failure)
{
if (failure.isLoggable())
LogMessages.LOGGER.failedExecutingError(request.getHttpMethod(), request.getUri().getPath(), failure);
else LogMessages.LOGGER.failedExecutingDebug(request.getHttpMethod(), request.getUri().getPath(), failure);
if (failure.getResponse() != null) {
return failure.getResponse();
}
else {
Response.ResponseBuilder builder = Response.status(failure.getErrorCode());
if (failure.getMessage() != null) builder.type(MediaType.TEXT_HTML).entity(failure.getMessage());
return builder.build();
}
}
protected Response handleClientErrorException(Response response, final String message,
final int errorCode, final Throwable cause) {
if (response != null)
{
BuiltResponse bResponse = (BuiltResponse)response;
if (bResponse.getStatus() == HttpResponseCodes.SC_BAD_REQUEST
|| bResponse.getStatus() == HttpResponseCodes.SC_NOT_FOUND)
{
if (message != null)
{
Response.ResponseBuilder builder = bResponse.fromResponse(response);
builder.type(MediaType.TEXT_HTML).entity(message);
return builder.build();
}
}
return response;
} else {
Response.ResponseBuilder builder = Response.status(errorCode);
if (cause == null) {
if (message != null)
{
builder.type(MediaType.TEXT_HTML).entity(message);
}
} else {
if (cause instanceof BadRequestException) {
builder.status(HttpResponseCodes.SC_BAD_REQUEST);
} else if (cause instanceof NotFoundException) {
builder.status(HttpResponseCodes.SC_NOT_FOUND);
}
if (cause.getMessage() != null)
{
builder.type(MediaType.TEXT_HTML).entity(cause.getMessage());
}
}
Response resp = builder.build();
return resp;
}
}
protected Response handleWriterException(HttpRequest request, WriterException e)
{
Response jaxrsResponse = null;
if ((jaxrsResponse = executeExceptionMapperForClass(e, WriterException.class)) != null) {
return jaxrsResponse;
}
if (e.getResponse() != null || e.getErrorCode() > -1) {
return handleFailure(request, e);
}
else if (e.getCause() != null) {
if ((jaxrsResponse = unwrapException(request, e)) != null) return jaxrsResponse;
}
e.setErrorCode(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR);
return handleFailure(request, e);
}
protected Response handleReaderException(HttpRequest request, ReaderException e)
{
Response jaxrsResponse = null;
if ((jaxrsResponse = executeExceptionMapperForClass(e, ReaderException.class)) != null) {
return jaxrsResponse;
}
if (e.getResponse() != null || e.getErrorCode() > -1) {
return handleFailure(request, e);
}
else if (e.getCause() != null) {
if ((jaxrsResponse = unwrapException(request, e)) != null) return jaxrsResponse;
}
e.setErrorCode(HttpResponseCodes.SC_BAD_REQUEST);
return handleFailure(request, e);
}
protected Response handleWebApplicationException(WebApplicationException wae)
{
if (wae instanceof NotFoundException)
{
LogMessages.LOGGER.failedToExecuteDebug(wae);
}
else if (!(wae instanceof NoLogWebApplicationException))
{
LogMessages.LOGGER.failedToExecute(wae);
}
return wae.getResponse();
}
public Response handleException(HttpRequest request, Throwable e)
{
Response jaxrsResponse = null;
jaxrsResponse = executeExactExceptionMapper(e);
if (jaxrsResponse == null)
{
if (e instanceof InternalServerErrorException
|| e instanceof ClientErrorException)
{
jaxrsResponse = executeExceptionMapper(e);
if (jaxrsResponse == null)
{
LogMessages.LOGGER.failedExecutingDebug(request.getHttpMethod(),
request.getUri().getPath(), e);
if (e instanceof InternalServerErrorException){
jaxrsResponse = handleClientErrorException(
((InternalServerErrorException)e).getResponse(), e.getMessage(),
((InternalServerErrorException)e).getErrorCode(), e.getCause());
} else {
jaxrsResponse = handleClientErrorException(
((ClientErrorException)e).getResponse(), e.getMessage(),
((ClientErrorException)e).getResponse().getStatus(), e.getCause());
}
}
} else if (e instanceof WebApplicationException)
{
WebApplicationException wae = (WebApplicationException) e;
if (wae.getResponse() != null && wae.getResponse().getEntity() != null)
{
jaxrsResponse = wae.getResponse();
} else
{
jaxrsResponse = executeExceptionMapper(e);
if (jaxrsResponse == null)
{
jaxrsResponse = handleWebApplicationException((WebApplicationException) e);
}
}
} else if (e instanceof Failure)
{
if (e instanceof WriterException)
{
jaxrsResponse = handleWriterException(request, (WriterException) e);
} else if (e instanceof ReaderException)
{
jaxrsResponse = handleReaderException(request, (ReaderException) e);
} else
{
jaxrsResponse = executeExceptionMapper(e);
if (jaxrsResponse == null)
{
jaxrsResponse = handleFailure(request, (Failure) e);
}
}
} else
{
if (e instanceof ApplicationException)
{
jaxrsResponse = handleApplicationException(request, (ApplicationException) e);
} else
{
jaxrsResponse = executeExceptionMapper(e);
}
}
}
if (jaxrsResponse == null)
{
throw new UnhandledException(e);
}
return jaxrsResponse;
}
}