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