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 */ 018 019 package org.apache.hadoop.lib.util; 020 021 import org.apache.hadoop.classification.InterfaceAudience; 022 import org.apache.hadoop.conf.Configuration; 023 import org.w3c.dom.DOMException; 024 import org.w3c.dom.Document; 025 import org.w3c.dom.Element; 026 import org.w3c.dom.Node; 027 import org.w3c.dom.NodeList; 028 import org.w3c.dom.Text; 029 import org.xml.sax.SAXException; 030 031 import javax.xml.parsers.DocumentBuilder; 032 import javax.xml.parsers.DocumentBuilderFactory; 033 import javax.xml.parsers.ParserConfigurationException; 034 import java.io.IOException; 035 import java.io.InputStream; 036 import java.util.Map; 037 038 /** 039 * Configuration utilities. 040 */ 041 @InterfaceAudience.Private 042 public abstract class ConfigurationUtils { 043 044 /** 045 * Copy configuration key/value pairs from one configuration to another if a property exists in the target, it gets 046 * replaced. 047 * 048 * @param source source configuration. 049 * @param target target configuration. 050 */ 051 public static void copy(Configuration source, Configuration target) { 052 Check.notNull(source, "source"); 053 Check.notNull(target, "target"); 054 for (Map.Entry<String, String> entry : source) { 055 target.set(entry.getKey(), entry.getValue()); 056 } 057 } 058 059 /** 060 * Injects configuration key/value pairs from one configuration to another if the key does not exist in the target 061 * configuration. 062 * 063 * @param source source configuration. 064 * @param target target configuration. 065 */ 066 public static void injectDefaults(Configuration source, Configuration target) { 067 Check.notNull(source, "source"); 068 Check.notNull(target, "target"); 069 for (Map.Entry<String, String> entry : source) { 070 if (target.get(entry.getKey()) == null) { 071 target.set(entry.getKey(), entry.getValue()); 072 } 073 } 074 } 075 076 /** 077 * Returns a new ConfigurationUtils instance with all inline values resolved. 078 * 079 * @return a new ConfigurationUtils instance with all inline values resolved. 080 */ 081 public static Configuration resolve(Configuration conf) { 082 Configuration resolved = new Configuration(false); 083 for (Map.Entry<String, String> entry : conf) { 084 resolved.set(entry.getKey(), conf.get(entry.getKey())); 085 } 086 return resolved; 087 } 088 089 // Canibalized from FileSystemAccess <code>Configuration.loadResource()</code>. 090 091 /** 092 * Create a configuration from an InputStream. 093 * <p/> 094 * ERROR canibalized from <code>Configuration.loadResource()</code>. 095 * 096 * @param is inputstream to read the configuration from. 097 * 098 * @throws IOException thrown if the configuration could not be read. 099 */ 100 public static void load(Configuration conf, InputStream is) throws IOException { 101 try { 102 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 103 // ignore all comments inside the xml file 104 docBuilderFactory.setIgnoringComments(true); 105 DocumentBuilder builder = docBuilderFactory.newDocumentBuilder(); 106 Document doc = builder.parse(is); 107 parseDocument(conf, doc); 108 } catch (SAXException e) { 109 throw new IOException(e); 110 } catch (ParserConfigurationException e) { 111 throw new IOException(e); 112 } 113 } 114 115 // Canibalized from FileSystemAccess <code>Configuration.loadResource()</code>. 116 private static void parseDocument(Configuration conf, Document doc) throws IOException { 117 try { 118 Element root = doc.getDocumentElement(); 119 if (!"configuration".equals(root.getTagName())) { 120 throw new IOException("bad conf file: top-level element not <configuration>"); 121 } 122 NodeList props = root.getChildNodes(); 123 for (int i = 0; i < props.getLength(); i++) { 124 Node propNode = props.item(i); 125 if (!(propNode instanceof Element)) { 126 continue; 127 } 128 Element prop = (Element) propNode; 129 if (!"property".equals(prop.getTagName())) { 130 throw new IOException("bad conf file: element not <property>"); 131 } 132 NodeList fields = prop.getChildNodes(); 133 String attr = null; 134 String value = null; 135 for (int j = 0; j < fields.getLength(); j++) { 136 Node fieldNode = fields.item(j); 137 if (!(fieldNode instanceof Element)) { 138 continue; 139 } 140 Element field = (Element) fieldNode; 141 if ("name".equals(field.getTagName()) && field.hasChildNodes()) { 142 attr = ((Text) field.getFirstChild()).getData().trim(); 143 } 144 if ("value".equals(field.getTagName()) && field.hasChildNodes()) { 145 value = ((Text) field.getFirstChild()).getData(); 146 } 147 } 148 149 if (attr != null && value != null) { 150 conf.set(attr, value); 151 } 152 } 153 154 } catch (DOMException e) { 155 throw new IOException(e); 156 } 157 } 158 159 }