1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.yarn.webapp;
19 
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 
23 import javax.servlet.http.HttpServletResponse;
24 import javax.ws.rs.WebApplicationException;
25 import javax.ws.rs.core.Context;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.ext.ExceptionMapper;
28 import javax.ws.rs.ext.Provider;
29 import javax.xml.bind.UnmarshalException;
30 
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.classification.InterfaceAudience;
34 import org.apache.hadoop.ipc.RemoteException;
35 import org.apache.hadoop.security.authorize.AuthorizationException;
36 
37 import com.google.inject.Singleton;
38 
39 /**
40  * Handle webservices jersey exceptions and create json or xml response
41  * with the ExceptionData.
42  */
43 @InterfaceAudience.LimitedPrivate({"YARN", "MapReduce"})
44 @Singleton
45 @Provider
46 public class GenericExceptionHandler implements ExceptionMapper<Exception> {
47   public static final Log LOG = LogFactory
48       .getLog(GenericExceptionHandler.class);
49 
50   private @Context
51   HttpServletResponse response;
52 
53   @Override
toResponse(Exception e)54   public Response toResponse(Exception e) {
55     if (LOG.isTraceEnabled()) {
56       LOG.trace("GOT EXCEPITION", e);
57     }
58     // Don't catch this as filter forward on 404
59     // (ServletContainer.FEATURE_FILTER_FORWARD_ON_404)
60     // won't work and the web UI won't work!
61     if (e instanceof com.sun.jersey.api.NotFoundException) {
62       return ((com.sun.jersey.api.NotFoundException) e).getResponse();
63     }
64     // clear content type
65     response.setContentType(null);
66 
67     // Convert exception
68     if (e instanceof RemoteException) {
69       e = ((RemoteException) e).unwrapRemoteException();
70     }
71 
72     // Map response status
73     final Response.Status s;
74     if (e instanceof SecurityException) {
75       s = Response.Status.UNAUTHORIZED;
76     } else if (e instanceof AuthorizationException) {
77       s = Response.Status.UNAUTHORIZED;
78     } else if (e instanceof FileNotFoundException) {
79       s = Response.Status.NOT_FOUND;
80     } else if (e instanceof NotFoundException) {
81       s = Response.Status.NOT_FOUND;
82     } else if (e instanceof IOException) {
83       s = Response.Status.NOT_FOUND;
84     } else if (e instanceof ForbiddenException) {
85       s = Response.Status.FORBIDDEN;
86     } else if (e instanceof UnsupportedOperationException) {
87       s = Response.Status.BAD_REQUEST;
88     } else if (e instanceof IllegalArgumentException) {
89       s = Response.Status.BAD_REQUEST;
90     } else if (e instanceof NumberFormatException) {
91       s = Response.Status.BAD_REQUEST;
92     } else if (e instanceof BadRequestException) {
93       s = Response.Status.BAD_REQUEST;
94     } else if (e instanceof WebApplicationException
95         && e.getCause() instanceof UnmarshalException) {
96       s = Response.Status.BAD_REQUEST;
97     } else {
98       LOG.warn("INTERNAL_SERVER_ERROR", e);
99       s = Response.Status.INTERNAL_SERVER_ERROR;
100     }
101 
102     // let jaxb handle marshalling data out in the same format requested
103     RemoteExceptionData exception = new RemoteExceptionData(e.getClass().getSimpleName(),
104        e.getMessage(), e.getClass().getName());
105 
106     return Response.status(s).entity(exception)
107         .build();
108   }
109 }
110