ch.cern.ZKTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cerndb-sw-zkpolicy Show documentation
Show all versions of cerndb-sw-zkpolicy Show documentation
zkpolicy - ZooKeeper Policy Auditing Tool
/*
* Copyright © 2020, CERN
* This software is distributed under the terms of the MIT Licence,
* copied verbatim in the file 'LICENSE'. In applying this licence,
* CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/
//CPD-OFF
package ch.cern;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoAuthException;
import org.apache.zookeeper.data.ACL;
/**
* Class that handles operations on the ZNode tree structure.
*/
public class ZKTree {
private ZKClient zk = null;
private String resetColor;
private String matchColor;
private String misMatchColor;
/**
* Create a ZKTree instance for traversal and query execution.
*
* @param zk A ZooKeeper instance that provides access to the ZNode tree
*/
public ZKTree(ZKClient zk) {
this.zk = zk;
this.resetColor = ZKPolicyDefs.Colors.valueOf("RESET").getANSIValue();
this.matchColor = ZKPolicyDefs.Colors.valueOf(zk.getZKPConfig().getMatchColor()).getANSIValue();
this.misMatchColor = ZKPolicyDefs.Colors.valueOf(zk.getZKPConfig().getMismatchColor()).getANSIValue();
}
/**
* Function to return a tree view of the selected sub-tree and execute queries.
*
* @param rootPath Path to start recursive query execution from
* @param queryElements List of queries to be executed on each node
* @param queriesOutput Output buffers for each query
* @throws KeeperException
* @throws InterruptedException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws NoSuchFieldException
*/
public void queryTree(String rootPath, List queryElements,
Hashtable> queriesOutput)
throws KeeperException, InterruptedException, NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
List invalidQueries = new ArrayList();
List parentYesChildNoQueries = new ArrayList();
for (ZKQueryElement zkQueryElement : queryElements) {
// validate root path requested:
try {
if (this.zk.exists(zkQueryElement.getRootPath(), null) == null) {
queriesOutput.get(zkQueryElement.hashCode())
.add("The path " + zkQueryElement.getRootPath() + " does not exist.");
invalidQueries.add(zkQueryElement);
continue;
}
} catch (IllegalArgumentException e) {
queriesOutput.get(zkQueryElement.hashCode())
.add("Invalid rootpath " + zkQueryElement.getRootPath() + " : " + e.getMessage());
invalidQueries.add(zkQueryElement);
continue;
}
if (zkQueryElement.getName().equals("parentYesChildNo")) {
this.queryTreeIntParentYesChildNo(zkQueryElement.getRootPath(), "", "", null, true, false, false, queriesOutput,
zkQueryElement);
parentYesChildNoQueries.add(zkQueryElement);
}
}
for (ZKQueryElement zkQueryElement : parentYesChildNoQueries) {
queryElements.remove(zkQueryElement);
}
for (ZKQueryElement zkQueryElement : invalidQueries) {
queryElements.remove(zkQueryElement);
}
if (queryElements.size() > 0) {
this.queryTreeIntPreOrder(rootPath, "", "", queryElements, true, false, false, queriesOutput);
}
}
/**
* Recursive function that parses the full ZNode tree and executes queries on each step.
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchFieldException
*/
private void queryTreeIntPreOrder(String path, String indent, String name, List queryElements,
boolean isQueryRoot, boolean isLast, boolean isParentLast, Hashtable> queriesOutput)
throws KeeperException, InterruptedException, NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException {
List children = null;
try {
children = this.zk.getChildren(path, null);
} catch (NoAuthException e) {
return;
}
List znodeACLList = this.zk.getACL(path, null);
Boolean isQueryRootSentinel = true;
// After we got the ACL, execute all the queries
for (ZKQueryElement zkQueryElement : queryElements) {
isQueryRootSentinel = false;
String znodePrintColor = "";
ZKQuery query = zkQueryElement.getQuery();
if (query.query(znodeACLList, null, path, this.zk, zkQueryElement.getArgs())) {
znodePrintColor = this.matchColor;
} else {
znodePrintColor = this.misMatchColor;
}
if (isQueryRoot) {
name = path.substring(1, path.length());
} else {
if (indent.length() > 0) {
if (isParentLast) {
indent = indent.substring(0, indent.length() - ZKPolicyDefs.TerminalConstants.indentStepLength)
+ ZKPolicyDefs.TerminalConstants.lastParentIndent;
} else {
indent = indent.substring(0, indent.length() - ZKPolicyDefs.TerminalConstants.indentStepLength)
+ ZKPolicyDefs.TerminalConstants.innerParentIndent;
}
}
if (isLast) {
indent += ZKPolicyDefs.TerminalConstants.lastChildIndent;
} else {
indent += ZKPolicyDefs.TerminalConstants.innerChildIndent;
}
}
queriesOutput.get(zkQueryElement.hashCode()).add(indent + znodePrintColor + "/" + name + this.resetColor);
}
if (path.equals("/")) {
path = "";
}
Collections.sort(children);
Iterator iterator = children.iterator();
while (iterator.hasNext()) {
String child = iterator.next();
this.queryTreeIntPreOrder(path + "/" + child, indent, child, queryElements, isQueryRootSentinel,
!iterator.hasNext(), isLast, queriesOutput);
}
}
/**
* Recursive function that constructs the full ZNode tree while passing parent
* ACL to child queries.
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchFieldException
*/
private void queryTreeIntParentYesChildNo(String path, String indent, String name, List parentACLList,
boolean isQueryRoot, boolean isLast, boolean isParentLast, Hashtable> queriesOutput,
ZKQueryElement queryElement) throws KeeperException, InterruptedException, NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
List children = null;
try {
children = this.zk.getChildren(path, null);
} catch (NoAuthException e) {
return;
}
String znodePrintColor = "";
List znodeACLList = this.zk.getACL(path, null);
ZKQuery query = queryElement.getQuery();
if (parentACLList == null || query.query(znodeACLList, parentACLList, path, this.zk, null)) {
znodePrintColor = this.matchColor;
} else {
znodePrintColor = this.misMatchColor;
}
parentACLList = this.zk.getACL(path, null);
if (path.equals("/")) {
path = "";
} else if (isQueryRoot) {
name = path.substring(1, path.length());
} else {
if (indent.length() > 0) {
if (isParentLast) {
indent = indent.substring(0, indent.length() - ZKPolicyDefs.TerminalConstants.indentStepLength)
+ ZKPolicyDefs.TerminalConstants.lastParentIndent;
} else {
indent = indent.substring(0, indent.length() - ZKPolicyDefs.TerminalConstants.indentStepLength)
+ ZKPolicyDefs.TerminalConstants.innerParentIndent;
}
}
if (isLast) {
indent += znodePrintColor + ZKPolicyDefs.TerminalConstants.lastChildIndent;
} else {
indent += znodePrintColor + ZKPolicyDefs.TerminalConstants.innerChildIndent;
}
}
queriesOutput.get(queryElement.hashCode()).add(indent + this.resetColor + "/" + name);
Collections.sort(children);
Iterator iterator = children.iterator();
while (iterator.hasNext()) {
String child = iterator.next();
this.queryTreeIntParentYesChildNo(path + "/" + child, indent, child, parentACLList, false, !iterator.hasNext(),
isLast, queriesOutput, queryElement);
}
}
/**
* Function to return a list of the selected sub-tree with the full path of
* query matching nodes.
*
* @param rootPath Path to start recursive query execution from
* @param queryElements List of queries to be executed on each node
* @param queriesOutput Output buffers for each query
* @throws KeeperException
* @throws InterruptedException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws NoSuchFieldException
*/
public void queryFind(String rootPath, List queryElements,
Hashtable> queriesOutput)
throws KeeperException, InterruptedException, NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
List invalidQueries = new ArrayList();
List parentYesChildNoQueries = new ArrayList();
for (ZKQueryElement zkQueryElement : queryElements) {
// validate root path requested:
try {
if (this.zk.exists(zkQueryElement.getRootPath(), null) == null) {
queriesOutput.get(zkQueryElement.hashCode())
.add("The path " + zkQueryElement.getRootPath() + " does not exist.");
invalidQueries.add(zkQueryElement);
continue;
}
} catch (IllegalArgumentException e) {
queriesOutput.get(zkQueryElement.hashCode())
.add("Invalid rootpath " + zkQueryElement.getRootPath() + " : " + e.getMessage());
invalidQueries.add(zkQueryElement);
continue;
}
if (zkQueryElement.getName().equals("parentYesChildNo")) {
this.queryFindIntParentYesChildNo(zkQueryElement.getRootPath(), null, queriesOutput, zkQueryElement);
parentYesChildNoQueries.add(zkQueryElement);
}
}
for (ZKQueryElement zkQueryElement : parentYesChildNoQueries) {
queryElements.remove(zkQueryElement);
}
for (ZKQueryElement zkQueryElement : invalidQueries) {
queryElements.remove(zkQueryElement);
}
if (queryElements.size() > 0) {
this.queryFindIntPreOrder(rootPath, queryElements, queriesOutput);
}
}
/**
* Recursive function that constructs the full ZNode tree, executes queries
* and outputs lines matching each one of them.
*
* @param queryElements List of queries to be executed on each node
* @param queriesOutput Output buffers for each query
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchFieldException
*/
private void queryFindIntPreOrder(String path, List queryElements,
Hashtable> queriesOutput) throws KeeperException, InterruptedException,
NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
List children = null;
try {
children = this.zk.getChildren(path, null);
} catch (NoAuthException e) {
for (ZKQueryElement zkQueryElement : queryElements) {
queriesOutput.get(zkQueryElement.hashCode())
.add("WARNING: No READ permission for " + path + ", skipping subtree");
}
return;
}
List znodeACLList = this.zk.getACL(path, null);
for (ZKQueryElement zkQueryElement : queryElements) {
ZKQuery query = zkQueryElement.getQuery();
if (query.query(znodeACLList, null, path, this.zk, zkQueryElement.getArgs())) {
queriesOutput.get(zkQueryElement.hashCode()).add(path);
}
}
if (path.equals("/")) {
path = "";
}
Collections.sort(children);
for (String child : children) {
this.queryFindIntPreOrder(path + "/" + child, queryElements, queriesOutput);
}
}
/**
* Recursive function that constructs the full ZNode tree, passing parent ACL to
* children queries.
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchFieldException
*/
private void queryFindIntParentYesChildNo(String path, List parentACLList,
Hashtable> queriesOutput, ZKQueryElement queryElement) throws KeeperException,
InterruptedException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
List children = null;
try {
children = this.zk.getChildren(path, null);
} catch (NoAuthException e) {
queriesOutput.get(queryElement.hashCode()).add("WARNING: No READ permission for " + path + ", skipping subtree");
return;
}
List znodeACLList = this.zk.getACL(path, null);
ZKQuery query = queryElement.getQuery();
if (parentACLList != null && !query.query(znodeACLList, parentACLList, path, this.zk, null)) {
queriesOutput.get(queryElement.hashCode()).add(path);
}
parentACLList = this.zk.getACL(path, null);
if (path.equals("/")) {
path = "";
}
Collections.sort(children);
for (String child : children) {
this.queryFindIntParentYesChildNo(path + "/" + child, parentACLList, queriesOutput, queryElement);
}
}
/**
* Return color code explanation for command line output.
*
* @return Hint for colors used in tree representation
*/
public String colorCodeExplanation() {
String explanation = "";
explanation += "* " + this.matchColor + this.zk.getZKPConfig().getMatchColor() + this.resetColor
+ ": znodes matching the query" + "\n";
explanation += "* " + this.misMatchColor + this.zk.getZKPConfig().getMismatchColor() + this.resetColor
+ ": znodes not matching the query" + "\n";
return explanation;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy