/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.pig.validator; import java.util.Set; import org.apache.pig.PigConfiguration; import org.apache.pig.impl.PigContext; import org.apache.pig.impl.logicalLayer.FrontendException; import org.apache.pig.newplan.DepthFirstWalker; import org.apache.pig.newplan.OperatorPlan; import org.apache.pig.newplan.logical.relational.LOCogroup; import org.apache.pig.newplan.logical.relational.LOCross; import org.apache.pig.newplan.logical.relational.LOCube; import org.apache.pig.newplan.logical.relational.LODistinct; import org.apache.pig.newplan.logical.relational.LOFilter; import org.apache.pig.newplan.logical.relational.LOForEach; import org.apache.pig.newplan.logical.relational.LOGenerate; import org.apache.pig.newplan.logical.relational.LOInnerLoad; import org.apache.pig.newplan.logical.relational.LOJoin; import org.apache.pig.newplan.logical.relational.LOLimit; import org.apache.pig.newplan.logical.relational.LOLoad; import org.apache.pig.newplan.logical.relational.LONative; import org.apache.pig.newplan.logical.relational.LORank; import org.apache.pig.newplan.logical.relational.LOSort; import org.apache.pig.newplan.logical.relational.LOSplit; import org.apache.pig.newplan.logical.relational.LOSplitOutput; import org.apache.pig.newplan.logical.relational.LOStore; import org.apache.pig.newplan.logical.relational.LOStream; import org.apache.pig.newplan.logical.relational.LOUnion; import org.apache.pig.newplan.logical.relational.LogicalRelationalNodesVisitor; import org.apache.pig.newplan.logical.rules.LogicalRelationalNodeValidator; import com.google.common.base.Splitter; import com.google.common.collect.Sets; /** * This validator walks through the list of operators defined in {@link PigConfiguration#PIG_BLACKLIST} and * {@link PigConfiguration#PIG_WHITELIST} and checks whether the operation is permitted. In case these * properties are not defined (default), we let everything pass as usual. * */ public final class BlackAndWhitelistValidator implements LogicalRelationalNodeValidator { private final PigContext pigContext; private final OperatorPlan operatorPlan; public BlackAndWhitelistValidator(PigContext pigContext, OperatorPlan operatorPlan) { this.pigContext = pigContext; this.operatorPlan = operatorPlan; } public void validate() throws FrontendException { BlackAndWhitelistVisitor visitor = new BlackAndWhitelistVisitor(this.operatorPlan); visitor.visit(); } private class BlackAndWhitelistVisitor extends LogicalRelationalNodesVisitor { private static final int ERROR_CODE = 1855; private final Splitter splitter; private final Set<String> blacklist; private final Set<String> whitelist; protected BlackAndWhitelistVisitor(OperatorPlan plan) throws FrontendException { super(plan, new DepthFirstWalker(plan)); blacklist = Sets.newHashSet(); whitelist = Sets.newHashSet(); splitter = Splitter.on(',').trimResults().omitEmptyStrings(); init(); } private void init() { String blacklistConfig = pigContext.getProperties().getProperty(PigConfiguration.PIG_BLACKLIST); // Set blacklist only if it's been defined by a user if (blacklistConfig != null) { Iterable<String> iter = splitter.split(blacklistConfig); for(String elem : iter) { blacklist.add(elem.toLowerCase()); } } String whitelistConfig = pigContext.getProperties().getProperty(PigConfiguration.PIG_WHITELIST); // Set whitelist only if it's been defined by a user if (whitelistConfig != null) { Iterable<String> iter = splitter.split(whitelistConfig); for(String elem : iter) { String lElem = elem.toLowerCase(); if(blacklist.contains(lElem)) { throw new IllegalStateException("Conflict between whitelist and blacklist. '"+elem+"' appears in both."); } whitelist.add(lElem); } } } private void check(String operator) throws FrontendException { // throw an exception if the operator is not defined in whitelist if(whitelist != null && whitelist.size() > 0 && !whitelist.contains(operator)) { throw new FrontendException(operator +" is disabled. ", ERROR_CODE); } // throw an exception if operator is defined in blacklist if(blacklist != null && blacklist.size() > 0 && blacklist.contains(operator)) { throw new FrontendException(operator + " is disabled. ", ERROR_CODE); } } @Override public void visit(LOLoad load) throws FrontendException { check("load"); } @Override public void visit(LOFilter filter) throws FrontendException { check("filter"); } @Override public void visit(LOStore store) throws FrontendException { check("store"); } @Override public void visit(LOJoin join) throws FrontendException { check("join"); } @Override public void visit(LOForEach foreach) throws FrontendException { check("foreach"); } @Override public void visit(LOGenerate gen) throws FrontendException { } public void visit(LOInnerLoad load) throws FrontendException { } @Override public void visit(LOCube cube) throws FrontendException { check("cube"); } public void visit(LOCogroup loCogroup) throws FrontendException { check("group"); check("cogroup"); } @Override public void visit(LOSplit loSplit) throws FrontendException { check("split"); } @Override public void visit(LOSplitOutput loSplitOutput) throws FrontendException { } @Override public void visit(LOUnion loUnion) throws FrontendException { check("union"); } @Override public void visit(LOSort loSort) throws FrontendException { check("order"); } @Override public void visit(LORank loRank) throws FrontendException { check("rank"); } @Override public void visit(LODistinct loDistinct) throws FrontendException { check("distinct"); } @Override public void visit(LOLimit loLimit) throws FrontendException { check("limit"); } @Override public void visit(LOCross loCross) throws FrontendException { check("cross"); } @Override public void visit(LOStream loStream) throws FrontendException { check("stream"); } @Override public void visit(LONative nativeMR) throws FrontendException { check("mapreduce"); } } }