Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.rx.core.SystemException Maven / Gradle / Ivy
package org.rx.core;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.rx.annotation.ErrorCode;
import org.rx.beans.$;
import org.rx.beans.BiTuple;
import org.rx.beans.Tuple;
import org.springframework.core.NestedRuntimeException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.*;
import static org.rx.core.Contract.*;
/**
* 根据Exception来读取errorCode.yml的错误信息
* ex.fillInStackTrace()
* https://northconcepts.com/blog/2013/01/18/6-tips-to-improve-your-exception-handling/
*/
@Slf4j
public class SystemException extends NestedRuntimeException {
public static final String CodeFile = "code.yml";
public static final String DefaultMessage = isNull(getSettings().get("default"), "网络繁忙,请稍后再试。").toString();
private static Map getSettings() {
return MemoryCache.getOrStore("SystemException", k -> {
List files = new ArrayList<>();
files.add(CodeFile);
if (!Arrays.isEmpty(App.Config.getErrorCodeFiles())) {
files.addAll(Arrays.toList(App.Config.getErrorCodeFiles()));
}
return isNull(catchCall(() -> {
Map codes = App.loadYaml(NQuery.of(files).toArray(String.class));
if (codes.isEmpty()) {
log.warn("load code.yml fail");
}
return codes;
}), Collections.emptyMap());
});
}
public static SystemException wrap(Throwable cause) {
if (cause == null) {
return null;
}
if (cause instanceof SystemException) {
return (SystemException) cause;
}
return new SystemException(cause);
}
private String friendlyMessage;
private Map data;
/**
* Gets the method that throws the current cause.
*/
@Getter(AccessLevel.PROTECTED)
private BiTuple targetSite;
@Getter
private Enum errorCode;
@Override
public String getMessage() {
return isNull(friendlyMessage, super.getMessage());
}
public String getFriendlyMessage() {
return isNull(friendlyMessage, DefaultMessage);
}
public Map getData() {
if (data == null) {
data = new HashMap<>();
}
return data;
}
protected SystemException(String message) {
super(message);
}
protected SystemException(Throwable cause) {
super(cause != null ? cause.getMessage() : null, cause);
}
public SystemException(Object[] messageValues) {
this(null, null, messageValues);
}
public SystemException(Object[] messageValues, String errorName) {
this(errorName, null, messageValues);
}
public SystemException(Object[] messageValues, Throwable cause) {
this(null, cause, messageValues);
}
public SystemException(String errorName, Throwable cause, Object[] messageValues) {
super(cause != null ? cause.getMessage() : null, cause);
if (messageValues == null) {
messageValues = Arrays.EMPTY_OBJECT_ARRAY;
}
for (StackTraceElement stack : Reflects.threadStack(8)) {
Map methodSettings = as(App.readSetting(stack.getClassName(), null, getSettings()), Map.class);
if (methodSettings == null) {
continue;
}
Tuple caller = as(MemoryCache.getOrStore(stack.getClassName(), p -> {
Class type = App.loadClass(p, false);
return Tuple.of(type, type.getDeclaredMethods());
}), Tuple.class);
if (caller == null) {
continue;
}
Class source = null;
Method targetSite = null;
ErrorCode errorCode = null;
for (Method method : caller.right) {
if (!method.getName().equals(stack.getMethodName())) {
continue;
}
if ((errorCode = findCode(method, errorName, cause)) == null) {
continue;
}
log.debug("SystemException: Found @ErrorCode at {}", method.toString());
source = caller.left;
targetSite = method;
break;
}
if (errorCode == null) {
continue;
}
this.targetSite = BiTuple.of(source, targetSite, errorCode);
setFriendlyMessage(methodSettings, targetSite.getName(), errorCode, messageValues);
break;
}
if (friendlyMessage == null) {
log.debug("SystemException: Not found @ErrorCode");
}
}
@SneakyThrows
public > SystemException setErrorCode(T enumErrorCode, Object... messageValues) {
if ((this.errorCode = enumErrorCode) == null) {
log.debug("SystemException.setErrorCode: Parameter errorCode is null");
return this;
}
Class type = enumErrorCode.getClass();
Map methodSettings = as(App.readSetting(type.getName(), null, getSettings()), Map.class);
if (methodSettings == null) {
return this;
}
Field field = type.getDeclaredField(enumErrorCode.name());
ErrorCode errorCode;
if ((errorCode = findCode(field, null, null)) == null) {
return this;
}
setFriendlyMessage(methodSettings, enumErrorCode.name(), errorCode, messageValues);
return this;
}
private ErrorCode findCode(AccessibleObject member, String errorName, Throwable cause) {
NQuery errorCodes = NQuery.of(member.getAnnotationsByType(ErrorCode.class));
if (!errorCodes.any()) {
log.debug("SystemException: Not found @ErrorCode in {}", member.toString());
return null;
}
if (errorName != null) {
errorCodes = errorCodes.where(p -> errorName.equals(p.value()));
}
if (cause != null) {
errorCodes = errorCodes.orderByDescending(p -> {
byte count = 0;
Class st = p.cause();
for (; count < 8; count++) {
if (st.equals(Exception.class)) {
break;
}
st = st.getSuperclass();
}
return count;
}).where(p -> p.cause().isAssignableFrom(cause.getClass()));
}
if (!errorCodes.any()) {
return null;
}
return errorCodes.first();
}
private void setFriendlyMessage(Map methodSettings, String messageName, ErrorCode errorCode,
Object[] messageValues) {
if (!Strings.isNullOrEmpty(errorCode.value())) {
messageName += "[" + errorCode.value() + "]";
}
if (!Exception.class.equals(errorCode.cause())) {
messageName += "<" + errorCode.cause().getSimpleName() + ">";
}
String msg = as(methodSettings.get(messageName), String.class);
if (msg == null) {
log.debug("SystemException: Not found messageName {}", messageName);
return;
}
switch (errorCode.messageFormatter()) {
case StringFormat:
msg = String.format(msg, messageValues);
break;
case MessageFormat:
msg = MessageFormat.format(msg, messageValues);
break;
default:
String[] messageKeys = errorCode.messageKeys();
if (messageKeys.length != messageValues.length) {
log.debug("SystemException: MessageKeys length {} not equals messageValues length {}",
messageKeys.length, messageValues.length);
return;
}
NQuery> query = NQuery.of(messageKeys)
.select((p, i) -> Tuple.of(p, messageValues[i]));
if (data != null) {
query = query
.union(NQuery.of(data.entrySet()).select(p -> Tuple.of(p.getKey(), p.getValue())).toList());
}
StringBuilder temp = new StringBuilder().append(msg);
for (Tuple tuple : query.orderByDescending(p -> p.left.length())) {
temp.replace(tuple.left, toJsonString(tuple.right));
}
msg = temp.toString();
break;
}
friendlyMessage = msg;
}
public boolean tryGet($ out, Class exType) {
if (out == null || exType == null) {
return false;
}
if (exType.isInstance(this)) {
out.v = (T) this;
return true;
}
Throwable cause = this.getCause();
if (cause == this) {
return false;
}
if (cause instanceof SystemException) {
return ((SystemException) cause).tryGet(out, exType);
}
while (cause != null) {
if (exType.isInstance(cause)) {
out.v = (T) cause;
return true;
}
if (cause.getCause() == cause) {
break;
}
cause = cause.getCause();
}
return false;
}
public SystemException setFriendlyMessage(String format, Object... args) {
friendlyMessage = String.format(format, args);
return this;
}
protected Object recall(Object instance, Object... args) throws ReflectiveOperationException {
require(targetSite);
return targetSite.middle.invoke(instance, args);
}
}