Skip to content

Commit

Permalink
新增对允许但容易导致潜在问题的情况在 DEBUG 下返回警告信息
Browse files Browse the repository at this point in the history
  • Loading branch information
TommyLemon committed Sep 9, 2023
1 parent 214bbea commit 83eeaa2
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 71 deletions.
27 changes: 27 additions & 0 deletions APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -833,12 +833,39 @@ public JSONObject parseResponse(SQLConfig config, boolean isProcedure) throws Ex
if (parser.getSQLExecutor() == null) {
parser.createSQLExecutor();
}
if (parser != null && config.getParser() == null) {
config.setParser(parser);
}
return parser.getSQLExecutor().execute(config, isProcedure);
}


@Override
public SQLConfig newSQLConfig(boolean isProcedure) throws Exception {
String raw = Log.DEBUG == false || sqlRequest == null ? null : sqlRequest.getString(apijson.JSONRequest.KEY_RAW);
String[] keys = raw == null ? null : StringUtil.split(raw);
if (keys != null && keys.length > 0) {
boolean allow = AbstractSQLConfig.ALLOW_MISSING_KEY_4_COMBINE;

for (String key : keys) {
if (sqlRequest.get(key) != null) {
continue;
}

String msg = "@raw:value 的 value 中 " + key + " 不合法!对应的 "
+ key + ": value 在当前对象 " + name + " 不存在或 value = null,无法有效转为原始 SQL 片段!";

if (allow == false) {
throw new UnsupportedOperationException(msg);
}

if (parser instanceof AbstractParser) {
((AbstractParser) parser).putWarnIfNeed(JSONRequest.KEY_RAW, msg);
}
break;
}
}

return newSQLConfig(method, table, alias, sqlRequest, joinList, isProcedure)
.setParser(parser)
.setObjectParser(this);
Expand Down
209 changes: 147 additions & 62 deletions APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ public AbstractParser() {
* @param method null ? requestMethod = GET
*/
public AbstractParser(RequestMethod method) {
super();
setMethod(method);
setNeedVerifyRole(AbstractVerifier.ENABLE_VERIFY_ROLE);
setNeedVerifyContent(AbstractVerifier.ENABLE_VERIFY_CONTENT);
super();
setMethod(method);
setNeedVerifyRole(AbstractVerifier.ENABLE_VERIFY_ROLE);
setNeedVerifyContent(AbstractVerifier.ENABLE_VERIFY_CONTENT);
}
/**
* @param method null ? requestMethod = GET
Expand All @@ -145,6 +145,57 @@ public AbstractParser<T> setRoot(boolean isRoot) {
return this;
}

public static final String KEY_REF = "Reference";

/**警告信息
* Map<"Reference", "引用赋值获取路径 /Comment/userId 对应的值为 null!">
*/
protected Map<String, String> warnMap = new LinkedHashMap<>();
public String getWarn(String type) {
return warnMap == null ? null : warnMap.get(type);
}
public AbstractParser<T> putWarnIfNeed(String type, String warn) {
if (Log.DEBUG) {
String w = getWarn(type);
if (StringUtil.isEmpty(w, true)) {
putWarn(type, warn);
}
}
return this;
}
public AbstractParser<T> putWarn(String type, String warn) {
if (warnMap == null) {
warnMap = new LinkedHashMap<>();
}
warnMap.put(type, warn);
return this;
}
/**获取警告信息
* @return
*/
public String getWarnString() {
Set<Entry<String, String>> set = warnMap == null ? null : warnMap.entrySet();
if (set == null || set.isEmpty()) {
return null;
}

StringBuilder sb = new StringBuilder();
for (Entry<String, String> e : set) {
String k = e == null ? null : e.getKey();
String v = k == null ? null : e.getValue();
if (StringUtil.isEmpty(v, true)) {
continue;
}

if (StringUtil.isNotEmpty(k, true)) {
sb.append("[" + k + "]: ");
}
sb.append(v + "; ");
}

return sb.toString();
}


@NotNull
protected Visitor<T> visitor;
Expand Down Expand Up @@ -334,9 +385,6 @@ public AbstractParser<T> setNeedVerifyContent(boolean needVerifyContent) {
}





protected SQLExecutor sqlExecutor;
protected Verifier<T> verifier;
protected Map<String, Object> queryResultMap;//path-result
Expand Down Expand Up @@ -487,7 +535,9 @@ public JSONObject parseResponse(JSONObject request) {
onRollback();
}

requestObject = error == null ? extendSuccessResult(requestObject, isRoot) : extendErrorResult(requestObject, error, requestMethod, getRequestURL(), isRoot);
String warn = Log.DEBUG == false || error != null ? null : getWarnString();

requestObject = error == null ? extendSuccessResult(requestObject, warn, isRoot) : extendErrorResult(requestObject, error, requestMethod, getRequestURL(), isRoot);

JSONObject res = (globalFormat != null && globalFormat) && JSONResponse.isSuccess(requestObject) ? new JSONResponse(requestObject) : requestObject;

Expand Down Expand Up @@ -663,31 +713,49 @@ else if (target.containsKey(key) == false) {
* @return
*/
public static JSONObject newResult(int code, String msg) {
return newResult(code, msg, false);
return newResult(code, msg, null);
}
/**新建带状态内容的JSONObject

/**
* 添加JSONObject的状态内容,一般用于错误提示结果
*
* @param code
* @param msg
* @param warn
* @return
*/
public static JSONObject newResult(int code, String msg, String warn) {
return newResult(code, msg, warn, false);
}

/**
* 新建带状态内容的JSONObject
*
* @param code
* @param msg
* @param warn
* @param isRoot
* @return
*/
public static JSONObject newResult(int code, String msg, boolean isRoot) {
return extendResult(null, code, msg, isRoot);
public static JSONObject newResult(int code, String msg, String warn, boolean isRoot) {
return extendResult(null, code, msg, warn, isRoot);
}

/**添加JSONObject的状态内容,一般用于错误提示结果
/**
* 添加JSONObject的状态内容,一般用于错误提示结果
*
* @param object
* @param code
* @param msg
* @return
*/
public static JSONObject extendResult(JSONObject object, int code, String msg, boolean isRoot) {
public static JSONObject extendResult(JSONObject object, int code, String msg, String warn, boolean isRoot) {
int index = Log.DEBUG == false || isRoot == false || msg == null ? -1 : msg.lastIndexOf(Log.KEY_SYSTEM_INFO_DIVIDER);
String debug = Log.DEBUG == false || isRoot == false ? null : (index >= 0 ? msg.substring(index + Log.KEY_SYSTEM_INFO_DIVIDER.length()).trim()
: " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决!"
+ " \n开发者有限的时间和精力主要放在【维护项目源码和文档】上!"
+ " \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!!"
+ " \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!!"
+ " \n开发者有限的时间和精力主要放在【维护项目源码和文档】上!"
+ " \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!!"
+ " \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!!"
+ " \n\n **环境信息** "
+ " \n系统: " + Log.OS_NAME + " " + Log.OS_VERSION
+ " \n数据库: DEFAULT_DATABASE = " + AbstractSQLConfig.DEFAULT_DATABASE
Expand Down Expand Up @@ -717,40 +785,61 @@ public static JSONObject extendResult(JSONObject object, int code, String msg, b

object.put(JSONResponse.KEY_MSG, msg);
if (debug != null) {
if (StringUtil.isNotEmpty(warn, true)) {
debug += "\n 【警告】:" + warn;
}
object.put("debug:info|help", debug);
}

return object;
}


/**添加请求成功的状态内容
/**
* 添加请求成功的状态内容
*
* @param object
* @return
*/
public static JSONObject extendSuccessResult(JSONObject object) {
return extendSuccessResult(object, false);
}

public static JSONObject extendSuccessResult(JSONObject object, boolean isRoot) {
return extendSuccessResult(object, null, isRoot);
}

/**添加请求成功的状态内容
* @param object
* @param isRoot
* @return
*/
public static JSONObject extendSuccessResult(JSONObject object, boolean isRoot) {
return extendResult(object, JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, isRoot);
public static JSONObject extendSuccessResult(JSONObject object, String warn, boolean isRoot) {
return extendResult(object, JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, warn, isRoot);
}

/**获取请求成功的状态内容
* @return
*/
public static JSONObject newSuccessResult() {
return newSuccessResult(false);
return newSuccessResult(null);
}

/**获取请求成功的状态内容
* @param warn
* @return
*/
public static JSONObject newSuccessResult(String warn) {
return newSuccessResult(warn, false);
}

/**获取请求成功的状态内容
* @param warn
* @param isRoot
* @return
*/
public static JSONObject newSuccessResult(boolean isRoot) {
return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, isRoot);
public static JSONObject newSuccessResult(String warn, boolean isRoot) {
return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, warn, isRoot);
}

/**添加请求成功的状态内容
Expand Down Expand Up @@ -848,7 +937,7 @@ public static JSONObject extendErrorResult(JSONObject object, Throwable e, Reque
}

int code = CommonException.getCode(e);
return extendResult(object, code, msg, isRoot);
return extendResult(object, code, msg, null, isRoot);
}

/**新建错误状态内容
Expand All @@ -872,16 +961,13 @@ public static JSONObject newErrorResult(Exception e, boolean isRoot) {
String msg = CommonException.getMsg(e);
Integer code = CommonException.getCode(e);

return newResult(code, msg, isRoot);
return newResult(code, msg, null, isRoot);
}

return newResult(JSONResponse.CODE_SERVER_ERROR, JSONResponse.MSG_SERVER_ERROR, isRoot);
return newResult(JSONResponse.CODE_SERVER_ERROR, JSONResponse.MSG_SERVER_ERROR, null, isRoot);
}




//TODO 启动时一次性加载Request所有内容,作为初始化。
/**获取正确的请求,非GET请求必须是服务器指定的
* @return
* @throws Exception
Expand All @@ -902,7 +988,6 @@ public JSONObject parseCorrectRequest() throws Exception {
*/
@Override
public JSONObject getStructure(@NotNull String table, String method, String tag, int version) throws Exception {
// TODO 目前只使用 Request 而不使用 Response,所以这里写死用 REQUEST_MAP,以后可能 Response 表也会与 Request 表合并,用字段来区分
String cacheKey = AbstractVerifier.getCacheKeyForRequest(method, tag);
SortedMap<Integer, JSONObject> versionedMap = AbstractVerifier.REQUEST_MAP.get(cacheKey);

Expand Down Expand Up @@ -1419,17 +1504,17 @@ else if (join != null){

index = path.lastIndexOf("/");
String tableKey = index < 0 ? path : path.substring(0, index); // User:owner
int index2 = tableKey.lastIndexOf("/");
String arrKey = index2 < 0 ? null : tableKey.substring(0, index2);
if (arrKey != null && JSONRequest.isArrayKey(arrKey) == false) {
int index2 = tableKey.lastIndexOf("/");
String arrKey = index2 < 0 ? null : tableKey.substring(0, index2);
if (arrKey != null && JSONRequest.isArrayKey(arrKey) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + " 不是合法的数组 key[] !" +
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
}
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
}

tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);
tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);

apijson.orm.Entry<String, String> entry = Pair.parseEntry(tableKey, true);
String table = entry.getKey(); // User
apijson.orm.Entry<String, String> entry = Pair.parseEntry(tableKey, true);
String table = entry.getKey(); // User
if (StringUtil.isName(table) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!"
+ "必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式!"
Expand Down Expand Up @@ -1458,20 +1543,20 @@ else if (join != null){
"必须是 {} 这种 JSONObject 格式!" + e2.getMessage());
}

if (arrKey != null) {
if (parentPathObj.get(JSONRequest.KEY_JOIN) != null) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + ":{ join: value } 中 value 不合法!" +
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
}
if (arrKey != null) {
if (parentPathObj.get(JSONRequest.KEY_JOIN) != null) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + ":{ join: value } 中 value 不合法!" +
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
}

Integer subPage = parentPathObj.getInteger(JSONRequest.KEY_PAGE);
if (subPage != null && subPage != 0) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + ":{ page: value } 中 value 不合法!" +
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中 page 值只能为 null 或 0 !");
Integer subPage = parentPathObj.getInteger(JSONRequest.KEY_PAGE);
if (subPage != null && subPage != 0) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + ":{ page: value } 中 value 不合法!" +
"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中 page 值只能为 null 或 0 !");
}
}
}

boolean isAppJoin = "@".equals(joinType);
boolean isAppJoin = "@".equals(joinType);

JSONObject refObj = new JSONObject(tableObj.size(), true);

Expand All @@ -1489,8 +1574,8 @@ else if (join != null){
}

if (isAppJoin && StringUtil.isName(key.substring(0, key.length() - 1)) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + key + " 不合法 !" +
"@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + key + " 不合法 !" +
"@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
}

refObj.put(key, tableObj.getString(key));
Expand Down Expand Up @@ -1525,20 +1610,20 @@ else if (join != null){
apijson.orm.Entry<String, String> te = tk == null || p.substring(ind2 + 1).indexOf("/") >= 0 ? null : Pair.parseEntry(tk, true);

if (te != null && JSONRequest.isTableKey(te.getKey()) && request.get(tk) instanceof JSONObject) {
if (isAppJoin) {
if (refObj.size() >= 1) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!"
+ "@ APP JOIN 必须有且只有一个引用赋值键值对!");
}
if (isAppJoin) {
if (refObj.size() >= 1) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!"
+ "@ APP JOIN 必须有且只有一个引用赋值键值对!");
}

if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" +
"@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" +
"@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
}
}
}

refObj.put(k, v);
continue;
refObj.put(k, v);
continue;
}
}

Expand Down
Loading

0 comments on commit 83eeaa2

Please sign in to comment.