Skip to content

Commit bbcf05e

Browse files
committed
解决某些情况下解析 引用赋值 出错 throw NullPointerException 或 IndexOutOfBoundsException
1 parent f05df3a commit bbcf05e

File tree

2 files changed

+78
-76
lines changed

2 files changed

+78
-76
lines changed

APIJSONORM/src/main/java/apijson/orm/AbstractParser.java

Lines changed: 77 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ public static JSONObject parseRequest(String request) throws Exception {
462462
@Override
463463
public JSONObject parseCorrectRequest(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request
464464
, int maxUpdateCount, SQLCreator creator) throws Exception {
465-
465+
466466
if (RequestMethod.isPublicMethod(method)) {
467467
return request;//需要指定JSON结构的get请求可以改为post请求。一般只有对安全性要求高的才会指定,而这种情况用明文的GET方式几乎肯定不安全
468468
}
@@ -486,10 +486,10 @@ public JSONObject parseCorrectRequest(RequestMethod method, String tag, int vers
486486

487487
JSONObject target = object;
488488
if (object.containsKey(tag) == false) { //tag 是 Table 名或 Table[]
489-
489+
490490
boolean isArrayKey = tag.endsWith(":[]"); // JSONRequest.isArrayKey(tag);
491491
String key = isArrayKey ? tag.substring(0, tag.length() - 3) : tag;
492-
492+
493493
if (apijson.JSONObject.isTableKey(key)) {
494494
if (isArrayKey) { //自动为 tag = Comment:[] 的 { ... } 新增键值对 "Comment[]":[] 为 { "Comment[]":[], ... }
495495
target.put(key + "[]", new JSONArray());
@@ -500,15 +500,15 @@ public JSONObject parseCorrectRequest(RequestMethod method, String tag, int vers
500500
}
501501
}
502502
}
503-
503+
504504
//获取指定的JSON结构 >>>>>>>>>>>>>>
505505

506-
506+
507507
//JSONObject clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {}
508508
return getVerifier().verifyRequest(method, name, target, request, maxUpdateCount, getGlobleDatabase(), getGlobleSchema(), creator);
509509
}
510-
511-
510+
511+
512512
/**新建带状态内容的JSONObject
513513
* @param code
514514
* @param msg
@@ -533,7 +533,7 @@ public static JSONObject extendResult(JSONObject object, int code, String msg) {
533533
if (object.containsKey(JSONResponse.KEY_CODE) == false) {
534534
object.put(JSONResponse.KEY_CODE, code);
535535
}
536-
536+
537537
String m = StringUtil.getString(object.getString(JSONResponse.KEY_MSG));
538538
if (m.isEmpty() == false) {
539539
msg = m + " ;\n " + StringUtil.getString(msg);
@@ -679,14 +679,14 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
679679
// TODO 目前只使用 Request 而不使用 Response,所以这里写死用 REQUEST_MAP,以后可能 Response 表也会与 Request 表合并,用字段来区分
680680
String cacheKey = AbstractVerifier.getCacheKeyForRequest(method, tag);
681681
SortedMap<Integer, JSONObject> versionedMap = AbstractVerifier.REQUEST_MAP.get(cacheKey);
682-
682+
683683
JSONObject result = versionedMap == null ? null : versionedMap.get(Integer.valueOf(version));
684684
if (result == null) { // version <= 0 时使用最新,version > 0 时使用 > version 的最接近版本(最小版本)
685685
Set<Entry<Integer, JSONObject>> set = versionedMap == null ? null : versionedMap.entrySet();
686-
686+
687687
if (set != null && set.isEmpty() == false) {
688688
Entry<Integer, JSONObject> maxEntry = null;
689-
689+
690690
for (Entry<Integer, JSONObject> entry : set) {
691691
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
692692
continue;
@@ -700,30 +700,30 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
700700
if (entry.getKey() < version) {
701701
break;
702702
}
703-
703+
704704
maxEntry = entry;
705705
}
706-
706+
707707
result = maxEntry == null ? null : maxEntry.getValue();
708708
}
709-
709+
710710
if (result != null) { // 加快下次查询,查到值的话组合情况其实是有限的,不属于恶意请求
711711
if (versionedMap == null) {
712712
versionedMap = new TreeMap<>((o1, o2) -> {
713713
return o2 == null ? -1 : o2.compareTo(o1); // 降序
714714
});
715715
}
716-
716+
717717
versionedMap.put(Integer.valueOf(version), result);
718718
AbstractVerifier.REQUEST_MAP.put(cacheKey, versionedMap);
719719
}
720720
}
721-
721+
722722
if (result == null) {
723723
if (AbstractVerifier.REQUEST_MAP.isEmpty() == false) {
724724
return null; // 已使用 REQUEST_MAP 缓存全部,但没查到
725725
}
726-
726+
727727
//获取指定的JSON结构 <<<<<<<<<<<<<<
728728
SQLConfig config = createSQLConfig().setMethod(GET).setTable(table);
729729
config.setPrepared(false);
@@ -732,7 +732,7 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
732732
Map<String, Object> where = new HashMap<String, Object>();
733733
where.put("method", method);
734734
where.put(JSONRequest.KEY_TAG, tag);
735-
735+
736736
if (version > 0) {
737737
where.put(JSONRequest.KEY_VERSION + "{}", ">=" + version);
738738
}
@@ -742,12 +742,12 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
742742

743743
//too many connections error: 不try-catch,可以让客户端看到是服务器内部异常
744744
result = getSQLExecutor().execute(config, false);
745-
745+
746746
// version, method, tag 组合情况太多了,JDK 里又没有 LRUCache,所以要么启动时一次性缓存全部后面只用缓存,要么每次都查数据库
747747
// versionedMap.put(Integer.valueOf(version), result);
748748
// AbstractVerifier.REQUEST_MAP.put(cacheKey, versionedMap);
749749
}
750-
750+
751751
return getJSONObject(result, "structure"); //解决返回值套了一层 "structure":{}
752752
}
753753

@@ -807,18 +807,18 @@ public JSONObject onObjectParse(final JSONObject request
807807
int index = parentPath.lastIndexOf("]/");
808808
if (index >= 0) {
809809
int total = rp.getIntValue(JSONResponse.KEY_COUNT);
810-
810+
811811
String pathPrefix = parentPath.substring(0, index) + "]/";
812812
putQueryResult(pathPrefix + JSONResponse.KEY_TOTAL, total);
813-
813+
814814
//详细的分页信息,主要为 PC 端提供
815815
int count = arrayConfig.getCount();
816816
int page = arrayConfig.getPage();
817817
int max = (int) ((total - 1)/count);
818818
if (max < 0) {
819819
max = 0;
820820
}
821-
821+
822822
JSONObject pagination = new JSONObject(true);
823823
pagination.put(JSONResponse.KEY_TOTAL, total);
824824
pagination.put(JSONRequest.KEY_COUNT, count);
@@ -929,51 +929,52 @@ public JSONArray onArrayParse(JSONObject request, String parentPath, String name
929929
request.remove(JSONRequest.KEY_JOIN);
930930
Log.d(TAG, "onArrayParse query = " + query + "; count = " + count + "; page = " + page + "; join = " + join);
931931

932-
if (request.isEmpty()) {//如果条件成立,说明所有的 parentPath/name:request 中request都无效!!!
932+
if (request.isEmpty()) { // 如果条件成立,说明所有的 parentPath/name:request 中request都无效!!! 后续都不执行,没必要还原数组关键词浪费性能
933933
Log.e(TAG, "onArrayParse request.isEmpty() >> return null;");
934934
return null;
935935
}
936936

937+
JSONArray response = null;
938+
try {
939+
int size = count2 == 0 ? max : count2;//count为每页数量,size为第page页实际数量,max(size) = count
940+
Log.d(TAG, "onArrayParse size = " + size + "; page = " + page);
937941

938-
int size = count2 == 0 ? max : count2;//count为每页数量,size为第page页实际数量,max(size) = count
939-
Log.d(TAG, "onArrayParse size = " + size + "; page = " + page);
940-
941-
942-
//key[]:{Table:{}}中key equals Table时 提取Table
943-
int index = isSubquery || name == null ? -1 : name.lastIndexOf("[]");
944-
String childPath = index <= 0 ? null : Pair.parseEntry(name.substring(0, index), true).getKey(); // Table-key1-key2...
945942

946-
//判断第一个key,即Table是否存在,如果存在就提取
947-
String[] childKeys = StringUtil.split(childPath, "-", false);
948-
if (childKeys == null || childKeys.length <= 0 || request.containsKey(childKeys[0]) == false) {
949-
childKeys = null;
950-
}
943+
//key[]:{Table:{}}中key equals Table时 提取Table
944+
int index = isSubquery || name == null ? -1 : name.lastIndexOf("[]");
945+
String childPath = index <= 0 ? null : Pair.parseEntry(name.substring(0, index), true).getKey(); // Table-key1-key2...
951946

947+
//判断第一个key,即Table是否存在,如果存在就提取
948+
String[] childKeys = StringUtil.split(childPath, "-", false);
949+
if (childKeys == null || childKeys.length <= 0 || request.containsKey(childKeys[0]) == false) {
950+
childKeys = null;
951+
}
952952

953-
//Table<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
954-
JSONArray response = new JSONArray();
955-
SQLConfig config = createSQLConfig()
956-
.setMethod(requestMethod)
957-
.setCount(size)
958-
.setPage(page)
959-
.setQuery(query2)
960-
.setJoinList(onJoinParse(join, request));
961953

962-
JSONObject parent;
963-
//生成size个
964-
for (int i = 0; i < (isSubquery ? 1 : size); i++) {
965-
parent = onObjectParse(request, isSubquery ? parentPath : path, isSubquery ? name : "" + i, config.setType(SQLConfig.TYPE_ITEM).setPosition(i), isSubquery);
966-
if (parent == null || parent.isEmpty()) {
967-
break;
954+
//Table<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
955+
response = new JSONArray();
956+
SQLConfig config = createSQLConfig()
957+
.setMethod(requestMethod)
958+
.setCount(size)
959+
.setPage(page)
960+
.setQuery(query2)
961+
.setJoinList(onJoinParse(join, request));
962+
963+
JSONObject parent;
964+
//生成size个
965+
for (int i = 0; i < (isSubquery ? 1 : size); i++) {
966+
parent = onObjectParse(request, isSubquery ? parentPath : path, isSubquery ? name : "" + i, config.setType(SQLConfig.TYPE_ITEM).setPosition(i), isSubquery);
967+
if (parent == null || parent.isEmpty()) {
968+
break;
969+
}
970+
//key[]:{Table:{}}中key equals Table时 提取Table
971+
response.add(getValue(parent, childKeys)); //null有意义
968972
}
969-
//key[]:{Table:{}}中key equals Table时 提取Table
970-
response.add(getValue(parent, childKeys)); //null有意义
971-
}
972-
//Table>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
973+
//Table>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
973974

974975

975-
/*
976-
* 支持引用取值后的数组
976+
/*
977+
* 支持引用取值后的数组
977978
{
978979
"User-id[]": {
979980
"User": {
@@ -986,18 +987,19 @@ public JSONArray onArrayParse(JSONObject request, String parentPath, String name
986987
}
987988
}
988989
}
989-
*/
990-
Object fo = childKeys == null || response.isEmpty() ? null : response.get(0);
991-
if (fo instanceof Boolean || fo instanceof Number || fo instanceof String) { //[{}] 和 [[]] 都没意义
992-
putQueryResult(path, response);
993-
}
994-
990+
*/
991+
Object fo = childKeys == null || response.isEmpty() ? null : response.get(0);
992+
if (fo instanceof Boolean || fo instanceof Number || fo instanceof String) { //[{}] 和 [[]] 都没意义
993+
putQueryResult(path, response);
994+
}
995+
} finally {
995996

996-
//后面还可能用到,要还原
997-
request.put(JSONRequest.KEY_QUERY, query);
998-
request.put(JSONRequest.KEY_COUNT, count);
999-
request.put(JSONRequest.KEY_PAGE, page);
1000-
request.put(JSONRequest.KEY_JOIN, join);
997+
//后面还可能用到,要还原
998+
request.put(JSONRequest.KEY_QUERY, query);
999+
request.put(JSONRequest.KEY_COUNT, count);
1000+
request.put(JSONRequest.KEY_PAGE, page);
1001+
request.put(JSONRequest.KEY_JOIN, join);
1002+
}
10011003

10021004
if (Log.DEBUG) {
10031005
Log.i(TAG, "onArrayParse return response = \n" + JSON.toJSONString(response) + "\n>>>>>>>>>>>>>>>\n\n\n");
@@ -1142,23 +1144,23 @@ else if (join != null){
11421144

11431145

11441146
private static final List<String> JOIN_COPY_KEY_LIST;
1145-
static {//TODO 不全
1147+
static { // TODO 不全
11461148
JOIN_COPY_KEY_LIST = new ArrayList<String>();
1149+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ROLE);
11471150
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_DATABASE);
11481151
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_SCHEMA);
11491152
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COLUMN);
11501153
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COMBINE);
11511154
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_GROUP);
11521155
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_HAVING);
11531156
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ORDER);
1157+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_RAW);
11541158
}
11551159

1156-
/**
1157-
* 取指定json对象的id集合
1160+
/**取指定 JSON 对象的 id 集合
11581161
* @param table
11591162
* @param key
11601163
* @param obj
1161-
* @param targetKey
11621164
* @return null ? 全部 : 有限的数组
11631165
*/
11641166
private JSONObject getJoinObject(String table, JSONObject obj, String key) {
@@ -1171,8 +1173,8 @@ private JSONObject getJoinObject(String table, JSONObject obj, String key) {
11711173
return null;
11721174
}
11731175

1174-
//取出所有join条件
1175-
JSONObject requestObj = new JSONObject(true);//(JSONObject) obj.clone();//
1176+
// 取出所有 join 条件
1177+
JSONObject requestObj = new JSONObject(true); // (JSONObject) obj.clone();
11761178
Set<String> set = new LinkedHashSet<>(obj.keySet());
11771179
for (String k : set) {
11781180
if (StringUtil.isEmpty(k, true)) {
@@ -1190,7 +1192,7 @@ private JSONObject getJoinObject(String table, JSONObject obj, String key) {
11901192
continue;
11911193
}
11921194
throw new UnsupportedOperationException(table + "." + k + " 不合法!" + JSONRequest.KEY_JOIN
1193-
+ " 关联的Table中只能有1个 key@:value !");
1195+
+ " 关联的Table中只能有1个 key@:value !"); // TODO 支持 join on
11941196
}
11951197

11961198
if (k.contains("()") == false) { //不需要远程函数
@@ -1393,7 +1395,7 @@ public Object getValueByPath(String valuePath) {
13931395

13941396
if (parent != null) {
13951397
Log.i(TAG, "getValueByPath >> get from queryResultMap >> return parent.get(keys[keys.length - 1]);");
1396-
target = parent.get(keys[keys.length - 1]); //值为null应该报错NotExistExeption,一般都是id关联,不可为null,否则可能绕过安全机制
1398+
target = keys == null || keys.length <= 0 ? parent : parent.get(keys[keys.length - 1]); //值为null应该报错NotExistExeption,一般都是id关联,不可为null,否则可能绕过安全机制
13971399
if (target != null) {
13981400
Log.i(TAG, "getValueByPath >> getValue >> return target = " + target);
13991401
return target;

APIJSONORM/src/main/java/apijson/orm/SQLConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public interface SQLConfig {
112112
SQLConfig setId(Object id);
113113

114114
RequestRole getRole();
115-
SQLConfig setRole(RequestRole role);
115+
SQLConfig setRole(RequestRole role); // TODO 提供 String 类型的,方便扩展
116116

117117
public boolean isDistinct();
118118
public SQLConfig setDistinct(boolean distinct);

0 commit comments

Comments
 (0)