package azkaban.project; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import azkaban.utils.Props; /** * @author wkang * * This class manages project whitelist defined in xml config file. * An single xml config file contains different types of whitelisted * projects. For additional type of whitelist, modify WhitelistType enum. * * The xml config file should in the following format. Please note * the tag <MemoryCheck> is same as the defined enum MemoryCheck * * <ProjectWhitelist> * <MemoryCheck> * <project projectname="project1" /> * <project projectname="project2" /> * </MemoryCheck> * <ProjectWhitelist> * */ public class ProjectWhitelist { public static final String XML_FILE_PARAM = "project.whitelist.xml.file"; private static final String PROJECT_WHITELIST_TAG = "ProjectWhitelist"; private static final String PROJECT_TAG = "project"; private static final String PROJECTID_ATTR = "projectid"; private static AtomicReference<Map<WhitelistType, Set<Integer>>> projectsWhitelisted = new AtomicReference<Map<WhitelistType, Set<Integer>>>(); static void load(Props props) { String xmlFile = props.getString(XML_FILE_PARAM); parseXMLFile(xmlFile); } private static void parseXMLFile(String xmlFile) { File file = new File(xmlFile); if (!file.exists()) { throw new IllegalArgumentException("Project whitelist xml file " + xmlFile + " doesn't exist."); } // Creating the document builder to parse xml. DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = docBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new IllegalArgumentException( "Exception while parsing project whitelist xml. Document builder not created.", e); } Document doc = null; try { doc = builder.parse(file); } catch (SAXException e) { throw new IllegalArgumentException("Exception while parsing " + xmlFile + ". Invalid XML.", e); } catch (IOException e) { throw new IllegalArgumentException("Exception while parsing " + xmlFile + ". Error reading file.", e); } Map<WhitelistType, Set<Integer>> projsWhitelisted = new HashMap<WhitelistType, Set<Integer>>(); NodeList tagList = doc.getChildNodes(); if (!tagList.item(0).getNodeName().equals(PROJECT_WHITELIST_TAG)) { throw new RuntimeException("Cannot find tag '" + PROJECT_WHITELIST_TAG + "' in " + xmlFile); } NodeList whitelist = tagList.item(0).getChildNodes(); for (int n = 0; n < whitelist.getLength(); ++n) { if (whitelist.item(n).getNodeType() != Node.ELEMENT_NODE) { continue; } String whitelistType = whitelist.item(n).getNodeName(); Set<Integer> projs = new HashSet<Integer>(); NodeList projectsList = whitelist.item(n).getChildNodes(); for (int i = 0; i < projectsList.getLength(); ++i) { Node node = projectsList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals(PROJECT_TAG)) { parseProjectTag(node, projs); } } } projsWhitelisted.put(WhitelistType.valueOf(whitelistType), projs); } projectsWhitelisted.set(projsWhitelisted); } private static void parseProjectTag(Node node, Set<Integer> projects) { NamedNodeMap projectAttrMap = node.getAttributes(); Node projectIdAttr = projectAttrMap.getNamedItem(PROJECTID_ATTR); if (projectIdAttr == null) { throw new RuntimeException("Error loading project. The '" + PROJECTID_ATTR + "' attribute doesn't exist"); } String projectId = projectIdAttr.getNodeValue(); projects.add(Integer.parseInt(projectId)); } public static boolean isProjectWhitelisted(int project, WhitelistType whitelistType) { Map<WhitelistType, Set<Integer>> projsWhitelisted = projectsWhitelisted.get(); if (projsWhitelisted != null) { Set<Integer> projs = projsWhitelisted.get(whitelistType); if (projs != null) { return projs.contains(project); } } return false; } /** * The tag in the project whitelist xml config file should be same as * the defined enums. */ public static enum WhitelistType { MemoryCheck, NumJobPerFlow } }