001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.fs.http.server;
020
021import org.apache.hadoop.lib.service.FileSystemAccessException;
022import org.apache.hadoop.lib.wsrs.ExceptionProvider;
023import org.slf4j.Logger;
024import org.slf4j.LoggerFactory;
025import org.slf4j.MDC;
026
027import javax.ws.rs.core.Response;
028import javax.ws.rs.ext.Provider;
029import java.io.FileNotFoundException;
030import java.io.IOException;
031
032/**
033 * JAX-RS <code>ExceptionMapper</code> implementation that maps HttpFSServer's
034 * exceptions to HTTP status codes.
035 */
036@Provider
037public class HttpFSExceptionProvider extends ExceptionProvider {
038  private static Logger AUDIT_LOG = LoggerFactory.getLogger("httpfsaudit");
039  private static Logger LOG = LoggerFactory.getLogger(HttpFSExceptionProvider.class);
040
041  /**
042   * Maps different exceptions thrown by HttpFSServer to HTTP status codes.
043   * <p/>
044   * <ul>
045   * <li>SecurityException : HTTP UNAUTHORIZED</li>
046   * <li>FileNotFoundException : HTTP NOT_FOUND</li>
047   * <li>IOException : INTERNAL_HTTP SERVER_ERROR</li>
048   * <li>UnsupporteOperationException : HTTP BAD_REQUEST</li>
049   * <li>all other exceptions : HTTP INTERNAL_SERVER_ERROR </li>
050   * </ul>
051   *
052   * @param throwable exception thrown.
053   *
054   * @return mapped HTTP status code
055   */
056  @Override
057  public Response toResponse(Throwable throwable) {
058    Response.Status status;
059    if (throwable instanceof FileSystemAccessException) {
060      throwable = throwable.getCause();
061    }
062    if (throwable instanceof SecurityException) {
063      status = Response.Status.UNAUTHORIZED;
064    } else if (throwable instanceof FileNotFoundException) {
065      status = Response.Status.NOT_FOUND;
066    } else if (throwable instanceof IOException) {
067      status = Response.Status.INTERNAL_SERVER_ERROR;
068    } else if (throwable instanceof UnsupportedOperationException) {
069      status = Response.Status.BAD_REQUEST;
070    } else {
071      status = Response.Status.INTERNAL_SERVER_ERROR;
072    }
073    return createResponse(status, throwable);
074  }
075
076  /**
077   * Logs the HTTP status code and exception in HttpFSServer's log.
078   *
079   * @param status HTTP status code.
080   * @param throwable exception thrown.
081   */
082  @Override
083  protected void log(Response.Status status, Throwable throwable) {
084    String method = MDC.get("method");
085    String path = MDC.get("path");
086    String message = getOneLineMessage(throwable);
087    AUDIT_LOG.warn("FAILED [{}:{}] response [{}] {}", new Object[]{method, path, status, message});
088    LOG.warn("[{}:{}] response [{}] {}", new Object[]{method, path, status, message, throwable});
089  }
090
091}