merge -r 1359890:1359891 from trunk. FIXES: HADOOP-8573

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1359892 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Graves 2012-07-10 20:51:19 +00:00
parent 504353c259
commit 6d100d340c
3 changed files with 66 additions and 16 deletions

View File

@ -621,6 +621,9 @@ Release 0.23.3 - UNRELEASED
HADOOP-8129. ViewFileSystemTestSetup setupForViewFileSystem is erring HADOOP-8129. ViewFileSystemTestSetup setupForViewFileSystem is erring
(Ahmed Radwan and Ravi Prakash via bobby) (Ahmed Radwan and Ravi Prakash via bobby)
HADOOP-8573. Configuration tries to read from an inputstream resource
multiple times (Robert Evans via tgraves)
Release 0.23.2 - UNRELEASED Release 0.23.2 - UNRELEASED
NEW FEATURES NEW FEATURES

View File

@ -44,6 +44,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -611,7 +612,12 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
* The properties of this resource will override properties of previously * The properties of this resource will override properties of previously
* added resources, unless they were marked <a href="#Final">final</a>. * added resources, unless they were marked <a href="#Final">final</a>.
* *
* @param in InputStream to deserialize the object from. * WARNING: The contents of the InputStream will be cached, by this method.
* So use this sparingly because it does increase the memory consumption.
*
* @param in InputStream to deserialize the object from. In will be read from
* when a get or set is called next. After it is read the stream will be
* closed.
*/ */
public void addResource(InputStream in) { public void addResource(InputStream in) {
addResourceObject(new Resource(in)); addResourceObject(new Resource(in));
@ -1799,13 +1805,20 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
} }
} }
for (Resource resource : resources) { for (int i = 0; i < resources.size(); i++) {
loadResource(properties, resource, quiet); Resource ret = loadResource(properties, resources.get(i), quiet);
if (ret != null) {
resources.set(i, ret);
}
} }
} }
private void loadResource(Properties properties, Resource wrapper, boolean quiet) { private Resource loadResource(Properties properties, Resource wrapper, boolean quiet) {
String name = UNKNOWN_RESOURCE;
try { try {
Object resource = wrapper.getResource();
name = wrapper.getName();
DocumentBuilderFactory docBuilderFactory DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance(); = DocumentBuilderFactory.newInstance();
//ignore all comments inside the xml file //ignore all comments inside the xml file
@ -1824,9 +1837,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
DocumentBuilder builder = docBuilderFactory.newDocumentBuilder(); DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
Document doc = null; Document doc = null;
Element root = null; Element root = null;
boolean returnCachedProperties = false;
Object resource = wrapper.getResource();
String name = wrapper.getName();
if (resource instanceof URL) { // an URL resource if (resource instanceof URL) { // an URL resource
URL url = (URL)resource; URL url = (URL)resource;
@ -1863,22 +1874,29 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
} else if (resource instanceof InputStream) { } else if (resource instanceof InputStream) {
try { try {
doc = builder.parse((InputStream)resource); doc = builder.parse((InputStream)resource);
returnCachedProperties = true;
} finally { } finally {
((InputStream)resource).close(); ((InputStream)resource).close();
} }
} else if (resource instanceof Properties) {
overlay(properties, (Properties)resource);
} else if (resource instanceof Element) { } else if (resource instanceof Element) {
root = (Element)resource; root = (Element)resource;
} }
if (doc == null && root == null) { if (doc == null && root == null) {
if (quiet) if (quiet)
return; return null;
throw new RuntimeException(resource + " not found"); throw new RuntimeException(resource + " not found");
} }
if (root == null) { if (root == null) {
root = doc.getDocumentElement(); root = doc.getDocumentElement();
} }
Properties toAddTo = properties;
if(returnCachedProperties) {
toAddTo = new Properties();
}
if (!"configuration".equals(root.getTagName())) if (!"configuration".equals(root.getTagName()))
LOG.fatal("bad conf file: top-level element not <configuration>"); LOG.fatal("bad conf file: top-level element not <configuration>");
NodeList props = root.getChildNodes(); NodeList props = root.getChildNodes();
@ -1888,7 +1906,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
continue; continue;
Element prop = (Element)propNode; Element prop = (Element)propNode;
if ("configuration".equals(prop.getTagName())) { if ("configuration".equals(prop.getTagName())) {
loadResource(properties, new Resource(prop, name), quiet); loadResource(toAddTo, new Resource(prop, name), quiet);
continue; continue;
} }
if (!"property".equals(prop.getTagName())) if (!"property".equals(prop.getTagName()))
@ -1921,32 +1939,43 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
keyInfo.accessed = false; keyInfo.accessed = false;
for (String key:keyInfo.newKeys) { for (String key:keyInfo.newKeys) {
// update new keys with deprecated key's value // update new keys with deprecated key's value
loadProperty(properties, name, key, value, finalParameter, loadProperty(toAddTo, name, key, value, finalParameter,
source.toArray(new String[source.size()])); source.toArray(new String[source.size()]));
} }
} }
else { else {
loadProperty(properties, name, attr, value, finalParameter, loadProperty(toAddTo, name, attr, value, finalParameter,
source.toArray(new String[source.size()])); source.toArray(new String[source.size()]));
} }
} }
} }
if (returnCachedProperties) {
overlay(properties, toAddTo);
return new Resource(toAddTo, name);
}
return null;
} catch (IOException e) { } catch (IOException e) {
LOG.fatal("error parsing conf file: " + e); LOG.fatal("error parsing conf " + name, e);
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (DOMException e) { } catch (DOMException e) {
LOG.fatal("error parsing conf file: " + e); LOG.fatal("error parsing conf " + name, e);
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (SAXException e) { } catch (SAXException e) {
LOG.fatal("error parsing conf file: " + e); LOG.fatal("error parsing conf " + name, e);
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
LOG.fatal("error parsing conf file: " + e); LOG.fatal("error parsing conf " + name , e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private void overlay(Properties to, Properties from) {
for (Entry<Object, Object> entry: from.entrySet()) {
to.put(entry.getKey(), entry.getValue());
}
}
private void loadProperty(Properties properties, String name, String attr, private void loadProperty(Properties properties, String name, String attr,
String value, boolean finalParameter, String[] source) { String value, boolean finalParameter, String[] source) {
if (value != null) { if (value != null) {

View File

@ -18,10 +18,12 @@
package org.apache.hadoop.conf; package org.apache.hadoop.conf;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter; import java.io.StringWriter;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -78,6 +80,22 @@ public class TestConfiguration extends TestCase {
out.write("<xi:include href=\"" + filename + "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\" />\n "); out.write("<xi:include href=\"" + filename + "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\" />\n ");
} }
public void testInputStreamResource() throws Exception {
StringWriter writer = new StringWriter();
out = new BufferedWriter(writer);
startConfig();
declareProperty("prop", "A", "A");
endConfig();
InputStream in1 = new ByteArrayInputStream(writer.toString().getBytes());
Configuration conf = new Configuration(false);
conf.addResource(in1);
assertEquals("A", conf.get("prop"));
InputStream in2 = new ByteArrayInputStream(writer.toString().getBytes());
conf.addResource(in2);
assertEquals("A", conf.get("prop"));
}
public void testVariableSubstitution() throws IOException { public void testVariableSubstitution() throws IOException {
out=new BufferedWriter(new FileWriter(CONFIG)); out=new BufferedWriter(new FileWriter(CONFIG));
startConfig(); startConfig();