mirror of https://github.com/apache/lucene.git
SOLR-7838: changed the permissions froma map to an array so that order is obvious
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1695308 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
040849908c
commit
11ac3f7f88
|
@ -18,6 +18,7 @@ package org.apache.solr.handler.admin;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -141,9 +142,14 @@ public class SecurityConfHandler extends RequestHandlerBase {
|
|||
}
|
||||
|
||||
public static Map<String, Object> getMapValue(Map<String, Object> lookupMap, String key) {
|
||||
Map<String, Object> roleMap = (Map<String, Object>) lookupMap.get(key);
|
||||
if (roleMap == null) lookupMap.put(key, roleMap = new LinkedHashMap<>());
|
||||
return roleMap;
|
||||
Map<String, Object> m = (Map<String, Object>) lookupMap.get(key);
|
||||
if (m == null) lookupMap.put(key, m = new LinkedHashMap<>());
|
||||
return m;
|
||||
}
|
||||
public static List getListValue(Map<String, Object> lookupMap, String key) {
|
||||
List l = (List) lookupMap.get(key);
|
||||
if (l == null) lookupMap.put(key, l= new ArrayList());
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -39,6 +39,8 @@ import org.apache.solr.util.CommandOperation;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
import static org.apache.solr.handler.admin.SecurityConfHandler.getListValue;
|
||||
import static org.apache.solr.handler.admin.SecurityConfHandler.getMapValue;
|
||||
import static org.apache.solr.common.params.CommonParams.NAME;
|
||||
import static org.apache.solr.common.util.Utils.getDeepCopy;
|
||||
|
@ -86,12 +88,15 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
@Override
|
||||
public AuthorizationResponse authorize(AuthorizationContext context) {
|
||||
List<AuthorizationContext.CollectionRequest> collectionRequests = context.getCollectionRequests();
|
||||
if (collectionRequests != null) {
|
||||
for (AuthorizationContext.CollectionRequest collreq : collectionRequests) {
|
||||
//check permissions for each collection
|
||||
MatchStatus flag = checkCollPerm(mapping.get(collreq.collectionName), context);
|
||||
if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag.rsp;
|
||||
}
|
||||
if (collectionRequests.isEmpty()) {
|
||||
MatchStatus flag = checkCollPerm(mapping.get(""), context);
|
||||
return flag.rsp;
|
||||
}
|
||||
|
||||
for (AuthorizationContext.CollectionRequest collreq : collectionRequests) {
|
||||
//check permissions for each collection
|
||||
MatchStatus flag = checkCollPerm(mapping.get(collreq.collectionName), context);
|
||||
if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag.rsp;
|
||||
}
|
||||
//check global permissions.
|
||||
MatchStatus flag = checkCollPerm(mapping.get(null), context);
|
||||
|
@ -160,12 +165,11 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
String roleName = (String) e.getKey();
|
||||
usersVsRoles.put(roleName, readValueAsSet(map, roleName));
|
||||
}
|
||||
map = getMapValue(initInfo, "permissions");
|
||||
for (Object o : map.entrySet()) {
|
||||
Map.Entry e = (Map.Entry) o;
|
||||
List<Map> perms = getListValue(initInfo, "permissions");
|
||||
for (Map o : perms) {
|
||||
Permission p;
|
||||
try {
|
||||
p = Permission.load((String) e.getKey(), (Map) e.getValue());
|
||||
p = Permission.load(o);
|
||||
} catch (Exception exp) {
|
||||
log.error("Invalid permission ", exp);
|
||||
continue;
|
||||
|
@ -175,8 +179,8 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
}
|
||||
}
|
||||
|
||||
//this is to do optimized lookup of permissions for a given collection/path
|
||||
private void add2Mapping(Permission permission) {
|
||||
//this is to do optimized lookup of permissions for a given collection/path
|
||||
for (String c : permission.collections) {
|
||||
WildCardSupportMap m = mapping.get(c);
|
||||
if (m == null) mapping.put(c, m = new WildCardSupportMap());
|
||||
|
@ -186,7 +190,6 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
perms.add(permission);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,7 +202,14 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
static Set<String> readValueAsSet(Map m, String key) {
|
||||
Set<String> result = new HashSet<>();
|
||||
Object val = m.get(key);
|
||||
if (val == null) return null;
|
||||
if (val == null) {
|
||||
if("collection".equals(key)){
|
||||
//for collection collection: null means a core admin/ collection admin request
|
||||
// otherwise it means a request where collection name is ignored
|
||||
return m.containsKey(key) ? singleton("") : singleton(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (val instanceof Collection) {
|
||||
Collection list = (Collection) val;
|
||||
for (Object o : list) result.add(String.valueOf(o));
|
||||
|
@ -223,13 +233,15 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
private Permission() {
|
||||
}
|
||||
|
||||
static Permission load(String name, Map m) {
|
||||
static Permission load(Map m) {
|
||||
Permission p = new Permission();
|
||||
String name = (String) m.get(NAME);
|
||||
if (!m.containsKey("role")) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "role not specified");
|
||||
p.role = readValueAsSet(m, "role");
|
||||
if (well_known_permissions.containsKey(name)) {
|
||||
HashSet<String> disAllowed = new HashSet<>(knownKeys);
|
||||
disAllowed.remove("role");
|
||||
disAllowed.remove("role");//these are the only
|
||||
disAllowed.remove(NAME);//allowed keys for well-known permissions
|
||||
for (String s : disAllowed) {
|
||||
if (m.containsKey(s))
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, s + " is not a valid key for the permission : " + name);
|
||||
|
@ -245,7 +257,7 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
return p;
|
||||
}
|
||||
|
||||
static final Set<String> knownKeys = ImmutableSet.of("collection", "role", "params", "path", "method");
|
||||
static final Set<String> knownKeys = ImmutableSet.of("collection", "role", "params", "path", "method", NAME);
|
||||
}
|
||||
|
||||
enum MatchStatus {
|
||||
|
@ -275,7 +287,7 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
}
|
||||
return set;
|
||||
}
|
||||
return set == null ? Collections.singleton(null) : set;
|
||||
return set == null ? singleton(null) : set;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -328,36 +340,53 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
Map<String, Object> dataMap = op.getDataMap();
|
||||
if (op.hasError()) return null;
|
||||
dataMap = getDeepCopy(dataMap, 3);
|
||||
dataMap.remove(NAME);
|
||||
String before = (String) dataMap.remove("before");
|
||||
for (String key : dataMap.keySet()) {
|
||||
if (!Permission.knownKeys.contains(key)) op.addError("Unknown key, " + key);
|
||||
}
|
||||
try {
|
||||
Permission.load(name, dataMap);
|
||||
Permission.load(dataMap);
|
||||
} catch (Exception e) {
|
||||
op.addError(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> permissions = getMapValue(latestConf, "permissions");
|
||||
if (before == null) {
|
||||
permissions.put(name, dataMap);
|
||||
} else {
|
||||
Map<String, Object> permissionsCopy = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> e : permissions.entrySet()) {
|
||||
if (e.getKey().equals(before)) permissionsCopy.put(name, dataMap);
|
||||
permissionsCopy.put(e.getKey(), e.getValue());
|
||||
List<Map> permissions = getListValue(latestConf, "permissions");
|
||||
List<Map> permissionsCopy = new ArrayList<>();
|
||||
boolean added = false;
|
||||
for (Map e : permissions) {
|
||||
Object n = e.get(NAME);
|
||||
if (n.equals(before) || n.equals(name)) {
|
||||
added = true;
|
||||
permissionsCopy.add(dataMap);
|
||||
}
|
||||
if (!permissionsCopy.containsKey(name)) {
|
||||
op.addError("Invalid 'before' :" + before);
|
||||
return null;
|
||||
}
|
||||
latestConf.put("permissions", permissionsCopy);
|
||||
if (!n.equals(name)) permissionsCopy.add(e);
|
||||
}
|
||||
|
||||
if (!added && before != null) {
|
||||
op.addError("Invalid 'before' :" + before);
|
||||
return null;
|
||||
}
|
||||
if (!added) permissionsCopy.add(dataMap);
|
||||
latestConf.put("permissions", permissionsCopy);
|
||||
return latestConf;
|
||||
}
|
||||
},
|
||||
UPDATE_PERMISSION("update-permission") {
|
||||
@Override
|
||||
public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
|
||||
String name = op.getStr(NAME);
|
||||
if (op.hasError()) return null;
|
||||
for (Map permission : (List<Map>) getListValue(latestConf, "permissions")) {
|
||||
if (name.equals(permission.get(NAME))) {
|
||||
LinkedHashMap copy = new LinkedHashMap<>(permission);
|
||||
copy.putAll(op.getDataMap());
|
||||
op.setCommandData(copy);
|
||||
return SET_PERMISSION.edit(latestConf, op);
|
||||
}
|
||||
}
|
||||
op.addError("No such permission " + name);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
DELETE_PERMISSION("delete-permission") {
|
||||
@Override
|
||||
public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
|
||||
|
@ -366,13 +395,23 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
op.addError("Invalid command");
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> p = getMapValue(latestConf, "permissions");
|
||||
for (String s : names) {
|
||||
if (p.remove(s) == null) {
|
||||
op.addError("Unknown permission : " + s);
|
||||
return null;
|
||||
names = new ArrayList<>(names);
|
||||
List<Map> copy = new ArrayList<>();
|
||||
List<Map> p = getListValue(latestConf, "permissions");
|
||||
for (Map map : p) {
|
||||
Object n = map.get(NAME);
|
||||
if (names.contains(n)) {
|
||||
names.remove(n);
|
||||
continue;
|
||||
} else {
|
||||
copy.add(map);
|
||||
}
|
||||
}
|
||||
if (!names.isEmpty()) {
|
||||
op.addError("Unknown permission name(s) " + names);
|
||||
return null;
|
||||
}
|
||||
latestConf.put("permissions", copy);
|
||||
return latestConf;
|
||||
}
|
||||
};
|
||||
|
@ -397,16 +436,20 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
|
|||
" { " +
|
||||
" security-edit :{" +
|
||||
" path:['/admin/authentication','/admin/authorization']," +
|
||||
" collection:null," +
|
||||
" method:POST }," +
|
||||
" security-read :{" +
|
||||
" path:['/admin/authentication','/admin/authorization']," +
|
||||
" method:GET }," +
|
||||
" collection:null," +
|
||||
" method:GET}," +
|
||||
" schema-edit :{" +
|
||||
" method:POST," +
|
||||
" path:'/schema/*'}," +
|
||||
" collection-admin-edit :{" +
|
||||
" collection:null," +
|
||||
" path:'/admin/collections'}," +
|
||||
" collection-admin-read :{" +
|
||||
" collection:null," +
|
||||
" path:'/admin/collections'}," +
|
||||
" schema-read :{" +
|
||||
" method:GET," +
|
||||
|
|
|
@ -59,6 +59,9 @@ public class CommandOperation {
|
|||
Object o = getMapVal(key);
|
||||
return o == null ? def : String.valueOf(o);
|
||||
}
|
||||
public void setCommandData(Object o){
|
||||
commandData = o;
|
||||
}
|
||||
|
||||
public Map<String,Object> getDataMap() {
|
||||
if (commandData instanceof Map) {
|
||||
|
|
|
@ -97,13 +97,56 @@ public class SecurityConfHandlerTest extends SolrTestCaseJ4 {
|
|||
List tomRoles = (List) userRoles.get("tom");
|
||||
assertTrue(tomRoles.contains("admin"));
|
||||
assertTrue(tomRoles.contains("dev"));
|
||||
Map permissions = (Map) authzconf.get("permissions");
|
||||
List<Map> permissions = (List<Map>) authzconf.get("permissions");
|
||||
assertEquals(2, permissions.size());
|
||||
for (Object p : permissions.entrySet()) {
|
||||
Map.Entry e = (Map.Entry) p;
|
||||
assertEquals("some-permission", e.getKey());
|
||||
for (Map p : permissions) {
|
||||
assertEquals("some-permission", p.get("name"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
command = "{\n" +
|
||||
"'set-permission':{'name': 'security-edit',\n" +
|
||||
" 'role': ['admin','dev']\n" +
|
||||
" }}";
|
||||
req = new LocalSolrQueryRequest(null, new ModifiableSolrParams());
|
||||
req.getContext().put("httpMethod","POST");
|
||||
req.getContext().put("path","/admin/authorization");
|
||||
o = new ContentStreamBase.ByteArrayStream(command.getBytes(StandardCharsets.UTF_8),"");
|
||||
req.setContentStreams(Collections.singletonList(o));
|
||||
rsp = new SolrQueryResponse();
|
||||
handler.handleRequestBody(req, rsp);
|
||||
authzconf = (Map) ((ConfigData) handler.m.get("/security.json")).data.get("authorization");
|
||||
permissions = (List<Map>) authzconf.get("permissions");
|
||||
|
||||
Map p = permissions.get(1);
|
||||
assertEquals("security-edit", p.get("name"));
|
||||
List rol = (List) p.get("role");
|
||||
assertEquals( "admin", rol.get(0));
|
||||
assertEquals( "dev", rol.get(1));
|
||||
|
||||
command = "{\n" +
|
||||
"'update-permission':{'name': 'some-permission',\n" +
|
||||
" 'role': ['guest','admin']\n" +
|
||||
" }}";
|
||||
req = new LocalSolrQueryRequest(null, new ModifiableSolrParams());
|
||||
req.getContext().put("httpMethod","POST");
|
||||
req.getContext().put("path","/admin/authorization");
|
||||
o = new ContentStreamBase.ByteArrayStream(command.getBytes(StandardCharsets.UTF_8),"");
|
||||
req.setContentStreams(Collections.singletonList(o));
|
||||
rsp = new SolrQueryResponse();
|
||||
handler.handleRequestBody(req, rsp);
|
||||
authzconf = (Map) ((ConfigData) handler.m.get("/security.json")).data.get("authorization");
|
||||
permissions = (List<Map>) authzconf.get("permissions");
|
||||
|
||||
p = permissions.get(0);
|
||||
assertEquals("some-permission", p.get("name"));
|
||||
rol = (List) p.get("role");
|
||||
assertEquals( "guest", rol.get(0));
|
||||
assertEquals( "admin", rol.get(1));
|
||||
|
||||
|
||||
|
||||
command = "{\n" +
|
||||
"'delete-permission': 'some-permission',\n" +
|
||||
"'set-user-role':{'tom':null}\n" +
|
||||
|
@ -119,12 +162,15 @@ public class SecurityConfHandlerTest extends SolrTestCaseJ4 {
|
|||
authzconf = (Map) ((ConfigData) handler.m.get("/security.json")).data.get("authorization");
|
||||
userRoles = (Map) authzconf.get("user-role");
|
||||
assertEquals(0, userRoles.size());
|
||||
permissions = (Map) authzconf.get("permissions");
|
||||
permissions = (List<Map>) authzconf.get("permissions");
|
||||
assertEquals(1, permissions.size());
|
||||
assertNull(permissions.get("some-permission"));
|
||||
|
||||
for (Map permission : permissions) {
|
||||
assertFalse("some-permission".equals(permission.get("name")));
|
||||
}
|
||||
command = "{\n" +
|
||||
"'set-permission':{'name': 'security-edit',\n" +
|
||||
" 'method':'POST',"+ // security edit is a well-known permission , only role attribute should be provided
|
||||
" 'method':'POST',"+ // -ve test security edit is a well-known permission , only role attribute should be provided
|
||||
" 'role': 'admin'\n" +
|
||||
" }}";
|
||||
req = new LocalSolrQueryRequest(null, new ModifiableSolrParams());
|
||||
|
@ -136,7 +182,6 @@ public class SecurityConfHandlerTest extends SolrTestCaseJ4 {
|
|||
handler.handleRequestBody(req, rsp);
|
||||
List l = (List) ((Map) ((List)rsp.getValues().get("errorMessages")).get(0)).get("errorMessages");
|
||||
assertEquals(1, l.size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudCluster {
|
|||
r = cl.execute(httpPost);
|
||||
assertEquals(200, r.getStatusLine().getStatusCode());
|
||||
|
||||
verifySecurityStatus(cl, baseUrl+"/admin/authorization", "authorization/permissions/x-update/collection", "x", 20);
|
||||
verifySecurityStatus(cl, baseUrl+"/admin/authorization", "authorization/permissions[1]/collection", "x", 20);
|
||||
|
||||
}
|
||||
|
||||
|
@ -206,5 +206,5 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudCluster {
|
|||
" 'authorization':{\n" +
|
||||
" 'class':'solr.RuleBasedAuthorizationPlugin',\n" +
|
||||
" 'user-role':{'solr':'admin'},\n" +
|
||||
" 'permissions':{'security-edit':{'role':'admin'}}}}";
|
||||
" 'permissions':[{'name':'security-edit','role':'admin'}]}}";
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.solr.security;
|
|||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
@ -44,21 +45,18 @@ public class TestRuleBasedAuthorizationPlugin extends SolrTestCaseJ4 {
|
|||
" joe: [user]," +
|
||||
" noble:[dev,user]" +
|
||||
" }," +
|
||||
" permissions : {" +
|
||||
" schema-edit :{" +
|
||||
" role:admin" +
|
||||
" }," +
|
||||
" collection-admin-read :{" +
|
||||
" role:null" +
|
||||
" }," +
|
||||
" collection-admin-edit :{" +
|
||||
" role:admin" +
|
||||
" }," +
|
||||
" mycoll_update: {" +
|
||||
" permissions : [" +
|
||||
" {name:'schema-edit'," +
|
||||
" role:admin}," +
|
||||
" {name:'collection-admin-read'," +
|
||||
" role:null}," +
|
||||
" {name:collection-admin-edit ," +
|
||||
" role:admin}," +
|
||||
" {name:mycoll_update," +
|
||||
" collection:mycoll," +
|
||||
" path:'/update/*'," +
|
||||
" role:[dev,admin]" +
|
||||
" }}}" ;
|
||||
" }]}" ;
|
||||
Map initConfig = (Map) Utils.fromJSON(jsonRules.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
RuleBasedAuthorizationPlugin plugin= new RuleBasedAuthorizationPlugin();
|
||||
|
@ -97,6 +95,7 @@ public class TestRuleBasedAuthorizationPlugin extends SolrTestCaseJ4 {
|
|||
assertEquals(FORBIDDEN,authResp.statusCode);
|
||||
|
||||
values.put("resource","/admin/collections");
|
||||
values.put("collectionRequests",new ArrayList<>());
|
||||
values.put("params", new MapSolrParams(Collections.singletonMap("action", "LIST")));
|
||||
values.put("httpMethod","GET");
|
||||
authResp = plugin.authorize(context);
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Map;
|
|||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.common.util.Utils;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
|
@ -154,4 +155,26 @@ public class TestUtils extends SolrTestCaseJ4 {
|
|||
assertEquals( num, NumberUtils.SortableStr2long(sortable, 0, sortable.length() ) );
|
||||
assertEquals( Long.toString(num), NumberUtils.SortableStr2long(sortable) );
|
||||
}
|
||||
|
||||
public void testUtilsJSPath(){
|
||||
|
||||
String json = "{\n" +
|
||||
" 'authorization':{\n" +
|
||||
" 'class':'solr.RuleBasedAuthorizationPlugin',\n" +
|
||||
" 'user-role':{\n" +
|
||||
" 'solr':'admin',\n" +
|
||||
" 'harry':'admin'},\n" +
|
||||
" 'permissions':[{\n" +
|
||||
" 'name':'security-edit',\n" +
|
||||
" 'role':'admin'},\n" +
|
||||
" {\n" +
|
||||
" 'name':'x-update',\n" +
|
||||
" 'collection':'x',\n" +
|
||||
" 'path':'/update/*',\n" +
|
||||
" 'role':'dev'}],\n" +
|
||||
" '':{'v':4}}}";
|
||||
Map m = (Map) Utils.fromJSONString(json);
|
||||
assertEquals("x-update", Utils.getObjectByPath(m,false, "authorization/permissions[1]/name"));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.noggit.CharArr;
|
||||
|
@ -121,16 +123,37 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Object getObjectByPath(Map root, boolean onlyPrimitive, String hierarchy) {
|
||||
return getObjectByPath(root, onlyPrimitive, StrUtils.splitSmart(hierarchy, '/'));
|
||||
}
|
||||
|
||||
public static Object getObjectByPath(Map root, boolean onlyPrimitive, List<String> hierarchy) {
|
||||
Map obj = root;
|
||||
for (int i = 0; i < hierarchy.size(); i++) {
|
||||
int idx = -1;
|
||||
String s = hierarchy.get(i);
|
||||
if (s.endsWith("]")) {
|
||||
Matcher matcher = ARRAY_ELEMENT_INDEX.matcher(s);
|
||||
if (matcher.find()) {
|
||||
s = matcher.group(1);
|
||||
idx = Integer.parseInt(matcher.group(2));
|
||||
}
|
||||
}
|
||||
if (i < hierarchy.size() - 1) {
|
||||
if (!(obj.get(s) instanceof Map)) return null;
|
||||
obj = (Map) obj.get(s);
|
||||
if (obj == null) return null;
|
||||
Object o = obj.get(s);
|
||||
if (o == null) return null;
|
||||
if (idx > -1) {
|
||||
List l = (List) o;
|
||||
o = idx < l.size() ? l.get(idx) : null;
|
||||
}
|
||||
if (!(o instanceof Map)) return null;
|
||||
obj = (Map) o;
|
||||
} else {
|
||||
Object val = obj.get(s);
|
||||
if (idx > -1) {
|
||||
List l = (List) val;
|
||||
val = idx < l.size() ? l.get(idx) : null;
|
||||
}
|
||||
if (onlyPrimitive && val instanceof Map) {
|
||||
return null;
|
||||
}
|
||||
|
@ -140,4 +163,7 @@ public class Utils {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final Pattern ARRAY_ELEMENT_INDEX = Pattern
|
||||
.compile("(\\S*?)\\[(\\d+)\\]");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue