hadoop HttpExceptionUtils 源码

  • 2022-10-20
  • 浏览 (242)

haddop HttpExceptionUtils 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/HttpExceptionUtils.java

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.util;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.net.HttpURLConnection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * HTTP utility class to help propagate server side exception to the client
 * over HTTP as a JSON payload.
 * <p>
 * It creates HTTP Servlet and JAX-RPC error responses including details of the
 * exception that allows a client to recreate the remote exception.
 * <p>
 * It parses HTTP client connections and recreates the exception.
 */
@InterfaceAudience.Private
@InterfaceStability.Unstable
public class HttpExceptionUtils {

  public static final String ERROR_JSON = "RemoteException";
  public static final String ERROR_EXCEPTION_JSON = "exception";
  public static final String ERROR_CLASSNAME_JSON = "javaClassName";
  public static final String ERROR_MESSAGE_JSON = "message";

  private static final String APPLICATION_JSON_MIME = "application/json";

  private static final String ENTER = System.getProperty("line.separator");

  /**
   * Creates a HTTP servlet response serializing the exception in it as JSON.
   *
   * @param response the servlet response
   * @param status the error code to set in the response
   * @param ex the exception to serialize in the response
   * @throws IOException thrown if there was an error while creating the
   * response
   */
  public static void createServletExceptionResponse(
      HttpServletResponse response, int status, Throwable ex)
      throws IOException {
    response.setStatus(status);
    response.setContentType(APPLICATION_JSON_MIME);
    Map<String, Object> json = new LinkedHashMap<String, Object>();
    json.put(ERROR_MESSAGE_JSON, getOneLineMessage(ex));
    json.put(ERROR_EXCEPTION_JSON, ex.getClass().getSimpleName());
    json.put(ERROR_CLASSNAME_JSON, ex.getClass().getName());
    Map<String, Object> jsonResponse =
        Collections.singletonMap(ERROR_JSON, json);
    Writer writer = response.getWriter();
    JsonSerialization.writer().writeValue(writer, jsonResponse);
    writer.flush();
  }

  /**
   * Creates a HTTP JAX-RPC response serializing the exception in it as JSON.
   *
   * @param status the error code to set in the response
   * @param ex the exception to serialize in the response
   * @return the JAX-RPC response with the set error and JSON encoded exception
   */
  public static Response createJerseyExceptionResponse(Response.Status status,
      Throwable ex) {
    Map<String, Object> json = new LinkedHashMap<String, Object>();
    json.put(ERROR_MESSAGE_JSON, getOneLineMessage(ex));
    json.put(ERROR_EXCEPTION_JSON, ex.getClass().getSimpleName());
    json.put(ERROR_CLASSNAME_JSON, ex.getClass().getName());
    Map<String, Object> response = Collections.singletonMap(ERROR_JSON, json);
    return Response.status(status).type(MediaType.APPLICATION_JSON).
        entity(response).build();
  }

  private static String getOneLineMessage(Throwable exception) {
    String message = exception.getMessage();
    if (message != null) {
      int i = message.indexOf(ENTER);
      if (i > -1) {
        message = message.substring(0, i);
      }
    }
    return message;
  }

  // trick, riding on generics to throw an undeclared exception

  private static void throwEx(Throwable ex) {
    HttpExceptionUtils.<RuntimeException>throwException(ex);
  }

  @SuppressWarnings("unchecked")
  private static <E extends Throwable> void throwException(Throwable ex)
      throws E {
    throw (E) ex;
  }

  /**
   * Validates the status of an <code>HttpURLConnection</code> against an
   * expected HTTP status code. If the current status code is not the expected
   * one it throws an exception with a detail message using Server side error
   * messages if available.
   * <p>
   * <b>NOTE:</b> this method will throw the deserialized exception even if not
   * declared in the <code>throws</code> of the method signature.
   *
   * @param conn the <code>HttpURLConnection</code>.
   * @param expectedStatus the expected HTTP status code.
   * @throws IOException thrown if the current status code does not match the
   * expected one.
   */
  @SuppressWarnings("unchecked")
  public static void validateResponse(HttpURLConnection conn,
      int expectedStatus) throws IOException {
    if (conn.getResponseCode() != expectedStatus) {
      Exception toThrow;
      InputStream es = null;
      try {
        es = conn.getErrorStream();
        Map json = JsonSerialization.mapReader().readValue(es);
        json = (Map) json.get(ERROR_JSON);
        String exClass = (String) json.get(ERROR_CLASSNAME_JSON);
        String exMsg = (String) json.get(ERROR_MESSAGE_JSON);
        if (exClass != null) {
          try {
            ClassLoader cl = HttpExceptionUtils.class.getClassLoader();
            Class klass = cl.loadClass(exClass);
            Constructor constr = klass.getConstructor(String.class);
            toThrow = (Exception) constr.newInstance(exMsg);
          } catch (Exception ex) {
            toThrow = new IOException(String.format(
                "HTTP status [%d], exception [%s], message [%s], URL [%s]",
                conn.getResponseCode(), exClass, exMsg, conn.getURL()));
          }
        } else {
          String msg = (exMsg != null) ? exMsg : conn.getResponseMessage();
          toThrow = new IOException(String.format(
              "HTTP status [%d], message [%s], URL [%s]",
              conn.getResponseCode(), msg, conn.getURL()));
        }
      } catch (Exception ex) {
        toThrow = new IOException(String.format(
            "HTTP status [%d], message [%s], URL [%s], exception [%s]",
            conn.getResponseCode(), conn.getResponseMessage(), conn.getURL(),
            ex.toString()), ex);
      } finally {
        if (es != null) {
          try {
            es.close();
          } catch (IOException ex) {
            //ignore
          }
        }
      }
      throwEx(toThrow);
    }
  }

}

相关信息

hadoop 源码目录

相关文章

hadoop ApplicationClassLoader 源码

hadoop AsyncDiskService 源码

hadoop AutoCloseableLock 源码

hadoop BasicDiskValidator 源码

hadoop BlockingThreadPoolExecutorService 源码

hadoop CacheableIPList 源码

hadoop ChunkedArrayList 源码

hadoop ClassUtil 源码

hadoop Classpath 源码

hadoop CleanerUtil 源码

0  赞