|
@@ -27,6 +27,7 @@ import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.io.OutputStream;
|
|
|
+import java.io.OutputStreamWriter;
|
|
|
import java.io.Reader;
|
|
|
import java.io.Writer;
|
|
|
import java.net.URL;
|
|
@@ -51,6 +52,7 @@ import javax.xml.parsers.DocumentBuilder;
|
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
import javax.xml.transform.Transformer;
|
|
|
+import javax.xml.transform.TransformerException;
|
|
|
import javax.xml.transform.TransformerFactory;
|
|
|
import javax.xml.transform.dom.DOMSource;
|
|
|
import javax.xml.transform.stream.StreamResult;
|
|
@@ -65,6 +67,7 @@ import org.apache.hadoop.util.ReflectionUtils;
|
|
|
import org.apache.hadoop.util.StringUtils;
|
|
|
import org.codehaus.jackson.JsonFactory;
|
|
|
import org.codehaus.jackson.JsonGenerator;
|
|
|
+import org.w3c.dom.Comment;
|
|
|
import org.w3c.dom.DOMException;
|
|
|
import org.w3c.dom.Document;
|
|
|
import org.w3c.dom.Element;
|
|
@@ -171,10 +174,10 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
new CopyOnWriteArrayList<String>();
|
|
|
|
|
|
/**
|
|
|
- * Flag to indicate if the storage of resource which updates a key needs
|
|
|
- * to be stored for each key
|
|
|
+ * The value reported as the setting resource when a key is set
|
|
|
+ * by code rather than a file resource.
|
|
|
*/
|
|
|
- private boolean storeResource;
|
|
|
+ static final String UNKNOWN_RESOURCE = "Unknown";
|
|
|
|
|
|
/**
|
|
|
* Stores the mapping of key to the resource which modifies or loads
|
|
@@ -223,27 +226,10 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
*/
|
|
|
public Configuration(boolean loadDefaults) {
|
|
|
this.loadDefaults = loadDefaults;
|
|
|
+ updatingResource = new HashMap<String, String>();
|
|
|
synchronized(Configuration.class) {
|
|
|
REGISTRY.put(this, null);
|
|
|
}
|
|
|
- this.storeResource = false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * A new configuration with the same settings and additional facility for
|
|
|
- * storage of resource to each key which loads or updates
|
|
|
- * the key most recently
|
|
|
- * @param other the configuration from which to clone settings
|
|
|
- * @param storeResource flag to indicate if the storage of resource to
|
|
|
- * each key is to be stored
|
|
|
- */
|
|
|
- private Configuration(Configuration other, boolean storeResource) {
|
|
|
- this(other);
|
|
|
- this.loadDefaults = other.loadDefaults;
|
|
|
- this.storeResource = storeResource;
|
|
|
- if (storeResource) {
|
|
|
- updatingResource = new HashMap<String, String>();
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -253,19 +239,22 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
*/
|
|
|
@SuppressWarnings("unchecked")
|
|
|
public Configuration(Configuration other) {
|
|
|
- this.resources = (ArrayList)other.resources.clone();
|
|
|
- synchronized(other) {
|
|
|
- if (other.properties != null) {
|
|
|
- this.properties = (Properties)other.properties.clone();
|
|
|
- }
|
|
|
-
|
|
|
- if (other.overlay!=null) {
|
|
|
- this.overlay = (Properties)other.overlay.clone();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ this.resources = (ArrayList) other.resources.clone();
|
|
|
+ synchronized (other) {
|
|
|
+ if (other.properties != null) {
|
|
|
+ this.properties = (Properties) other.properties.clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (other.overlay != null) {
|
|
|
+ this.overlay = (Properties) other.overlay.clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.updatingResource = new HashMap<String, String>(
|
|
|
+ other.updatingResource);
|
|
|
+ }
|
|
|
+
|
|
|
this.finalParameters = new HashSet<String>(other.finalParameters);
|
|
|
- synchronized(Configuration.class) {
|
|
|
+ synchronized (Configuration.class) {
|
|
|
REGISTRY.put(this, null);
|
|
|
}
|
|
|
}
|
|
@@ -429,6 +418,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
public void set(String name, String value) {
|
|
|
getOverlay().setProperty(name, value);
|
|
|
getProps().setProperty(name, value);
|
|
|
+ this.updatingResource.put(name, UNKNOWN_RESOURCE);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1055,10 +1045,8 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
loadResources(properties, resources, quietmode);
|
|
|
if (overlay!= null) {
|
|
|
properties.putAll(overlay);
|
|
|
- if (storeResource) {
|
|
|
- for (Map.Entry<Object,Object> item: overlay.entrySet()) {
|
|
|
- updatingResource.put((String) item.getKey(), "Unknown");
|
|
|
- }
|
|
|
+ for (Map.Entry<Object,Object> item: overlay.entrySet()) {
|
|
|
+ updatingResource.put((String) item.getKey(), UNKNOWN_RESOURCE);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1230,9 +1218,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
if (value != null) {
|
|
|
if (!finalParameters.contains(attr)) {
|
|
|
properties.setProperty(attr, value);
|
|
|
- if (storeResource) {
|
|
|
- updatingResource.put(attr, name.toString());
|
|
|
- }
|
|
|
+ updatingResource.put(attr, name.toString());
|
|
|
} else if (!value.equals(properties.getProperty(attr))) {
|
|
|
LOG.warn(name+":a attempt to override final parameter: "+attr
|
|
|
+"; Ignoring.");
|
|
@@ -1260,12 +1246,22 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Write out the non-default properties in this configuration to the give
|
|
|
+ * Write out the non-default properties in this configuration to the given
|
|
|
* {@link OutputStream}.
|
|
|
*
|
|
|
* @param out the output stream to write to.
|
|
|
*/
|
|
|
public void writeXml(OutputStream out) throws IOException {
|
|
|
+ writeXml(new OutputStreamWriter(out));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Write out the non-default properties in this configuration to the given
|
|
|
+ * {@link Writer}.
|
|
|
+ *
|
|
|
+ * @param out the writer to write to.
|
|
|
+ */
|
|
|
+ public synchronized void writeXml(Writer out) throws IOException {
|
|
|
Properties properties = getProps();
|
|
|
try {
|
|
|
Document doc =
|
|
@@ -1284,7 +1280,11 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
}
|
|
|
Element propNode = doc.createElement("property");
|
|
|
conf.appendChild(propNode);
|
|
|
-
|
|
|
+ if (updatingResource != null) {
|
|
|
+ Comment commentNode = doc.createComment("Loaded from "
|
|
|
+ + updatingResource.get(name));
|
|
|
+ propNode.appendChild(commentNode);
|
|
|
+ }
|
|
|
Element nameNode = doc.createElement("name");
|
|
|
nameNode.appendChild(doc.createTextNode(name));
|
|
|
propNode.appendChild(nameNode);
|
|
@@ -1301,8 +1301,10 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
TransformerFactory transFactory = TransformerFactory.newInstance();
|
|
|
Transformer transformer = transFactory.newTransformer();
|
|
|
transformer.transform(source, result);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
+ } catch (TransformerException te) {
|
|
|
+ throw new IOException(te);
|
|
|
+ } catch (ParserConfigurationException pe) {
|
|
|
+ throw new IOException(pe);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1317,26 +1319,26 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|
|
* @param out the Writer to write to
|
|
|
* @throws IOException
|
|
|
*/
|
|
|
- public static void dumpConfiguration(Configuration conf,
|
|
|
+ public static void dumpConfiguration(Configuration config,
|
|
|
Writer out) throws IOException {
|
|
|
- Configuration config = new Configuration(conf,true);
|
|
|
- config.reloadConfiguration();
|
|
|
JsonFactory dumpFactory = new JsonFactory();
|
|
|
JsonGenerator dumpGenerator = dumpFactory.createJsonGenerator(out);
|
|
|
dumpGenerator.writeStartObject();
|
|
|
dumpGenerator.writeFieldName("properties");
|
|
|
dumpGenerator.writeStartArray();
|
|
|
dumpGenerator.flush();
|
|
|
- for (Map.Entry<Object,Object> item: config.getProps().entrySet()) {
|
|
|
- dumpGenerator.writeStartObject();
|
|
|
- dumpGenerator.writeStringField("key", (String) item.getKey());
|
|
|
- dumpGenerator.writeStringField("value",
|
|
|
- config.get((String) item.getKey()));
|
|
|
- dumpGenerator.writeBooleanField("isFinal",
|
|
|
- config.finalParameters.contains(item.getKey()));
|
|
|
- dumpGenerator.writeStringField("resource",
|
|
|
- config.updatingResource.get(item.getKey()));
|
|
|
- dumpGenerator.writeEndObject();
|
|
|
+ synchronized (config) {
|
|
|
+ for (Map.Entry<Object,Object> item: config.getProps().entrySet()) {
|
|
|
+ dumpGenerator.writeStartObject();
|
|
|
+ dumpGenerator.writeStringField("key", (String) item.getKey());
|
|
|
+ dumpGenerator.writeStringField("value",
|
|
|
+ config.get((String) item.getKey()));
|
|
|
+ dumpGenerator.writeBooleanField("isFinal",
|
|
|
+ config.finalParameters.contains(item.getKey()));
|
|
|
+ dumpGenerator.writeStringField("resource",
|
|
|
+ config.updatingResource.get(item.getKey()));
|
|
|
+ dumpGenerator.writeEndObject();
|
|
|
+ }
|
|
|
}
|
|
|
dumpGenerator.writeEndArray();
|
|
|
dumpGenerator.writeEndObject();
|