package com.rayo.server.exception; import javax.validation.ConstraintViolation; import com.rayo.server.exception.ErrorMapping; import com.rayo.server.exception.RayoProtocolException.Condition; import com.rayo.server.validation.ValidHandlerState; import com.rayo.core.validation.ValidationException; import com.voxeo.exceptions.NotFoundException; import com.voxeo.logging.Loggerf; import com.voxeo.moho.BusyException; import com.voxeo.moho.MediaException; import com.voxeo.servlet.xmpp.StanzaError; public class ExceptionMapper { private static final Loggerf log = Loggerf.getLogger(ExceptionMapper.class); public ErrorMapping toXmppError(Exception e) { String errorType = StanzaError.Type.CANCEL.toString(); String errorCondition = toString(StanzaError.Condition.INTERNAL_SERVER_ERROR); Integer httpCode = 500; String errorMessage = e.getMessage(); if (e instanceof ValidationException) { ConstraintViolation<?> violation = ((ValidationException)e).getFirstViolation(); errorType = StanzaError.Type.MODIFY.toString(); errorCondition = toString(StanzaError.Condition.BAD_REQUEST); httpCode = 400; if (violation != null) { if (violation.getConstraintDescriptor() != null && violation.getConstraintDescriptor().getAnnotation() instanceof ValidHandlerState) { errorCondition = violation.getPropertyPath().toString(); } if (violation.getMessageTemplate() != null) { errorMessage = violation.getMessageTemplate(); } else { errorMessage = String.format("Invalid value for property %s. Error: %s",violation.getPropertyPath(),violation.getMessage()); } } else { if (e.getMessage() != null) { errorMessage = e.getMessage(); } } return new ErrorMapping(errorType, errorCondition, errorMessage, httpCode); } else if(e instanceof NotFoundException) { errorCondition = toString(StanzaError.Condition.ITEM_NOT_FOUND); httpCode = 404; } else if (e instanceof IllegalArgumentException) { errorCondition = toString(StanzaError.Condition.BAD_REQUEST); httpCode = 400; } else if (e instanceof MediaException) { //TODO: Media Server needs to propagate proper response codes if (e.getMessage().contains("Response code of 407")) { // This is a grammar compilation issue errorCondition = toString(StanzaError.Condition.BAD_REQUEST); httpCode = 400; errorMessage = "There is an error in the grammar. It could not be compiled."; } } else if (e instanceof BusyException) { errorCondition = toString(StanzaError.Condition.RESOURCE_CONSTRAINT); errorMessage = "The requested resource is busy."; errorType = StanzaError.Type.WAIT.toString(); } else if (e instanceof RayoProtocolException) { RayoProtocolException re = (RayoProtocolException)e; switch (re.getCondition()) { case BAD_REQUEST: errorCondition = Condition.BAD_REQUEST.toString(); httpCode = 400; break; case ITEM_NOT_FOUND: errorCondition = Condition.ITEM_NOT_FOUND.toString(); httpCode = 404; break; case SERVICE_UNAVAILABLE: errorCondition = Condition.SERVICE_UNAVAILABLE.toString(); httpCode = 503; break; case CONFLICT: errorCondition = Condition.CONFLICT.toString(); httpCode = 409; break; default: log.error("Cound not map RayoProtocolException to XMPP [condition=%s]", re.getCondition()); } errorMessage = re.getMessage(); errorType = com.voxeo.servlet.xmpp.StanzaError.Type.CANCEL.toString(); } log.warn("Mapping unknown exception [type=%s, message=%s]",e.getClass(), e.getMessage()); return new ErrorMapping(errorType, errorCondition, errorMessage, httpCode); } public static String toString(com.voxeo.servlet.xmpp.StanzaError.Condition condition) { //TODO: Not needed once https://evolution.voxeo.com/ticket/1520421 is fixed return condition.toString().replaceAll("_", "-"); } }