001package co.codewizards.cloudstore.rest.server;
002
003import static java.util.Objects.*;
004
005import javax.ws.rs.WebApplicationException;
006import javax.ws.rs.core.Context;
007import javax.ws.rs.core.MediaType;
008import javax.ws.rs.core.Response;
009import javax.ws.rs.ext.ExceptionMapper;
010import javax.ws.rs.ext.Provider;
011
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015import co.codewizards.cloudstore.core.dto.Error;
016import co.codewizards.cloudstore.core.exception.ApplicationException;
017
018/**
019 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co
020 * @author Chairat Kongarayawetchakun - ckongarayawetchakun at nightlabs dot de
021 */
022@Provider
023public class DefaultExceptionMapper implements ExceptionMapper<Throwable>
024{
025        private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionMapper.class);
026
027        public DefaultExceptionMapper(@Context final CloudStoreRest cloudStoreRest) {
028                logger.debug("<init>: Instance created. cloudStoreRest={}", cloudStoreRest);
029
030                if (cloudStoreRest == null)
031                        throw new IllegalArgumentException("cloudStoreRest == null");
032
033        }
034
035        @Override
036        public Response toResponse(final Throwable throwable)
037        {
038                // We need to log the exception here, because it otherwise doesn't occur in any log
039                // in a vanilla tomcat 7.0.25. Marco :-)
040                Throwable applicationException = getApplicationException(throwable);
041                if (applicationException != null) { // normal part of protocol => only debug
042                        if (logger.isDebugEnabled())
043                                logger.debug(String.valueOf(throwable), throwable);
044                        else
045                                logger.info("toResponse: {} wrapped in {}. Enable debug-logging, if you need the stack-trace.", applicationException.getClass().getName(), throwable.getClass().getName());
046                }
047                else
048                        logger.error(String.valueOf(throwable),throwable);
049
050                if (throwable instanceof WebApplicationException) {
051                        return ((WebApplicationException)throwable).getResponse();
052                }
053
054                final Error error = new Error(throwable);
055                return Response
056                                .status(Response.Status.INTERNAL_SERVER_ERROR)
057                                .type(MediaType.APPLICATION_XML)
058                                .entity(error)
059                                .build();
060        }
061
062        private Throwable getApplicationException(final Throwable exception) {
063                requireNonNull(exception, "exception");
064
065                Throwable x = exception;
066                while (x != null) {
067                        final ApplicationException appEx = x.getClass().getAnnotation(ApplicationException.class);
068                        if (appEx != null)
069                                return x;
070
071                        x = x.getCause();
072                }
073                return null;
074        }
075}