001    package de.deepamehta.plugins.webservice.provider;
002    
003    import de.deepamehta.core.service.accesscontrol.AccessControlException;
004    import de.deepamehta.core.util.JavaUtils;
005    
006    import javax.servlet.http.HttpServletRequest;
007    
008    import javax.ws.rs.WebApplicationException;
009    import javax.ws.rs.core.Context;
010    import javax.ws.rs.core.Response;
011    import javax.ws.rs.core.Response.Status;
012    import javax.ws.rs.ext.ExceptionMapper;
013    import javax.ws.rs.ext.Provider;
014    
015    import java.util.logging.Level;
016    import java.util.logging.Logger;
017    
018    
019    
020    /**
021     * Maps all Throwables but WebApplicationExceptions to a 500 (Internal Server Error) response.
022     * A WebApplicationException's response is returned directly.
023     * <p>
024     * We don't want Jersey to re-throw anything to the HTTP container as this would result in logging
025     * the exception twice and possibly to interspersed illegible stack traces (see #484).
026     */
027    @Provider
028    public class CatchAllExceptionMapper implements ExceptionMapper<Throwable> {
029    
030        // ---------------------------------------------------------------------------------------------- Instance Variables
031    
032        @Context
033        HttpServletRequest request;
034    
035        private Logger logger = Logger.getLogger(getClass().getName());
036    
037        // -------------------------------------------------------------------------------------------------- Public Methods
038    
039        @Override
040        public Response toResponse(Throwable e) {
041            if (e instanceof WebApplicationException) {
042                return ((WebApplicationException) e).getResponse();
043            }
044            //
045            Status status;
046            if (hasNestedAccessControlException(e)) {
047                status = Status.UNAUTHORIZED;
048            } else {
049                status = Status.INTERNAL_SERVER_ERROR;
050            }
051            logger.log(Level.SEVERE, errorMessage(status), e);
052            return Response.status(status).build();
053        }
054    
055        // ------------------------------------------------------------------------------------------------- Private Methods
056    
057        private boolean hasNestedAccessControlException(Throwable e) {
058            while (e != null) {
059                if (e instanceof AccessControlException) {
060                    return true;
061                }
062                e = e.getCause();
063            }
064            return false;
065        }
066    
067        private String errorMessage(Status status) {
068            return "Request \"" + JavaUtils.requestInfo(request) + "\" failed. Generating " +
069                JavaUtils.responseInfo(status) + ". The original exception/error is:";
070        }
071    }