refactor path validation

This commit is contained in:
Mengyi Zhou 2016-05-23 15:51:21 +08:00
parent 46efea06bc
commit 932e392df2

View file

@ -87,7 +87,8 @@ public class DefaultGroupValidator implements GroupValidator {
throw new ValidationException("No virtual server is found bound to this group."); throw new ValidationException("No virtual server is found bound to this group.");
if (groupId == null) if (groupId == null)
groupId = 0L; groupId = 0L;
Map<Long, GroupVirtualServer> paths = new HashMap<>(); GroupVirtualServer dummy = new GroupVirtualServer();
Map<Long, GroupVirtualServer> addingGvs = new HashMap<>();
for (GroupVirtualServer gvs : groupVirtualServers) { for (GroupVirtualServer gvs : groupVirtualServers) {
if (gvs.getRewrite() != null && !gvs.getRewrite().isEmpty()) { if (gvs.getRewrite() != null && !gvs.getRewrite().isEmpty()) {
@ -100,75 +101,108 @@ public class DefaultGroupValidator implements GroupValidator {
if (!virtualServerModelValidator.exists(vs.getId())) { if (!virtualServerModelValidator.exists(vs.getId())) {
throw new ValidationException("Virtual server with id " + vs.getId() + " does not exist."); throw new ValidationException("Virtual server with id " + vs.getId() + " does not exist.");
} }
if (paths.containsKey(vs.getId())) { if (addingGvs.containsKey(vs.getId())) {
throw new ValidationException("Group and virtual server is an unique combination."); throw new ValidationException("Group and virtual server is an unique combination.");
} else {
addingGvs.put(vs.getId(), dummy);
} }
if (escapePathValidation) continue; if (escapePathValidation) {
if (gvs.getPath() == null || gvs.getPath().isEmpty()) {
throw new ValidationException("Path cannot be empty.");
}
List<String> pathValues = new ArrayList<>(2);
for (String pv : gvs.getPath().split(" ", 0)) {
if (pv.isEmpty()) continue;
if (pathValues.size() == 2) throw new ValidationException("Invalid path, too many whitespace modifiers is found.");
pathValues.add(pv);
}
if (pathValues.size() == 2) {
if (!pathPrefixModifier.contains(pathValues.get(0))) {
throw new ValidationException("Invalid path, invalid prefix modifier is found.");
}
// format path value
gvs.setPath(pathValues.get(0) + " " + pathValues.get(1));
}
String path = extractValue(gvs.getPath());
if (path.isEmpty()) {
paths.put(vs.getId(), new GroupVirtualServer().setPath(gvs.getPath()).setPriority(gvs.getPriority() == null ? -1000 : gvs.getPriority()));
continue; continue;
} else {
doPathValidationAndMapping(addingGvs, gvs);
} }
paths.put(vs.getId(), new GroupVirtualServer().setPath(path).setPriority(gvs.getPriority() == null ? 1000 : gvs.getPriority()));
} }
if (paths.size() == 0) return; if (escapePathValidation || addingGvs.size() == 0) return;
List<RelGroupVsDo> retainedGvs = rGroupVsDao.findAllByVses(addingGvs.keySet().toArray(new Long[addingGvs.size()]), RGroupVsEntity.READSET_FULL);
checkPathOverlappingAcrossVs(groupId, addingGvs, retainedGvs);
// reset priority after auto reorder
for (GroupVirtualServer e : groupVirtualServers) {
e.setPriority(addingGvs.get(e.getVirtualServer().getId()).getPriority());
}
}
@Override
public void validateGroupServers(List<GroupServer> groupServers) throws Exception {
groupServerModelValidator.validateGroupServers(groupServers);
}
private void doPathValidationAndMapping(Map<Long, GroupVirtualServer> mappingResult, GroupVirtualServer gvs) throws ValidationException {
if (gvs.getPath() == null || gvs.getPath().isEmpty()) {
throw new ValidationException("Path cannot be empty.");
}
List<String> pathValues = new ArrayList<>(2);
for (String pv : gvs.getPath().split(" ", 0)) {
if (pv.isEmpty()) continue;
if (pathValues.size() == 2) throw new ValidationException("Invalid path, too many whitespace modifiers is found.");
pathValues.add(pv);
}
if (pathValues.size() == 2) {
if (!pathPrefixModifier.contains(pathValues.get(0))) {
throw new ValidationException("Invalid path, invalid prefix modifier is found.");
}
// format path value
gvs.setPath(pathValues.get(0) + " " + pathValues.get(1));
}
String path = extractValue(gvs.getPath());
if (path.isEmpty()) {
mappingResult.put(gvs.getVirtualServer().getId(), new GroupVirtualServer().setPath(gvs.getPath()).setPriority(gvs.getPriority() == null ? -1000 : gvs.getPriority()));
} else {
mappingResult.put(gvs.getVirtualServer().getId(), new GroupVirtualServer().setPath(path).setPriority(gvs.getPriority() == null ? 1000 : gvs.getPriority()));
}
}
private void checkPathOverlappingAcrossVs(Long groupId, Map<Long, GroupVirtualServer> addingGvs, List<RelGroupVsDo> retainedGvs) throws ValidationException {
List<RelGroupVsDo> retained = new ArrayList<>(); List<RelGroupVsDo> retained = new ArrayList<>();
for (RelGroupVsDo d : rGroupVsDao.findAllByVses(paths.keySet().toArray(new Long[paths.size()]), RGroupVsEntity.READSET_FULL)) { for (RelGroupVsDo retainedEntry : retainedGvs) {
if (groupId.equals(d.getGroupId())) if (groupId.equals(retainedEntry.getGroupId()))
continue; continue;
if (d.getPriority() == 0) d.setPriority(1000); if (retainedEntry.getPriority() == 0) retainedEntry.setPriority(1000);
String value = d.getPath(); String retainedPath = retainedEntry.getPath();
try { try {
value = extractValue(d.getPath()); retainedPath = extractValue(retainedEntry.getPath());
} catch (ValidationException ex) { } catch (ValidationException ex) {
} }
GroupVirtualServer addingEntry = addingGvs.get(retainedEntry.getVsId());
if (addingEntry == null) {
throw new ValidationException("Unexpected path validation is reached. Related group and vs: " + groupId + ", " + retainedEntry.getVsId());
}
String addingPath = addingEntry.getPath();
try {
addingPath = extractValue(addingPath);
} catch (ValidationException ex) {
}
// check if root path is completely equivalent, otherwise escape comparing with root path // check if root path is completely equivalent, otherwise escape comparing with root path
GroupVirtualServer entry = paths.get(d.getVsId()); if (retainedPath.isEmpty() || addingPath.isEmpty()) {
if (value.isEmpty()) { if (retainedEntry.getPath().equals(addingEntry.getPath())) {
if (d.getPath().equals(entry.getPath())) { retained.add(retainedEntry);
retained.add(d);
} }
continue; continue;
} }
int ol = StringUtils.prefixOverlapped(entry.getPath(), value); int ol = StringUtils.prefixOverlapped(addingPath, retainedPath);
switch (ol) { switch (ol) {
case -1: case -1:
break; break;
case 0: case 0:
retained.add(d); retained.add(retainedEntry);
break; break;
case 1: case 1:
if (entry.getPriority() == null || entry.getPriority() <= d.getPriority()) { if (addingEntry.getPriority() == null || addingEntry.getPriority() <= retainedEntry.getPriority()) {
entry.setPriority(d.getPriority() + 100); addingEntry.setPriority(retainedEntry.getPriority() + 100);
} }
break; break;
case 2: case 2:
if (entry.getPriority() == null || entry.getPriority() >= d.getPriority()) { if (addingEntry.getPriority() == null || addingEntry.getPriority() >= retainedEntry.getPriority()) {
entry.setPriority(d.getPriority() - 100); addingEntry.setPriority(retainedEntry.getPriority() - 100);
} }
break; break;
default: default:
@ -183,15 +217,6 @@ public class DefaultGroupValidator implements GroupValidator {
} }
throw new ValidationException("Path is prefix-overlapped across virtual server " + sb.toString() + "."); throw new ValidationException("Path is prefix-overlapped across virtual server " + sb.toString() + ".");
} }
for (GroupVirtualServer e : groupVirtualServers) {
e.setPriority(paths.get(e.getVirtualServer().getId()).getPriority());
}
}
@Override
public void validateGroupServers(List<GroupServer> groupServers) throws Exception {
groupServerModelValidator.validateGroupServers(groupServers);
} }
private static String extractValue(String path) throws ValidationException { private static String extractValue(String path) throws ValidationException {