io.tarantool.driver.exceptions.errors.TarantoolErrors Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cartridge-driver Show documentation
Show all versions of cartridge-driver Show documentation
Tarantool Cartridge driver for Tarantool versions 1.10+ based on Netty framework
package io.tarantool.driver.exceptions.errors;
import io.tarantool.driver.exceptions.TarantoolAccessDeniedException;
import io.tarantool.driver.exceptions.TarantoolException;
import io.tarantool.driver.exceptions.TarantoolInternalException;
import io.tarantool.driver.exceptions.TarantoolInternalNetworkException;
import io.tarantool.driver.exceptions.TarantoolNoSuchProcedureException;
import io.tarantool.driver.protocol.TarantoolErrorResult;
import org.msgpack.value.Value;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class-container for built-in tarantool errors factories
*
* @author Artyom Dubinin
* @author Oleg Kuznetsov
*/
public class TarantoolErrors {
private static final String CLIENT_ERROR_TYPE = "ClientError";
/**
* Produces {@link TarantoolInternalException} subclasses
* from the serialized representation in the format of require('errors').new_class("NewError")
,
*
* @see tarantool/errors
*/
public static class TarantoolErrorsErrorFactory implements TarantoolErrorFactory {
private static final Pattern NETWORK_ERROR_PATTERN = Pattern.compile(
"(?=.*\"type\":\"" + CLIENT_ERROR_TYPE + "\")"
+ "(?=.*\"code\":"
+ "[" + ErrorCode.NO_CONNECTION.getCode() + "|" + ErrorCode.TIMEOUT.getCode() + "])",
Pattern.DOTALL);
public TarantoolErrorsErrorFactory() {
}
@Override
public Optional create(Value error) {
if (error == null || !error.isMapValue()) {
return Optional.empty();
}
final Map errorMap = error.asMapValue().map();
if (!isErrorsError(errorMap)) {
return Optional.empty();
}
String exceptionMessage = getExceptionMessage(ErrorsErrorKey.values(), errorMap);
if (isNetworkError(errorMap)) {
return Optional.of(new TarantoolInternalNetworkException(exceptionMessage));
}
return Optional.of(new TarantoolInternalException(exceptionMessage));
}
/**
* Check code from tarantool/errors is network code or not
*
* @param errorMap map which contain info about error from tarantool/errors
* @return an {@link Boolean}
*/
private Boolean isNetworkError(Map errorMap) {
String err = errorMap.containsKey(ErrorsErrorKey.ERR.getMsgPackKey()) ?
errorMap.get(ErrorsErrorKey.ERR.getMsgPackKey()).toString() : null;
if (err == null) {
return false;
}
// 77 or 78 code
// FIXME: Blocked by https://github.com/tarantool/crud/issues/186
Matcher matcher = NETWORK_ERROR_PATTERN.matcher(err);
return matcher.find();
}
/**
* Check the error message contains field of str,
* which contains an error in tarantool/errors
*
* @param errorMap string message from tarantool/errors
* @return an {@link Boolean}
*/
private Boolean isErrorsError(Map errorMap) {
return errorMap.containsKey(ErrorsErrorKey.ERROR_MESSAGE.getMsgPackKey());
}
}
/**
* Produces {@link TarantoolInternalException} subclasses from the serialized representation
* in the format of box.error:unpack
,
*
* @see box_error
*/
public static class TarantoolBoxErrorFactory implements TarantoolErrorFactory {
private static final long ERROR_INDICATOR_OFFSET = 32768L;
public TarantoolBoxErrorFactory() {
}
@Override
public Optional create(Value error) {
if (error == null || !error.isMapValue()) {
return Optional.empty();
}
Map errorMap = error.asMapValue().map();
if (!isBoxError(errorMap)) {
return Optional.empty();
}
String exceptionMessage = getExceptionMessage(BoxErrorKey.values(), errorMap);
if (isNetworkError(errorMap)) {
return Optional.of(new TarantoolInternalNetworkException(exceptionMessage));
}
return Optional.of(new TarantoolInternalException(exceptionMessage));
}
public TarantoolException create(TarantoolErrorResult error) {
Long code = error.getErrorCode() - ERROR_INDICATOR_OFFSET;
String message = error.getErrorMessage();
StringBuilder sb = new StringBuilder("InnerErrorMessage:");
sb.append("\n").append(BoxErrorKey.CODE.getKey()).append(": ").append(code);
if (message != null) {
sb.append("\n").append(BoxErrorKey.MESSAGE.getKey()).append(": ").append(message);
}
String exceptionMessage = sb.toString();
if (isNetworkError(code)) {
return new TarantoolInternalNetworkException(exceptionMessage);
}
if (ErrorCode.NO_SUCH_PROCEDURE.getCode().equals(code)) {
return new TarantoolNoSuchProcedureException(exceptionMessage);
}
if (ErrorCode.ACCESS_DENIED.getCode().equals(code)) {
return new TarantoolAccessDeniedException(exceptionMessage);
}
return new TarantoolInternalException(exceptionMessage);
}
/**
* Check code from box.error is network code or not
*
* @param errorMap map which contain info about error
* @return an {@link Boolean}
*/
private Boolean isNetworkError(Map errorMap) {
long code = errorMap.get(BoxErrorKey.CODE.getMsgPackKey()).asIntegerValue().asLong();
String type = errorMap.get(BoxErrorKey.TYPE.getMsgPackKey()).toString();
// 77 or 78 code
return (code == ErrorCode.NO_CONNECTION.getCode() || code == ErrorCode.TIMEOUT.getCode())
&& type != null && type.equals(CLIENT_ERROR_TYPE);
}
/**
* Check code from box.error is network code or not
*
* @param code code from box.error
* @return an {@link Boolean}
*/
private Boolean isNetworkError(Long code) {
// 77 or 78 code
return code.equals(ErrorCode.NO_CONNECTION.getCode())
|| code.equals(ErrorCode.TIMEOUT.getCode());
}
/**
* Check the error message contains fields of code and message
*
* @param errorMap map which contain info about error
* @return an {@link Boolean}
*/
private Boolean isBoxError(Map errorMap) {
return errorMap.containsKey(BoxErrorKey.CODE.getMsgPackKey())
&& errorMap.containsKey(BoxErrorKey.MESSAGE.getMsgPackKey());
}
}
private static String getExceptionMessage(ErrorKey[] errorKeys, Map errorMap) {
return new ErrorMessageBuilder("InnerErrorMessage:", errorKeys, errorMap).build();
}
/**
* The factory is finalizing, i.e. errors passed into
* it will always be introverted as appropriate for the given factory
* The error is generated in a message that is passed to {@link TarantoolInternalException}
*/
public static class TarantoolUnrecognizedErrorFactory implements TarantoolErrorFactory {
public TarantoolUnrecognizedErrorFactory() {
}
@Override
public Optional create(Value error) {
String exceptionMessage = String.valueOf(error);
return Optional.of(new TarantoolInternalException(exceptionMessage));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy