in oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java [201:329]
private boolean doExcludes(ChangeSet changeSet) {
if (changeSet.anyOverflow()) {
// in case of an overflow we could
// either try to still determine include/exclude based on non-overflown
// sets - or we can do a fail-stop and determine this as too complex
// to try-to-exclude, and just include
//TODO: optimize this later
return false;
}
if (changeSet.doesHitMaxPathDepth()) {
// then we might or might not include this - but without
// further complicated checks this can't be determined for sure
// so for simplicity reason just check first level include names
// if available
if (firstLevelIncludeNames == null) {
return false;
}
for (String parentPath : changeSet.getParentPaths()) {
String firstLevelName = firstLevelName(parentPath);
if (firstLevelName != null && firstLevelIncludeNames.contains(firstLevelName)) {
return false;
}
}
// none of the first level include names matched any parentPath
// we can safely exclude this change set
return true;
}
final Set<String> parentPaths = new HashSet<String>(changeSet.getParentPaths());
// first go through the unprecise excludes. if that has any hit,
// we have to let it pass as include
boolean unpreciseExclude = false;
if (this.unpreciseExcludePathPatterns.size() != 0) {
final Iterator<String> it = parentPaths.iterator();
while (it.hasNext()) {
final String aParentPath = it.next();
if (patternsMatch(this.unpreciseExcludePathPatterns, aParentPath)) {
// if there is an unprecise match we keep track of that fact
// for later in this method
unpreciseExclude = true;
break;
}
}
}
// first go through excludes to remove those that are explicitly
// excluded
if (this.excludePathPatterns.size() != 0) {
final Iterator<String> it = parentPaths.iterator();
while (it.hasNext()) {
final String aParentPath = it.next();
if (patternsMatch(this.excludePathPatterns, aParentPath)) {
// if an exclude pattern matches, remove the parentPath
it.remove();
}
}
}
// note that cut-off paths are not applied with excludes,
// eg if excludePaths contains /var/foo/bar and path contains /var/foo
// with a maxPathLevel of 2, that might very well mean that
// the actual path would have been /var/foo/bar, but we don't know.
// so we cannot exclude it here and thus have a potential false negative
// (ie we didn't exclude it in the prefilter)
// now remainingPaths contains what is not excluded,
// then check if it is included
boolean included = false;
for (String aPath : parentPaths) {
// direct set contains is fastest, lets try that first
if (this.rootIncludePaths.contains(aPath)) {
included = true;
break;
}
if (firstLevelIncludeNames != null) {
final String firstLevelName = firstLevelName(aPath);
if (firstLevelName != null && !firstLevelIncludeNames.contains(firstLevelName)) {
// then the 'first level name check' concluded that
// it's not in any include path - hence we can skip
// the (more expensive) pattern check
continue;
}
}
if (patternsMatch(this.includePathPatterns, aPath)) {
included = true;
break;
}
}
if (!included) {
// well then we can definitely say that this commit is excluded
return true;
} else if (unpreciseExclude) {
// then it might have been excluded but we are not sure
// in which case we return false (as that's safe always)
return false;
}
if (this.propertyNames != null && this.propertyNames.size() != 0) {
if (disjoint(changeSet.getPropertyNames(), this.propertyNames)) {
// if propertyNames are defined then if we can't find any
// at this stage (if !included) then this equals to filtering out
return true;
}
// otherwise we have found a match, but one of the
// nodeType/nodeNames
// could still filter out, so we have to continue...
}
if (this.parentNodeTypes != null && this.parentNodeTypes.size() != 0) {
if (disjoint(changeSet.getParentNodeTypes(), this.parentNodeTypes)) {
// same story here: if nodeTypes is defined and we can't find any
// match
// then we're done now
return true;
}
// otherwise, again, continue
}
if (this.parentNodeNames != null && this.parentNodeNames.size() != 0) {
// and a 3rd time, if we can't find any nodeName match
// here, then we're filtering out
if (disjoint(changeSet.getParentNodeNames(), this.parentNodeNames)) {
return true;
}
}
// at this stage we haven't found any exclude, so we're likely including
return false;
}