package io.github.ibuildthecloud.gdapi.request.handler;
import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException;
import io.github.ibuildthecloud.gdapi.model.ApiError;
import io.github.ibuildthecloud.gdapi.model.impl.ErrorImpl;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.util.ExceptionUtils;
import io.github.ibuildthecloud.gdapi.util.ResponseCodes;
import java.io.IOException;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import javax.servlet.ServletException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExceptionHandler implements ApiRequestHandler {
private static final Logger log = LoggerFactory.getLogger(ExceptionHandler.class);
Properties standardErrorCodes;
String messageLocation;
String messageLocationOverride;
boolean throwUnknownErrors = false;
@Override
public void handle(ApiRequest request) throws IOException {
}
@Override
public boolean handleException(ApiRequest apiRequest, Throwable t) throws IOException, ServletException {
ApiError error = getError(apiRequest, t);
if (error != null) {
apiRequest.setResponseCode(error.getStatus());
apiRequest.setResponseObject(error);
return true;
}
return false;
}
protected ApiError getError(ApiRequest apiRequest, Throwable t) throws IOException, ServletException {
if (t instanceof ClientVisibleException) {
return getError(apiRequest, (ClientVisibleException)t);
} else {
return getUnknownError(apiRequest, t);
}
}
protected ApiError getError(ApiRequest apiRequest, ClientVisibleException e) {
if (e.getApiError() != null) {
return e.getApiError();
}
ErrorImpl errorImpl = new ErrorImpl(e);
return populateError(errorImpl, apiRequest.getLocale());
}
protected ApiError getUnknownError(ApiRequest apiRequest, Throwable t) throws IOException, ServletException {
if (throwUnknownErrors) {
log.error("Rethrowing exception in API for request [{}]", apiRequest, t);
ExceptionUtils.rethrowRuntime(t);
ExceptionUtils.rethrow(t, IOException.class);
ExceptionUtils.rethrow(t, ServletException.class);
throw new ServletException(t);
} else {
ErrorImpl e = new ErrorImpl(ResponseCodes.INTERNAL_SERVER_ERROR);
log.error("Exception in API for request [{}]. Error id: [{}].", apiRequest, e.getId(), t);
return populateError(e, apiRequest.getLocale());
}
}
protected ApiError populateError(ErrorImpl error, Locale locale) {
if (error.getCode() == null) {
if (standardErrorCodes != null) {
error.setCode(standardErrorCodes.getProperty(Integer.toString(error.getStatus())));
}
if (error.getCode() == null) {
error.setCode(Integer.toString(error.getStatus()));
}
}
if (error.getMessage() == null) {
error.setMessage(error.getCode());
}
error.setMessage(getMessage(error.getMessage(), locale));
error.setDetail(getMessage(error.getDetail(), locale));
return error;
}
protected String getMessage(String messageCode, Locale locale) {
if (messageCode == null) {
return messageCode;
}
String message = null;
message = getLocalizedMessage(messageLocationOverride, messageCode, locale);
if (message == null) {
message = getLocalizedMessage(messageLocation, messageCode, locale);
}
return message == null ? messageCode : message;
}
protected String getLocalizedMessage(String location, String messageCode, Locale locale) {
if (locale == null || location == null)
return null;
ResourceBundle bundle = ResourceBundle.getBundle(messageLocation, locale);
if (bundle != null) {
try {
return bundle.getString(messageCode);
} catch (MissingResourceException e) {
// ignore
}
}
return null;
}
public Properties getStandardErrorCodes() {
return standardErrorCodes;
}
public void setStandardErrorCodes(Properties standardErrorCodes) {
this.standardErrorCodes = standardErrorCodes;
}
public String getMessageLocation() {
return messageLocation;
}
public void setMessageLocation(String messageLocation) {
this.messageLocation = messageLocation;
}
public String getMessageLocationOverride() {
return messageLocationOverride;
}
public void setMessageLocationOverride(String messageLocationOverride) {
this.messageLocationOverride = messageLocationOverride;
}
public boolean isThrowUnknownErrors() {
return throwUnknownErrors;
}
public void setThrowUnknownErrors(boolean throwUnknownErrors) {
this.throwUnknownErrors = throwUnknownErrors;
}
}