/** * Copyright 2014 Confluent Inc. * * Licensed 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 io.confluent.rest.exceptions; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import io.confluent.rest.RestConfig; import io.confluent.rest.entities.ErrorMessage; /** * Abstract exception mapper that checks the debug flag and generates an error message including the * stack trace if it is enabled. */ @Provider public abstract class DebuggableExceptionMapper<E extends Throwable> implements ExceptionMapper<E> { RestConfig restConfig; @Context HttpHeaders headers; public DebuggableExceptionMapper(RestConfig restConfig) { this.restConfig = restConfig; } /** * Create a Response object using the given exception, status, and message. When debugging is * enabled, the message will be replaced with the exception class, exception message, and * stacktrace. * * @param exc Throwable that triggered this ExceptionMapper * @param status HTTP response status */ public Response.ResponseBuilder createResponse(Throwable exc, int errorCode, Response.Status status, String msg) { String readableMessage = msg; if (restConfig != null && restConfig.getBoolean(RestConfig.DEBUG_CONFIG)) { readableMessage += " " + exc.getClass().getName() + ": " + exc.getMessage(); try { ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream stream = new PrintStream(os, false, StandardCharsets.UTF_8.name()); exc.printStackTrace(stream); stream.close(); os.close(); readableMessage += System.lineSeparator() + os.toString(StandardCharsets.UTF_8.name()); } catch (IOException e) { // Ignore } } final ErrorMessage message = new ErrorMessage(errorCode, readableMessage); return Response.status(status) .entity(message); } }