Index: src/core/org/apache/hadoop/conf/ConfigurationIterator.java
===================================================================
--- src/core/org/apache/hadoop/conf/ConfigurationIterator.java	(revision 0)
+++ src/core/org/apache/hadoop/conf/ConfigurationIterator.java	(revision 0)
@@ -0,0 +1,60 @@
+/**
+ * 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.hadoop.conf;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/* pp */ class ConfigurationIterator
+		implements Iterator<Map.Entry<String,String>> {
+	private Configuration	self;
+	private Set<String>		seen;
+	private Iterator<Map.Entry<String,String>>
+							iterator;
+
+	public ConfigurationIterator(Configuration self) {
+		this.self = self;
+		this.seen = new HashSet<String>();
+		this.iterator = null;
+	}
+
+	public boolean hasNext() {
+		while (self != null) {
+			if (iterator == null)
+				iterator = self._getData().entrySet().iterator();
+			if (iterator.hasNext())
+				return true;
+			self = self.getParent();
+			iterator = null;
+		}
+		return false;
+	}
+
+	public Map.Entry<String,String> next() {
+		assert iterator != null : "Call hasNext first, please.";
+		return iterator.next();
+	}
+
+	public void remove() {
+		throw new UnsupportedOperationException();
+	}
+}
+
Index: src/core/org/apache/hadoop/conf/Configuration.java
===================================================================
--- src/core/org/apache/hadoop/conf/Configuration.java	(revision 767890)
+++ src/core/org/apache/hadoop/conf/Configuration.java	(working copy)
@@ -69,19 +69,41 @@
 import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 
-/** 
+/**
  * Provides access to configuration parameters.
  *
+ * A configuration consists of three layers:
+ * <ul>
+ * <li>The parent Configuration (specifies defaults)
+ * <li>The underlying resources
+ * <li>The explicit overlay values
+ * </ul>
+ *
+ * <p>Changes to the "default resources" will cause the parent
+ * Configuration to reload itself. This will not cause child
+ * configurations to reload themselves.
+ *
+ * <p>Changes to the resources in a Configuration will cause
+ * the Configuration to reload itself, and re-merge the overlay.
+ *
+ * <p>Changes to the data in a Configuration will modify the
+ * cached data _and_ the overlay.
+ *
+ * <p>Values are queried in the cached data, then the parent.
+ *
+ * <p>Explicit nulls will override (and hide) values from the
+ * parent.
+ *
  * <h4 id="Resources">Resources</h4>
  *
  * <p>Configurations are specified by resources. A resource contains a set of
- * name/value pairs as XML data. Each resource is named by either a 
- * <code>String</code> or by a {@link Path}. If named by a <code>String</code>, 
- * then the classpath is examined for a file with that name.  If named by a 
- * <code>Path</code>, then the local filesystem is examined directly, without 
+ * name/value pairs as XML data. Each resource is named by either a
+ * <code>String</code> or by a {@link Path}. If named by a <code>String</code>,
+ * then the classpath is examined for a file with that name.  If named by a
+ * <code>Path</code>, then the local filesystem is examined directly, without
  * referring to the classpath.
  *
- * <p>Unless explicitly turned off, Hadoop by default specifies two 
+ * <p>Unless explicitly turned off, Hadoop by default specifies two
  * resources, loaded in-order from the classpath: <ol>
  * <li><tt><a href="{@docRoot}/../core-default.html">core-default.xml</a>
  * </tt>: Read-only defaults for hadoop.</li>
@@ -90,12 +112,12 @@
  * </ol>
  * Applications may add additional resources, which are loaded
  * subsequent to these resources in the order they are added.
- * 
+ *
  * <h4 id="FinalParams">Final Parameters</h4>
  *
- * <p>Configuration parameters may be declared <i>final</i>. 
- * Once a resource declares a value final, no subsequently-loaded 
- * resource can alter that value.  
+ * <p>Configuration parameters may be declared <i>final</i>.
+ * Once a resource declares a value final, no subsequently-loaded
+ * resource can alter that value.
  * For example, one might define a final parameter with:
  * <tt><pre>
  *  &lt;property&gt;
@@ -104,7 +126,7 @@
  *    <b>&lt;final&gt;true&lt;/final&gt;</b>
  *  &lt;/property&gt;</pre></tt>
  *
- * Administrators typically define parameters as final in 
+ * Administrators typically define parameters as final in
  * <tt>core-site.xml</tt> for values that user applications may not alter.
  *
  * <h4 id="VariableExpansion">Variable Expansion</h4>
@@ -117,13 +139,13 @@
  * </ol>
  *
  * <p>For example, if a configuration resource contains the following property
- * definitions: 
+ * definitions:
  * <tt><pre>
  *  &lt;property&gt;
  *    &lt;name&gt;basedir&lt;/name&gt;
  *    &lt;value&gt;/user/${<i>user.name</i>}&lt;/value&gt;
  *  &lt;/property&gt;
- *  
+ *
  *  &lt;property&gt;
  *    &lt;name&gt;tempdir&lt;/name&gt;
  *    &lt;value&gt;${<i>basedir</i>}/tmp&lt;/value&gt;
@@ -133,140 +155,191 @@
  * will be resolved to another property in this Configuration, while
  * <tt>${<i>user.name</i>}</tt> would then ordinarily be resolved to the value
  * of the System property with that name.
+ *
+ * The synchronization on this object is external. Caveat user, and
+ * do not use this object as a lock or deadlocks may occur.
  */
+/*
+ * For those who are into serious multithreaded performance, note
+ * that accessing this class will serialize your memory accesses.
+ */
 public class Configuration implements Iterable<Map.Entry<String,String>>,
                                       Writable {
   private static final Log LOG =
     LogFactory.getLog(Configuration.class);
 
-  private boolean quietmode = true;
-  
+  /* Default Configuration is pointed to as a parent by all
+   * child Configurations which use the defaults. */
+
+  private static Configuration	DEFAULTS;
+
+  static {
+  	//print deprecation warning if hadoop-site.xml is found in classpath
+    ClassLoader cL = Thread.currentThread().getContextClassLoader();
+    if (cL == null) {
+      cL = Configuration.class.getClassLoader();
+    }
+    if (cL.getResource("hadoop-site.xml") != null) {
+      LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
+        "Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
+        + "mapred-site.xml and hdfs-site.xml to override properties of " +
+        "core-default.xml, mapred-default.xml and hdfs-default.xml " +
+        "respectively");
+    }
+    DEFAULTS = new Configuration(false);
+    DEFAULTS.addResource("core-default.xml");
+    DEFAULTS.addResource("core-site.xml");
+  }
+
   /**
+   * Add a default resource.
+   *
+   * Resources are loaded in the order of the resources added.
+   *
+   * @param name file name. File should be present in the classpath.
+   */
+  public static void addDefaultResource(String name) {
+    DEFAULTS.addResource(name);
+  }
+
+
+
+/* Instance work. */
+
+  private Configuration parent = null;
+
+  /**
    * List of configuration resources.
    */
-  private ArrayList<Object> resources = new ArrayList<Object>();
+  private List<Object>  resources;
 
   /**
-   * List of configuration parameters marked <b>final</b>. 
+   * ClassLoader from which to load configuration resources.
    */
-  private Set<String> finalParameters = new HashSet<String>();
-  
-  private boolean loadDefaults = true;
-  
+  private ClassLoader   classLoader;
+
   /**
-   * Configurtion objects
+   * Data loaded from configuration resources.
+   *
+   * This value serves as the lock for both itself and finalParameters.
    */
-  private static final WeakHashMap<Configuration,Object> REGISTRY = 
-    new WeakHashMap<Configuration,Object>();
-  
+  private Map<String,String>    properties;
+
   /**
-   * List of default Resources. Resources are loaded in the order of the list 
-   * entries
+   * Set of loaded configuration parameters marked <b>final</b>.
    */
-  private static final ArrayList<String> defaultResources = 
-    new ArrayList<String>();
-  
-  static{
-    //print deprecation warning if hadoop-site.xml is found in classpath
-    ClassLoader cL = Thread.currentThread().getContextClassLoader();
-    if (cL == null) {
-      cL = Configuration.class.getClassLoader();
-    }
-    if(cL.getResource("hadoop-site.xml")!=null) {
-      LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
-          "Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
-          + "mapred-site.xml and hdfs-site.xml to override properties of " +
-          "core-default.xml, mapred-default.xml and hdfs-default.xml " +
-          "respectively");
-    }
-    addDefaultResource("core-default.xml");
-    addDefaultResource("core-site.xml");
-  }
-  
-  private Properties properties;
-  private Properties overlay;
-  private ClassLoader classLoader;
-  {
+  private Set<String>           finalParameters;
+
+  /**
+   * Data explicitly set, which overrides configuration resources.
+   */
+  private Map<String,String>    overlay;
+
+  private boolean               quietmode;
+
+  /** A new configuration. */
+  public Configuration() {
+    if (LOG.isDebugEnabled())
+      LOG.debug(StringUtils.stringifyException(new IOException("config()")));
+    parent = DEFAULTS;
+    resources = new ArrayList<Object>();
     classLoader = Thread.currentThread().getContextClassLoader();
-    if (classLoader == null) {
+    if (classLoader == null)
       classLoader = Configuration.class.getClassLoader();
-    }
+    properties = null;  // Mark requiring reload.
+    finalParameters = null;
+    overlay = new HashMap<String,String>();
+    quietmode = true;
   }
-  
-  /** A new configuration. */
-  public Configuration() {
-    this(true);
-  }
 
-  /** A new configuration where the behavior of reading from the default 
+  /** A new configuration where the behavior of reading from the default
    * resources can be turned off.
-   * 
+   *
    * If the parameter {@code loadDefaults} is false, the new instance
-   * will not load resources from the default files. 
+   * will not load resources from the default files.
    * @param loadDefaults specifies whether to load from the default files
    */
   public Configuration(boolean loadDefaults) {
-    this.loadDefaults = loadDefaults;
-    if (LOG.isDebugEnabled()) {
-      LOG.debug(StringUtils.stringifyException(new IOException("config()")));
-    }
-    synchronized(Configuration.class) {
-      REGISTRY.put(this, null);
-    }
+    this();
+    if (loadDefaults)
+      this.parent = DEFAULTS;
+    else
+      this.parent = null;
   }
-  
-  /** 
+
+  /**
    * A new configuration with the same settings cloned from another.
-   * 
+   *
    * @param other the configuration from which to clone settings.
    */
   @SuppressWarnings("unchecked")
   public Configuration(Configuration other) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug(StringUtils.stringifyException
-                (new IOException("config(config)")));
-    }
-   
-   this.resources = (ArrayList)other.resources.clone();
-   synchronized(other) {
-     if (other.properties != null) {
-       this.properties = (Properties)other.properties.clone();
-     }
+    this();
 
-     if (other.overlay!=null) {
-       this.overlay = (Properties)other.overlay.clone();
-     }
-   }
-   
-    this.finalParameters = new HashSet<String>(other.finalParameters);
-    synchronized(Configuration.class) {
-      REGISTRY.put(this, null);
+    /* The synchronization on 'other' is external, so this makes us
+     * safe. Any value which is never modified after the constructor
+     * is allowed to be read outside the synchronization. Anything
+     * else must have a synchronized setter, and must be synchronized
+     * (currently externally) here. That sucks, but hey. Shevek. */
+
+    synchronized (other) {
+      this.classLoader = other.classLoader;
+      this.parent = other.parent;
+      this.resources.addAll(other.resources);
+      if (other.properties != null) {
+        /* There is a minor race here if someone modifies other between
+         * the call to properties and the call to finalParameters. */
+        this.properties = new HashMap<String,String>(other.properties);
+        this.finalParameters = new HashSet<String>(other.finalParameters);
+      }
+      this.overlay.putAll(other.overlay);
     }
   }
-  
+
+/* Field accessors. */
+
   /**
-   * Add a default resource. Resources are loaded in the order of the resources 
-   * added.
-   * @param name file name. File should be present in the classpath.
+   * Get the {@link ClassLoader} for this job.
+   *
+   * @return the correct class loader.
    */
-  public static synchronized void addDefaultResource(String name) {
-    if(!defaultResources.contains(name)) {
-      defaultResources.add(name);
-      for(Configuration conf : REGISTRY.keySet()) {
-        if(conf.loadDefaults) {
-          conf.reloadConfiguration();
-        }
-      }
-    }
+  public ClassLoader getClassLoader() {
+    return classLoader;
   }
 
   /**
-   * Add a configuration resource. 
-   * 
-   * The properties of this resource will override properties of previously 
-   * added resources, unless they were marked <a href="#Final">final</a>. 
-   * 
-   * @param name resource to be added, the classpath is examined for a file 
+   * Set the class loader that will be used to load the various objects.
+   *
+   * @param classLoader the new class loader.
+   */
+  public synchronized void setClassLoader(ClassLoader classLoader) {
+    this.classLoader = classLoader;
+  }
+
+  /**
+   * Set the quietness-mode.
+   *
+   * In the quiet-mode, error and informational messages might not be logged.
+   *
+   * @param quietmode <code>true</code> to set quiet-mode on, <code>false</code>
+   *              to turn it off.
+   */
+  public synchronized void setQuietMode(boolean quietmode) {
+    this.quietmode = quietmode;
+  }
+
+
+  /* pp */ Configuration getParent() {
+    return parent;
+  }
+
+  /**
+   * Add a configuration resource.
+   *
+   * The properties of this resource will override properties of previously
+   * added resources, unless they were marked <a href="#Final">final</a>.
+   *
+   * @param name resource to be added, the classpath is examined for a file
    *             with that name.
    */
   public void addResource(String name) {
@@ -274,13 +347,13 @@
   }
 
   /**
-   * Add a configuration resource. 
-   * 
-   * The properties of this resource will override properties of previously 
-   * added resources, unless they were marked <a href="#Final">final</a>. 
-   * 
-   * @param url url of the resource to be added, the local filesystem is 
-   *            examined directly to find the resource, without referring to 
+   * Add a configuration resource.
+   *
+   * The properties of this resource will override properties of previously
+   * added resources, unless they were marked <a href="#Final">final</a>.
+   *
+   * @param url url of the resource to be added, the local filesystem is
+   *            examined directly to find the resource, without referring to
    *            the classpath.
    */
   public void addResource(URL url) {
@@ -288,13 +361,13 @@
   }
 
   /**
-   * Add a configuration resource. 
-   * 
-   * The properties of this resource will override properties of previously 
-   * added resources, unless they were marked <a href="#Final">final</a>. 
-   * 
+   * Add a configuration resource.
+   *
+   * The properties of this resource will override properties of previously
+   * added resources, unless they were marked <a href="#Final">final</a>.
+   *
    * @param file file-path of resource to be added, the local filesystem is
-   *             examined directly to find the resource, without referring to 
+   *             examined directly to find the resource, without referring to
    *             the classpath.
    */
   public void addResource(Path file) {
@@ -302,39 +375,45 @@
   }
 
   /**
-   * Add a configuration resource. 
-   * 
-   * The properties of this resource will override properties of previously 
-   * added resources, unless they were marked <a href="#Final">final</a>. 
-   * 
-   * @param in InputStream to deserialize the object from. 
+   * Add a configuration resource.
+   *
+   * The properties of this resource will override properties of previously
+   * added resources, unless they were marked <a href="#Final">final</a>.
+   *
+   * @param in InputStream to deserialize the object from.
    */
   public void addResource(InputStream in) {
     addResourceObject(in);
   }
-  
-  
+
+
   /**
    * Reload configuration from previously added resources.
    *
-   * This method will clear all the configuration read from the added 
-   * resources, and final parameters. This will make the resources to 
+   * This method will clear all the configuration read from the added
+   * resources, and final parameters. This will make the resources to
    * be read again before accessing the values. Values that are added
    * via set methods will overlay values read from the resources.
    */
   public synchronized void reloadConfiguration() {
-    properties = null;                            // trigger reload
-    finalParameters.clear();                      // clear site-limits
+    properties = null;                    // trigger reload
+    finalParameters = null;               // clear site-limits
   }
-  
+
+  /* The synchronization protects the internal structure of the list
+   * from being messed up, in addition to the normal. If someone
+   * fixes this to use internal synchronization, remember to
+   * (re-)protect the list. */
   private synchronized void addResourceObject(Object resource) {
     resources.add(resource);                      // add to resources
     reloadConfiguration();
   }
-  
-  private static Pattern varPat = Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");
-  private static int MAX_SUBST = 20;
 
+  private static final Pattern varPat = Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");
+  private static final int MAX_SUBST = 20;
+
+  /* This must be called with the lock held, since it calls get(),
+   * and it might get an inconsistent view of the system. */
   private String substituteVars(String expr) {
     if (expr == null) {
       return null;
@@ -363,91 +442,180 @@
       // substitute
       eval = eval.substring(0, match.start())+val+eval.substring(match.end());
     }
-    throw new IllegalStateException("Variable substitution depth too large: " 
+    throw new IllegalStateException("Variable substitution depth too large: "
                                     + MAX_SUBST + " " + expr);
   }
-  
+
+/* Fundamental accessors. */
+
+  /* Called by ConfigurationIterator */
+  /* pp */ synchronized Map<String,String> _getData() {
+    /* Use atomicity of pointer-assignment. */
+    Map<String,String>    m = this.properties;
+    if (m == null) {
+      m = new HashMap<String,String>();
+      finalParameters = new HashSet<String>();
+      loadResources(m, resources, quietmode);
+      m.putAll(overlay);
+      /* We should not assign this earlier, or else:
+       * - If we have a sane granular synchronization strategy
+       * - then people who do not synchronize on the private lock
+       *   will try to read it before it is ready. */
+      properties = m;
+    }
+    return m;
+  }
+
   /**
-   * Get the value of the <code>name</code> property, <code>null</code> if
-   * no such property exists.
-   * 
-   * Values are processed for <a href="#VariableExpansion">variable expansion</a> 
-   * before being returned. 
-   * 
-   * @param name the property name.
-   * @return the value of the <code>name</code> property, 
-   *         or null if no such property exists.
+   * Return the number of keys in the configuration.
+   *
+   * @return number of keys in the configuration.
    */
-  public String get(String name) {
-    return substituteVars(getProps().getProperty(name));
+  public synchronized int size() {
+    Set<String>    keys = new HashSet<String>();
+    Configuration  self = this;
+    while (self != null) {
+      keys.addAll(self._getData().keySet());
+      self = self.parent;
+    }
+    return keys.size();
   }
 
   /**
+   * Get an {@link Iterator} to go through the list of <code>String</code>
+   * key-value pairs in the configuration.
+   *
+   * This isn't protected with synchronization. I hope we get
+   * an appropriate CME out of this; other things might go wrong.
+   *
+   * @return an iterator over the entries.
+   */
+  public synchronized Iterator<Map.Entry<String, String>> iterator() {
+    return new ConfigurationIterator(this);
+  }
+
+  /**
+   * Clears all keys from the configuration.
+   *
+   * This is fundamentally broken, because clearing the data cache
+   * will only stick until the underlying resources are reloaded.
+   *
+   * The only option is to redefine it as only clearing the overlay.
+   */
+  // @Deprecated  // I wish.
+  public synchronized void clear() {
+    /* XXX This ought to be done, really. I don't know whether the
+     * original documentation or the code was right. Ha.
+    parent = null;
+    resources.clear();
+    */
+    _getData().clear();
+    overlay.clear();
+  }
+
+  /**
    * Get the value of the <code>name</code> property, without doing
    * <a href="#VariableExpansion">variable expansion</a>.
-   * 
+   *
+   * The (external) synchronization protects the structure of the
+   * underlying Map.
+   *
    * @param name the property name.
-   * @return the value of the <code>name</code> property, 
+   * @return the value of the <code>name</code> property,
    *         or null if no such property exists.
    */
-  public String getRaw(String name) {
-    return getProps().getProperty(name);
+  public synchronized String getRaw(String name) {
+    Configuration    self = this;
+    Map<String,String>  m;
+    while (self != null) {
+      m = self._getData();
+      /* This might return null as an explicit value.
+       * This allows us to override a property set in the
+       * parent with an explicit null. */
+      synchronized (m) {
+        if (m.containsKey(name))
+          return m.get(name);
+      }
+      self = self.parent;
+    }
+    return null;
   }
 
-  /** 
+  /**
+   * Get the value of the <code>name</code> property, <code>null</code> if
+   * no such property exists.
+   *
+   * Values are processed for <a href="#VariableExpansion">variable expansion</a>
+   * before being returned.
+   *
+   * @param name the property name.
+   * @return the value of the <code>name</code> property,
+   *         or null if no such property exists.
+   */
+  /* For synchronization notes, see substituteVars. */
+  public synchronized String get(String name) {
+    return substituteVars(getRaw(name));
+  }
+
+  /**
    * Set the <code>value</code> of the <code>name</code> property.
-   * 
+   *
    * @param name property name.
    * @param value property value.
    */
-  public void set(String name, String value) {
-    getOverlay().setProperty(name, value);
-    getProps().setProperty(name, value);
+  public synchronized void set(String name, String value) {
+    Map<String,String>  m = _getData();
+    /* We must _getData() before we assume finalParameters != null. */
+    if (finalParameters.contains(name))
+      throw new IllegalArgumentException(
+        "Value for " + name + " is read-only."
+          );
+    m.put(name, value);
+    /* Save the mod in case we reload the underlying resources. */
+    overlay.put(name, value);
   }
-  
+
   /**
    * Sets a property if it is currently unset.
    * @param name the property name
    * @param value the new value
    */
-  public void setIfUnset(String name, String value) {
-    if (get(name) == null) {
+  public synchronized void setIfUnset(String name, String value) {
+    if (get(name) == null)
       set(name, value);
-    }
   }
-  
-  private synchronized Properties getOverlay() {
-    if (overlay==null){
-      overlay=new Properties();
-    }
-    return overlay;
-  }
 
-  /** 
-   * Get the value of the <code>name</code> property. If no such property 
+  /**
+   * Get the value of the <code>name</code> property. If no such property
    * exists, then <code>defaultValue</code> is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue default value.
-   * @return property value, or <code>defaultValue</code> if the property 
-   *         doesn't exist.                    
+   * @return property value, or <code>defaultValue</code> if the property
+   *         doesn't exist.
    */
-  public String get(String name, String defaultValue) {
-    return substituteVars(getProps().getProperty(name, defaultValue));
+  /* For synchronization notes, see substituteVars. */
+  public synchronized String get(String name, String defaultValue) {
+    String	value = get(name);
+    if (value == null)
+      value = defaultValue;
+    return substituteVars(value);
   }
-    
-  /** 
+
+  /**
    * Get the value of the <code>name</code> property as an <code>int</code>.
-   *   
+   *
    * If no such property exists, or if the specified value is not a valid
    * <code>int</code>, then <code>defaultValue</code> is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue default value.
-   * @return property value as an <code>int</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as an <code>int</code>,
+   *         or <code>defaultValue</code>.
    */
-  public int getInt(String name, int defaultValue) {
+  /* This method calls two subsidiary get()s so it must be
+   * synchronized. */
+  public synchronized int getInt(String name, int defaultValue) {
     String valueString = get(name);
     if (valueString == null)
       return defaultValue;
@@ -462,9 +630,9 @@
     }
   }
 
-  /** 
+  /**
    * Set the value of the <code>name</code> property to an <code>int</code>.
-   * 
+   *
    * @param name property name.
    * @param value <code>int</code> value of the property.
    */
@@ -473,15 +641,15 @@
   }
 
 
-  /** 
-   * Get the value of the <code>name</code> property as a <code>long</code>.  
+  /**
+   * Get the value of the <code>name</code> property as a <code>long</code>.
    * If no such property is specified, or if the specified value is not a valid
    * <code>long</code>, then <code>defaultValue</code> is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue default value.
-   * @return property value as a <code>long</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as a <code>long</code>,
+   *         or <code>defaultValue</code>.
    */
   public long getLong(String name, long defaultValue) {
     String valueString = get(name);
@@ -515,10 +683,10 @@
     }
     return null;
   }
-  
-  /** 
+
+  /**
    * Set the value of the <code>name</code> property to a <code>long</code>.
-   * 
+   *
    * @param name property name.
    * @param value <code>long</code> value of the property.
    */
@@ -526,15 +694,15 @@
     set(name, Long.toString(value));
   }
 
-  /** 
-   * Get the value of the <code>name</code> property as a <code>float</code>.  
+  /**
+   * Get the value of the <code>name</code> property as a <code>float</code>.
    * If no such property is specified, or if the specified value is not a valid
    * <code>float</code>, then <code>defaultValue</code> is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue default value.
-   * @return property value as a <code>float</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as a <code>float</code>,
+   *         or <code>defaultValue</code>.
    */
   public float getFloat(String name, float defaultValue) {
     String valueString = get(name);
@@ -548,23 +716,23 @@
   }
   /**
    * Set the value of the <code>name</code> property to a <code>float</code>.
-   * 
+   *
    * @param name property name.
    * @param value property value.
    */
   public void setFloat(String name, float value) {
     set(name,Float.toString(value));
   }
- 
-  /** 
-   * Get the value of the <code>name</code> property as a <code>boolean</code>.  
+
+  /**
+   * Get the value of the <code>name</code> property as a <code>boolean</code>.
    * If no such property is specified, or if the specified value is not a valid
    * <code>boolean</code>, then <code>defaultValue</code> is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue default value.
-   * @return property value as a <code>boolean</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as a <code>boolean</code>,
+   *         or <code>defaultValue</code>.
    */
   public boolean getBoolean(String name, boolean defaultValue) {
     String valueString = get(name);
@@ -575,9 +743,9 @@
     else return defaultValue;
   }
 
-  /** 
+  /**
    * Set the value of the <code>name</code> property to a <code>boolean</code>.
-   * 
+   *
    * @param name property name.
    * @param value <code>boolean</code> value of the property.
    */
@@ -595,10 +763,10 @@
   }
 
   /**
-   * A class that represents a set of positive integer ranges. It parses 
-   * strings of the form: "2-3,5,7-" where ranges are separated by comma and 
-   * the lower/upper bounds are separated by dash. Either the lower or upper 
-   * bound may be omitted meaning all values up to or over. So the string 
+   * A class that represents a set of positive integer ranges. It parses
+   * strings of the form: "2-3,5,7-" where ranges are separated by comma and
+   * the lower/upper bounds are separated by dash. Either the lower or upper
+   * bound may be omitted meaning all values up to or over. So the string
    * above means 2, 3, 5, and 7, 8, 9, ...
    */
   public static class IntegerRanges {
@@ -608,17 +776,17 @@
     }
 
     List<Range> ranges = new ArrayList<Range>();
-    
+
     public IntegerRanges() {
     }
-    
+
     public IntegerRanges(String newValue) {
       StringTokenizer itr = new StringTokenizer(newValue, ",");
       while (itr.hasMoreTokens()) {
         String rng = itr.nextToken().trim();
         String[] parts = rng.split("-", 3);
         if (parts.length < 1 || parts.length > 2) {
-          throw new IllegalArgumentException("integer range badly formed: " + 
+          throw new IllegalArgumentException("integer range badly formed: " +
                                              rng);
         }
         Range r = new Range();
@@ -629,7 +797,7 @@
           r.end = r.start;
         }
         if (r.start > r.end) {
-          throw new IllegalArgumentException("IntegerRange from " + r.start + 
+          throw new IllegalArgumentException("IntegerRange from " + r.start +
                                              " to " + r.end + " is invalid");
         }
         ranges.add(r);
@@ -663,7 +831,7 @@
       }
       return false;
     }
-    
+
     @Override
     public String toString() {
       StringBuffer result = new StringBuffer();
@@ -676,7 +844,8 @@
         }
         result.append(r.start);
         result.append('-');
-        result.append(r.end);
+        if (r.end != Integer.MAX_VALUE)
+          result.append(r.end);
       }
       return result.toString();
     }
@@ -692,44 +861,44 @@
     return new IntegerRanges(get(name, defaultValue));
   }
 
-  /** 
-   * Get the comma delimited values of the <code>name</code> property as 
-   * a collection of <code>String</code>s.  
+  /**
+   * Get the comma delimited values of the <code>name</code> property as
+   * a collection of <code>String</code>s.
    * If no such property is specified then empty collection is returned.
    * <p>
    * This is an optimized version of {@link #getStrings(String)}
-   * 
+   *
    * @param name property name.
-   * @return property value as a collection of <code>String</code>s. 
+   * @return property value as a collection of <code>String</code>s.
    */
   public Collection<String> getStringCollection(String name) {
     String valueString = get(name);
     return StringUtils.getStringCollection(valueString);
   }
 
-  /** 
-   * Get the comma delimited values of the <code>name</code> property as 
-   * an array of <code>String</code>s.  
+  /**
+   * Get the comma delimited values of the <code>name</code> property as
+   * an array of <code>String</code>s.
    * If no such property is specified then <code>null</code> is returned.
-   * 
+   *
    * @param name property name.
-   * @return property value as an array of <code>String</code>s, 
-   *         or <code>null</code>. 
+   * @return property value as an array of <code>String</code>s,
+   *         or <code>null</code>.
    */
   public String[] getStrings(String name) {
     String valueString = get(name);
     return StringUtils.getStrings(valueString);
   }
 
-  /** 
-   * Get the comma delimited values of the <code>name</code> property as 
-   * an array of <code>String</code>s.  
+  /**
+   * Get the comma delimited values of the <code>name</code> property as
+   * an array of <code>String</code>s.
    * If no such property is specified then default value is returned.
-   * 
+   *
    * @param name property name.
    * @param defaultValue The default value
-   * @return property value as an array of <code>String</code>s, 
-   *         or default value. 
+   * @return property value as an array of <code>String</code>s,
+   *         or default value.
    */
   public String[] getStrings(String name, String... defaultValue) {
     String valueString = get(name);
@@ -740,39 +909,42 @@
     }
   }
 
-  /** 
-   * Set the array of string values for the <code>name</code> property as 
-   * as comma delimited values.  
-   * 
+  /**
+   * Set the array of string values for the <code>name</code> property as
+   * as comma delimited values.
+   *
    * @param name property name.
    * @param values The values
    */
   public void setStrings(String name, String... values) {
     set(name, StringUtils.arrayToString(values));
   }
- 
+
   /**
    * Load a class by name.
-   * 
+   *
    * @param name the class name.
    * @return the class object.
    * @throws ClassNotFoundException if the class is not found.
    */
+  /* I have an opinion this should use Spring's ClassUtils, which
+   * can load things like int[] as a Class. I'm not sure how this
+   * flies with the Apache religion. Shevek. */
   public Class<?> getClassByName(String name) throws ClassNotFoundException {
     return Class.forName(name, true, classLoader);
   }
 
-  /** 
+  /**
    * Get the value of the <code>name</code> property
    * as an array of <code>Class</code>.
-   * The value of the property specifies a list of comma separated class names.  
-   * If no such property is specified, then <code>defaultValue</code> is 
+   * The value of the property specifies a list of comma separated class names.
+   * If no such property is specified, then <code>defaultValue</code> is
    * returned.
-   * 
+   *
    * @param name the property name.
    * @param defaultValue default value.
-   * @return property value as a <code>Class[]</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as a <code>Class[]</code>,
+   *         or <code>defaultValue</code>.
    */
   public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
     String[] classnames = getStrings(name);
@@ -789,15 +961,15 @@
     }
   }
 
-  /** 
-   * Get the value of the <code>name</code> property as a <code>Class</code>.  
-   * If no such property is specified, then <code>defaultValue</code> is 
+  /**
+   * Get the value of the <code>name</code> property as a <code>Class</code>.
+   * If no such property is specified, then <code>defaultValue</code> is
    * returned.
-   * 
+   *
    * @param name the class name.
    * @param defaultValue default value.
-   * @return property value as a <code>Class</code>, 
-   *         or <code>defaultValue</code>. 
+   * @return property value as a <code>Class</code>,
+   *         or <code>defaultValue</code>.
    */
   public Class<?> getClass(String name, Class<?> defaultValue) {
     String valueString = get(name);
@@ -810,24 +982,24 @@
     }
   }
 
-  /** 
+  /**
    * Get the value of the <code>name</code> property as a <code>Class</code>
    * implementing the interface specified by <code>xface</code>.
-   *   
-   * If no such property is specified, then <code>defaultValue</code> is 
+   *
+   * If no such property is specified, then <code>defaultValue</code> is
    * returned.
-   * 
+   *
    * An exception is thrown if the returned class does not implement the named
-   * interface. 
-   * 
+   * interface.
+   *
    * @param name the class name.
    * @param defaultValue default value.
    * @param xface the interface implemented by the named class.
-   * @return property value as a <code>Class</code>, 
+   * @return property value as a <code>Class</code>,
    *         or <code>defaultValue</code>.
    */
-  public <U> Class<? extends U> getClass(String name, 
-                                         Class<? extends U> defaultValue, 
+  public <U> Class<? extends U> getClass(String name,
+                                         Class<? extends U> defaultValue,
                                          Class<U> xface) {
     try {
       Class<?> theClass = getClass(name, defaultValue);
@@ -845,10 +1017,10 @@
   /**
    * Get the value of the <code>name</code> property as a <code>List</code>
    * of objects implementing the interface specified by <code>xface</code>.
-   * 
+   *
    * An exception is thrown if any of the classes does not exist, or if it does
    * not implement the named interface.
-   * 
+   *
    * @param name the property name.
    * @param xface the interface implemented by the classes named by
    *        <code>name</code>.
@@ -867,13 +1039,13 @@
     return ret;
   }
 
-  /** 
-   * Set the value of the <code>name</code> property to the name of a 
+  /**
+   * Set the value of the <code>name</code> property to the name of a
    * <code>theClass</code> implementing the given interface <code>xface</code>.
-   * 
-   * An exception is thrown if <code>theClass</code> does not implement the 
-   * interface <code>xface</code>. 
-   * 
+   *
+   * An exception is thrown if <code>theClass</code> does not implement the
+   * interface <code>xface</code>.
+   *
    * @param name property name.
    * @param theClass property value.
    * @param xface the interface implemented by the named class.
@@ -884,12 +1056,12 @@
     set(name, theClass.getName());
   }
 
-  /** 
+  /**
    * Get a local file under a directory named by <i>dirsProp</i> with
    * the given <i>path</i>.  If <i>dirsProp</i> contains multiple directories,
    * then one is chosen based on <i>path</i>'s hash code.  If the selected
    * directory does not exist, an attempt is made to create it.
-   * 
+   *
    * @param dirsProp directory in which to locate the file.
    * @param path file-path.
    * @return local file under the directory with the given path.
@@ -907,7 +1079,7 @@
         return file;
       }
     }
-    LOG.warn("Could not make " + path + 
+    LOG.warn("Could not make " + path +
              " in local directories from " + dirsProp);
     for(int i=0; i < dirs.length; i++) {
       int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;
@@ -916,12 +1088,12 @@
     throw new IOException("No valid local directories in property: "+dirsProp);
   }
 
-  /** 
+  /**
    * Get a local file name under a directory named in <i>dirsProp</i> with
    * the given <i>path</i>.  If <i>dirsProp</i> contains multiple directories,
    * then one is chosen based on <i>path</i>'s hash code.  If the selected
    * directory does not exist, an attempt is made to create it.
-   * 
+   *
    * @param dirsProp directory in which to locate the file.
    * @param path file-path.
    * @return local file under the directory with the given path.
@@ -941,20 +1113,20 @@
     throw new IOException("No valid local directories in property: "+dirsProp);
   }
 
-  /** 
+  /**
    * Get the {@link URL} for the named resource.
-   * 
+   *
    * @param name resource name.
    * @return the url for the named resource.
    */
   public URL getResource(String name) {
     return classLoader.getResource(name);
   }
-  
-  /** 
+
+  /**
    * Get an input stream attached to the configuration resource with the
    * given <code>name</code>.
-   * 
+   *
    * @param name configuration resource name.
    * @return an input stream attached to the resource.
    */
@@ -975,10 +1147,10 @@
     }
   }
 
-  /** 
+  /**
    * Get a {@link Reader} attached to the configuration resource with the
    * given <code>name</code>.
-   * 
+   *
    * @param name configuration resource name.
    * @return a reader attached to the resource.
    */
@@ -999,76 +1171,17 @@
     }
   }
 
-  protected synchronized Properties getProps() {
-    if (properties == null) {
-      properties = new Properties();
-      loadResources(properties, resources, quietmode);
-      if (overlay!= null)
-        properties.putAll(overlay);
-    }
-    return properties;
-  }
-
-  /**
-   * Return the number of keys in the configuration.
-   *
-   * @return number of keys in the configuration.
-   */
-  public int size() {
-    return getProps().size();
-  }
-
-  /**
-   * Clears all keys from the configuration.
-   */
-  public void clear() {
-    getProps().clear();
-    getOverlay().clear();
-  }
-
-  /**
-   * Get an {@link Iterator} to go through the list of <code>String</code> 
-   * key-value pairs in the configuration.
-   * 
-   * @return an iterator over the entries.
-   */
-  public Iterator<Map.Entry<String, String>> iterator() {
-    // Get a copy of just the string to string pairs. After the old object
-    // methods that allow non-strings to be put into configurations are removed,
-    // we could replace properties with a Map<String,String> and get rid of this
-    // code.
-    Map<String,String> result = new HashMap<String,String>();
-    for(Map.Entry<Object,Object> item: getProps().entrySet()) {
-      if (item.getKey() instanceof String && 
-          item.getValue() instanceof String) {
-        result.put((String) item.getKey(), (String) item.getValue());
-      }
-    }
-    return result.entrySet().iterator();
-  }
-
-  private void loadResources(Properties properties,
-                             ArrayList resources,
-                             boolean quiet) {
-    if(loadDefaults) {
-      for (String resource : defaultResources) {
-        loadResource(properties, resource, quiet);
-      }
-    
-      //support the hadoop-site.xml as a deprecated case
-      if(getResource("hadoop-site.xml")!=null) {
-        loadResource(properties, "hadoop-site.xml", quiet);
-      }
-    }
-    
+  private void loadResources(Map<String,String> properties,
+               List<Object> resources,
+               boolean quiet) {
     for (Object resource : resources) {
       loadResource(properties, resource, quiet);
     }
   }
 
-  private void loadResource(Properties properties, Object name, boolean quiet) {
+  private void loadResource(Map<String,String> properties, Object name, boolean quiet) {
     try {
-      DocumentBuilderFactory docBuilderFactory 
+      DocumentBuilderFactory docBuilderFactory
         = DocumentBuilderFactory.newInstance();
       //ignore all comments inside the xml file
       docBuilderFactory.setIgnoringComments(true);
@@ -1168,11 +1281,11 @@
           if ("final".equals(field.getTagName()) && field.hasChildNodes())
             finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
         }
-        
+
         // Ignore this parameter if it has already been marked as 'final'
         if (attr != null && value != null) {
           if (!finalParameters.contains(attr)) {
-            properties.setProperty(attr, value);
+            properties.put(attr, value);
             if (finalParameter)
               finalParameters.add(attr);
           } else {
@@ -1181,7 +1294,7 @@
           }
         }
       }
-        
+
     } catch (IOException e) {
       LOG.fatal("error parsing conf file: " + e);
       throw new RuntimeException(e);
@@ -1197,43 +1310,44 @@
     }
   }
 
-  /** 
+  /**
    * Write out the non-default properties in this configuration to the give
    * {@link OutputStream}.
-   * 
+   *
    * @param out the output stream to write to.
    */
   public void writeXml(OutputStream out) throws IOException {
-    Properties properties = getProps();
+    Map<String,String> properties = _getData();
     try {
       Document doc =
         DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
       Element conf = doc.createElement("configuration");
       doc.appendChild(conf);
       conf.appendChild(doc.createTextNode("\n"));
-      for (Enumeration e = properties.keys(); e.hasMoreElements();) {
-        String name = (String)e.nextElement();
-        Object object = properties.get(name);
-        String value = null;
-        if (object instanceof String) {
-          value = (String) object;
-        }else {
+      for (Map.Entry<String,String> e : properties.entrySet()) {
+        String name = e.getKey();
+        String value = e.getValue();
+        /* This reproduces the behaviour of the old system, but
+         * if we override a default property with a null value,
+         * perhaps we want that information preserved? */
+        if (value == null)
           continue;
-        }
         Element propNode = doc.createElement("property");
         conf.appendChild(propNode);
-      
+
         Element nameNode = doc.createElement("name");
         nameNode.appendChild(doc.createTextNode(name));
         propNode.appendChild(nameNode);
-      
-        Element valueNode = doc.createElement("value");
-        valueNode.appendChild(doc.createTextNode(value));
-        propNode.appendChild(valueNode);
 
+        if (value != null) {
+          Element valueNode = doc.createElement("value");
+          valueNode.appendChild(doc.createTextNode(value));
+          propNode.appendChild(valueNode);
+        }
+
         conf.appendChild(doc.createTextNode("\n"));
       }
-    
+
       DOMSource source = new DOMSource(doc);
       StreamResult result = new StreamResult(out);
       TransformerFactory transFactory = TransformerFactory.newInstance();
@@ -1244,58 +1358,75 @@
     }
   }
 
-  /**
-   * Get the {@link ClassLoader} for this job.
-   * 
-   * @return the correct class loader.
-   */
-  public ClassLoader getClassLoader() {
-    return classLoader;
+/* I assume that, as above, this is meant to handle non-default
+ * fields only. If it is to handle defaults as well, then there
+ * are two elegant ways to handle this:
+ *
+ * 1) A properties becomes a list of maps, the last one
+ *    having a length of zero, i.e.
+ * if (parent != null)
+ *	parent.write(out);
+ * else
+ *	WritableUtils.writeVInt(0);
+ *
+ * 2) Merge everything.
+ *
+ * I've done neither, since the semantics aren't clear, and the
+ * above documentation suggests that serialisation should transfer
+ * non-default fields only.
+ *
+ * If maintenance is performed here, finality of fields might also
+ * be preserved in a future version.
+ *
+ * -- Shevek
+ */
+
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    clear();
+    int size = WritableUtils.readVInt(in);
+    for(int i = 0; i < size; i++) {
+      set(org.apache.hadoop.io.Text.readString(in),
+        org.apache.hadoop.io.Text.readString(in));
+    }
   }
-  
-  /**
-   * Set the class loader that will be used to load the various objects.
-   * 
-   * @param classLoader the new class loader.
-   */
-  public void setClassLoader(ClassLoader classLoader) {
-    this.classLoader = classLoader;
+
+  @Override
+  public void write(DataOutput out) throws IOException {
+    Map<String,String> props = _getData();
+    WritableUtils.writeVInt(out, props.size());
+    for (Map.Entry<String, String> item : props.entrySet()) {
+      org.apache.hadoop.io.Text.writeString(out, item.getKey());
+      org.apache.hadoop.io.Text.writeString(out, item.getValue());
+    }
   }
-  
+
   @Override
   public String toString() {
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     sb.append("Configuration: ");
-    if(loadDefaults) {
-      toString(defaultResources, sb);
-      if(resources.size()>0) {
-        sb.append(", ");
-      }
-    }
-    toString(resources, sb);
+    toStringResources(sb);
     return sb.toString();
   }
 
-  private void toString(ArrayList resources, StringBuffer sb) {
-    ListIterator i = resources.listIterator();
-    while (i.hasNext()) {
-      if (i.nextIndex() != 0) {
+  private boolean toStringResources(StringBuilder sb) {
+    boolean  comma = false;
+    if (parent != null)
+      comma = parent.toStringResources(sb);
+    for (Object o : resources) {
+      if (comma)
         sb.append(", ");
-      }
-      sb.append(i.next());
+      sb.append(o);
+      comma = true;
     }
+    return comma;
   }
 
-  /** 
-   * Set the quietness-mode. 
-   * 
-   * In the quiet-mode, error and informational messages might not be logged.
-   * 
-   * @param quietmode <code>true</code> to set quiet-mode on, <code>false</code>
-   *              to turn it off.
-   */
-  public synchronized void setQuietMode(boolean quietmode) {
-    this.quietmode = quietmode;
+  public void dump() {
+    System.err.println("Configuration " + System.identityHashCode(this));
+    System.err.println("resources=" + resources);
+    System.err.println("properties=" + properties);
+    System.err.println("overlay=" + overlay);
   }
 
   /** For debugging.  List non-default properties to the terminal and exit. */
@@ -1303,24 +1434,4 @@
     new Configuration().writeXml(System.out);
   }
 
-  @Override
-  public void readFields(DataInput in) throws IOException {
-    clear();
-    int size = WritableUtils.readVInt(in);
-    for(int i=0; i < size; ++i) {
-      set(org.apache.hadoop.io.Text.readString(in), 
-          org.apache.hadoop.io.Text.readString(in));
-    }
-  }
-
-  //@Override
-  public void write(DataOutput out) throws IOException {
-    Properties props = getProps();
-    WritableUtils.writeVInt(out, props.size());
-    for(Map.Entry<Object, Object> item: props.entrySet()) {
-      org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());
-      org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());
-    }
-  }
-
 }
Index: src/test/org/apache/hadoop/conf/TestConfiguration.java
===================================================================
--- src/test/org/apache/hadoop/conf/TestConfiguration.java	(revision 767890)
+++ src/test/org/apache/hadoop/conf/TestConfiguration.java	(working copy)
@@ -177,11 +177,11 @@
     Configuration clone=new Configuration(conf);
     clone.addResource(new Path(CONFIG2));
     
-    assertEquals(clone.get("a"), "d"); 
-    assertEquals(clone.get("b"), "d"); 
-    assertEquals(clone.get("c"), "d"); 
-    assertEquals(clone.get("d"), "e"); 
-    assertEquals(clone.get("e"), "f"); 
+    assertEquals("d", clone.get("a"));
+    assertEquals("d", clone.get("b"));
+    assertEquals("d", clone.get("c"));
+    assertEquals("e", clone.get("d"));
+    assertEquals("f", clone.get("e"));
     
   }
   
@@ -232,7 +232,7 @@
       fileResource.toString();
     assertEquals(expectedOutput, conf.toString());
   }
-  
+
   public void testIncludes() throws Exception {
     tearDown();
     System.out.println("XXX testIncludes");
Index: src/test/org/apache/hadoop/conf/TestConfigurationSubclass.java
===================================================================
--- src/test/org/apache/hadoop/conf/TestConfigurationSubclass.java	(revision 767890)
+++ src/test/org/apache/hadoop/conf/TestConfigurationSubclass.java	(working copy)
@@ -32,17 +32,21 @@
 
   public void testGetProps() {
     SubConf conf = new SubConf(true);
-    Properties properties = conf.getProperties();
+    // Properties properties = conf.getProperties();
     assertNotNull("hadoop.tmp.dir is not set",
-            properties.getProperty("hadoop.tmp.dir"));
+            // properties.getProperty("hadoop.tmp.dir"));
+			conf.get("hadoop.tmp.dir"));
   }
 
   public void testReload() throws Throwable {
     SubConf conf = new SubConf(true);
     assertFalse(conf.isReloaded());
-    Configuration.addDefaultResource(EMPTY_CONFIGURATION_XML);
+	/* Shevek: This no longer causes a reload! (Good) */
+    // Configuration.addDefaultResource(EMPTY_CONFIGURATION_XML);
+	conf.addResource(EMPTY_CONFIGURATION_XML);
     assertTrue(conf.isReloaded());
-    Properties properties = conf.getProperties();
+    // Properties properties = conf.getProperties();
+	conf.get("hadoop.tmp.dir");
   }
 
   public void testReloadNotQuiet() throws Throwable {
@@ -52,7 +56,8 @@
     conf.addResource("not-a-valid-resource");
     assertTrue(conf.isReloaded());
     try {
-      Properties properties = conf.getProperties();
+      // Properties properties = conf.getProperties();
+		conf.get("hadoop.tmp.dir");
       fail("Should not have got here");
     } catch (RuntimeException e) {
       assertTrue(e.toString(),e.getMessage().contains("not found"));
@@ -76,9 +81,11 @@
       super(loadDefaults);
     }
 
+/*
     public Properties getProperties() {
       return super.getProps();
     }
+*/
 
     /**
      * {@inheritDoc}.
