001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security.visibility; 019 020import java.util.List; 021import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode; 022import org.apache.hadoop.hbase.security.visibility.expression.LeafExpressionNode; 023import org.apache.hadoop.hbase.security.visibility.expression.NonLeafExpressionNode; 024import org.apache.hadoop.hbase.security.visibility.expression.Operator; 025import org.apache.yetus.audience.InterfaceAudience; 026 027@InterfaceAudience.Private 028public class ExpressionExpander { 029 030 public ExpressionNode expand(ExpressionNode src) { 031 if (!src.isSingleNode()) { 032 NonLeafExpressionNode nlExp = (NonLeafExpressionNode) src; 033 List<ExpressionNode> childExps = nlExp.getChildExps(); 034 Operator outerOp = nlExp.getOperator(); 035 if (isToBeExpanded(childExps)) { 036 // Any of the child exp is a non leaf exp with & or | operator 037 NonLeafExpressionNode newNode = new NonLeafExpressionNode(nlExp.getOperator()); 038 for (ExpressionNode exp : childExps) { 039 if (exp.isSingleNode()) { 040 newNode.addChildExp(exp); 041 } else { 042 newNode.addChildExp(expand(exp)); 043 } 044 } 045 nlExp = expandNonLeaf(newNode, outerOp); 046 } 047 return nlExp; 048 } 049 if ( 050 src instanceof NonLeafExpressionNode 051 && ((NonLeafExpressionNode) src).getOperator() == Operator.NOT 052 ) { 053 // Negate the exp 054 return negate((NonLeafExpressionNode) src); 055 } 056 return src; 057 } 058 059 private ExpressionNode negate(NonLeafExpressionNode nlExp) { 060 ExpressionNode notChild = nlExp.getChildExps().get(0); 061 if (notChild instanceof LeafExpressionNode) { 062 return nlExp; 063 } 064 NonLeafExpressionNode nlNotChild = (NonLeafExpressionNode) notChild; 065 if (nlNotChild.getOperator() == Operator.NOT) { 066 // negate the negate 067 return nlNotChild.getChildExps().get(0); 068 } 069 Operator negateOp = nlNotChild.getOperator() == Operator.AND ? Operator.OR : Operator.AND; 070 NonLeafExpressionNode newNode = new NonLeafExpressionNode(negateOp); 071 for (ExpressionNode expNode : nlNotChild.getChildExps()) { 072 NonLeafExpressionNode negateNode = new NonLeafExpressionNode(Operator.NOT); 073 negateNode.addChildExp(expNode.deepClone()); 074 newNode.addChildExp(expand(negateNode)); 075 } 076 return newNode; 077 } 078 079 private boolean isToBeExpanded(List<ExpressionNode> childExps) { 080 for (ExpressionNode exp : childExps) { 081 if (!exp.isSingleNode()) { 082 return true; 083 } 084 } 085 return false; 086 } 087 088 private NonLeafExpressionNode expandNonLeaf(NonLeafExpressionNode newNode, Operator outerOp) { 089 // Now go for the merge or expansion across brackets 090 List<ExpressionNode> newChildExps = newNode.getChildExps(); 091 assert newChildExps.size() == 2; 092 ExpressionNode leftChild = newChildExps.get(0); 093 ExpressionNode rightChild = newChildExps.get(1); 094 if (rightChild.isSingleNode()) { 095 // Merge the single right node into the left side 096 assert leftChild instanceof NonLeafExpressionNode; 097 newNode = mergeChildNodes(newNode, outerOp, rightChild, (NonLeafExpressionNode) leftChild); 098 } else if (leftChild.isSingleNode()) { 099 // Merge the single left node into the right side 100 assert rightChild instanceof NonLeafExpressionNode; 101 newNode = mergeChildNodes(newNode, outerOp, leftChild, (NonLeafExpressionNode) rightChild); 102 } else { 103 // Both the child exp nodes are non single. 104 NonLeafExpressionNode leftChildNLE = (NonLeafExpressionNode) leftChild; 105 NonLeafExpressionNode rightChildNLE = (NonLeafExpressionNode) rightChild; 106 if (outerOp == leftChildNLE.getOperator() && outerOp == rightChildNLE.getOperator()) { 107 // Merge 108 NonLeafExpressionNode leftChildNLEClone = leftChildNLE.deepClone(); 109 leftChildNLEClone.addChildExps(rightChildNLE.getChildExps()); 110 newNode = leftChildNLEClone; 111 } else { 112 // (a | b) & (c & d) ... 113 if (outerOp == Operator.OR) { 114 // (a | b) | (c & d) 115 if ( 116 leftChildNLE.getOperator() == Operator.OR && rightChildNLE.getOperator() == Operator.AND 117 ) { 118 leftChildNLE.addChildExp(rightChildNLE); 119 newNode = leftChildNLE; 120 } else if ( 121 leftChildNLE.getOperator() == Operator.AND && rightChildNLE.getOperator() == Operator.OR 122 ) { 123 // (a & b) | (c | d) 124 rightChildNLE.addChildExp(leftChildNLE); 125 newNode = rightChildNLE; 126 } 127 // (a & b) | (c & d) 128 // This case no need to do any thing 129 } else { 130 // outer op is & 131 // (a | b) & (c & d) => (a & c & d) | (b & c & d) 132 if ( 133 leftChildNLE.getOperator() == Operator.OR && rightChildNLE.getOperator() == Operator.AND 134 ) { 135 newNode = new NonLeafExpressionNode(Operator.OR); 136 for (ExpressionNode exp : leftChildNLE.getChildExps()) { 137 NonLeafExpressionNode rightChildNLEClone = rightChildNLE.deepClone(); 138 rightChildNLEClone.addChildExp(exp); 139 newNode.addChildExp(rightChildNLEClone); 140 } 141 } else if ( 142 leftChildNLE.getOperator() == Operator.AND && rightChildNLE.getOperator() == Operator.OR 143 ) { 144 // (a & b) & (c | d) => (a & b & c) | (a & b & d) 145 newNode = new NonLeafExpressionNode(Operator.OR); 146 for (ExpressionNode exp : rightChildNLE.getChildExps()) { 147 NonLeafExpressionNode leftChildNLEClone = leftChildNLE.deepClone(); 148 leftChildNLEClone.addChildExp(exp); 149 newNode.addChildExp(leftChildNLEClone); 150 } 151 } else { 152 // (a | b) & (c | d) => (a & c) | (a & d) | (b & c) | (b & d) 153 newNode = new NonLeafExpressionNode(Operator.OR); 154 for (ExpressionNode leftExp : leftChildNLE.getChildExps()) { 155 for (ExpressionNode rightExp : rightChildNLE.getChildExps()) { 156 NonLeafExpressionNode newChild = new NonLeafExpressionNode(Operator.AND); 157 newChild.addChildExp(leftExp.deepClone()); 158 newChild.addChildExp(rightExp.deepClone()); 159 newNode.addChildExp(newChild); 160 } 161 } 162 } 163 } 164 } 165 } 166 return newNode; 167 } 168 169 private NonLeafExpressionNode mergeChildNodes(NonLeafExpressionNode newOuterNode, 170 Operator outerOp, ExpressionNode lChild, NonLeafExpressionNode nlChild) { 171 // Merge the single right/left node into the other side 172 if (nlChild.getOperator() == outerOp) { 173 NonLeafExpressionNode leftChildNLEClone = nlChild.deepClone(); 174 leftChildNLEClone.addChildExp(lChild); 175 newOuterNode = leftChildNLEClone; 176 } else if (outerOp == Operator.AND) { 177 assert nlChild.getOperator() == Operator.OR; 178 // outerOp is & here. We need to expand the node here 179 // (a | b) & c -> (a & c) | (b & c) 180 // OR 181 // c & (a | b) -> (c & a) | (c & b) 182 newOuterNode = new NonLeafExpressionNode(Operator.OR); 183 for (ExpressionNode exp : nlChild.getChildExps()) { 184 newOuterNode.addChildExp(new NonLeafExpressionNode(Operator.AND, exp, lChild)); 185 } 186 } 187 return newOuterNode; 188 } 189}