001package co.codewizards.cloudstore.ls.rest.server;
002
003import java.util.Arrays;
004import java.util.LinkedHashSet;
005import java.util.Set;
006
007import javax.ws.rs.WebApplicationException;
008import javax.ws.rs.core.Context;
009import javax.ws.rs.core.HttpHeaders;
010import javax.ws.rs.core.MediaType;
011import javax.ws.rs.core.Response;
012import javax.ws.rs.ext.ExceptionMapper;
013import javax.ws.rs.ext.Provider;
014
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017
018import co.codewizards.cloudstore.core.concurrent.DeferredCompletionException;
019import co.codewizards.cloudstore.core.dto.Error;
020
021/**
022 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co
023 * @author Chairat Kongarayawetchakun - ckongarayawetchakun at nightlabs dot de
024 */
025@Provider
026public class DefaultExceptionMapper implements ExceptionMapper<Throwable>
027{
028        private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionMapper.class);
029
030        /**
031         * The media-types supported for serialising an {@link Error}.
032         */
033        private static final Set<MediaType> RESPONSE_MEDIA_TYPES = new LinkedHashSet<>(Arrays.asList(
034                        MediaType.APPLICATION_XML_TYPE,
035                        MediaType.APPLICATION_JSON_TYPE
036        ));
037
038        @Context
039        private HttpHeaders headers;
040
041        public DefaultExceptionMapper(@Context final LocalServerRest localServerRest) {
042                logger.debug("<init>: Instance created. localServerRest={}", localServerRest);
043
044                if (localServerRest == null)
045                        throw new IllegalArgumentException("localServerRest == null");
046
047        }
048
049        @Override
050        public Response toResponse(final Throwable throwable)
051        {
052                // We need to log the exception here, because it otherwise doesn't occur in any log
053                // in a vanilla tomcat 7.0.25. Marco :-)
054                if (throwable instanceof DeferredCompletionException) // normal part of protocol => only debug
055                        logger.debug(String.valueOf(throwable), throwable);
056                else
057                        logger.error(String.valueOf(throwable),throwable);
058
059                if (throwable instanceof WebApplicationException) {
060                        return ((WebApplicationException)throwable).getResponse();
061                }
062
063                final Error error = new Error(throwable);
064                return Response
065                                .status(Response.Status.INTERNAL_SERVER_ERROR)
066                                .type(getResponseMediaType())
067                                .entity(error)
068                                .build();
069        }
070
071        private MediaType getResponseMediaType() {
072                for (MediaType mediaType : headers.getAcceptableMediaTypes()) {
073                        if (RESPONSE_MEDIA_TYPES.contains(mediaType))
074                                return mediaType;
075                }
076                return MediaType.APPLICATION_XML_TYPE;
077        }
078}