package ameba.message.jackson.internal;
import ameba.core.Application;
import ameba.message.error.ErrorMessage;
import ameba.message.error.ExceptionMapperUtils;
import ameba.util.IOUtils;
import ameba.util.Result;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.hash.Hashing;
import org.glassfish.jersey.spi.ExceptionMappers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.PersistenceException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
/**
* <p>JsonProcessingExceptionMapper class.</p>
*
* @author icode
*/
@Singleton
public class JsonProcessingExceptionMapper implements ExceptionMapper<JsonProcessingException> {
private static final Logger logger = LoggerFactory.getLogger(JsonProcessingExceptionMapper.class);
@Context
private Provider<ExceptionMappers> exceptionMappers;
@Inject
private Application.Mode mode;
/**
* {@inheritDoc}
*/
@Override
public Response toResponse(JsonProcessingException exception) {
Throwable throwable = exception;
while (throwable != null) {
if (throwable instanceof PersistenceException) {
return exceptionMappers.get().findMapping(throwable).toResponse(throwable);
}
throwable = throwable.getCause();
}
logger.debug("Json Processing error", exception);
String message = exception.getOriginalMessage();
String desc = null;
String source = null;
if (mode.isDev()) {
desc = IOUtils.getStackTrace(exception);
JsonLocation location = exception.getLocation();
if (location != null) {
source = "line: " + location.getLineNr() +
", column: " + location.getColumnNr();
} else {
source = exception.getStackTrace()[0].toString();
}
}
ErrorMessage errorMessage = ErrorMessage.fromStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorMessage.setThrowable(exception);
errorMessage.setCode(Hashing.murmur3_32().hashUnencodedChars(exception.getClass().getName()).toString());
errorMessage.addError(new Result.Error(
errorMessage.getCode(),
message != null ? message : exception.getMessage(),
desc,
source
));
return Response.status(errorMessage.getStatus())
.entity(errorMessage)
.type(ExceptionMapperUtils.getResponseType())
.build();
}
}