@@ -1588,52 +1588,67 @@ public void writeXml(OutputStream out) throws IOException {
15881588 *
15891589 * @param out the writer to write to.
15901590 */
1591- public synchronized void writeXml (Writer out ) throws IOException {
1591+ public void writeXml (Writer out ) throws IOException {
1592+ Document doc = asXmlDocument ();
1593+
15921594 Properties properties = getProps ();
15931595 try {
1594- Document doc =
1595- DocumentBuilderFactory .newInstance ().newDocumentBuilder ().newDocument ();
1596- Element conf = doc .createElement ("configuration" );
1597- doc .appendChild (conf );
1598- conf .appendChild (doc .createTextNode ("\n " ));
1599- for (Enumeration e = properties .keys (); e .hasMoreElements ();) {
1600- String name = (String )e .nextElement ();
1601- Object object = properties .get (name );
1602- String value = null ;
1603- if (object instanceof String ) {
1604- value = (String ) object ;
1605- }else {
1606- continue ;
1607- }
1608- Element propNode = doc .createElement ("property" );
1609- conf .appendChild (propNode );
1610-
1611- if (updatingResource != null ) {
1612- Comment commentNode = doc .createComment (
1613- "Loaded from " + updatingResource .get (name ));
1614- propNode .appendChild (commentNode );
1615- }
1616- Element nameNode = doc .createElement ("name" );
1617- nameNode .appendChild (doc .createTextNode (name ));
1618- propNode .appendChild (nameNode );
1619-
1620- Element valueNode = doc .createElement ("value" );
1621- valueNode .appendChild (doc .createTextNode (value ));
1622- propNode .appendChild (valueNode );
1623-
1624- conf .appendChild (doc .createTextNode ("\n " ));
1625- }
1626-
16271596 DOMSource source = new DOMSource (doc );
16281597 StreamResult result = new StreamResult (out );
16291598 TransformerFactory transFactory = TransformerFactory .newInstance ();
16301599 Transformer transformer = transFactory .newTransformer ();
1600+
1601+ // Important to not hold Configuration log while writing result, since
1602+ // 'out' may be an HDFS stream which needs to lock this configuration
1603+ // from another thread.
16311604 transformer .transform (source , result );
16321605 } catch (TransformerException te ) {
16331606 throw new IOException (te );
1607+ }
1608+ }
1609+
1610+ /**
1611+ * Return the XML DOM corresponding to this Configuration.
1612+ */
1613+ private synchronized Document asXmlDocument () throws IOException {
1614+ Document doc ;
1615+ try {
1616+ doc =
1617+ DocumentBuilderFactory .newInstance ().newDocumentBuilder ().newDocument ();
16341618 } catch (ParserConfigurationException pe ) {
16351619 throw new IOException (pe );
16361620 }
1621+ Element conf = doc .createElement ("configuration" );
1622+ doc .appendChild (conf );
1623+ conf .appendChild (doc .createTextNode ("\n " ));
1624+ for (Enumeration e = properties .keys (); e .hasMoreElements ();) {
1625+ String name = (String )e .nextElement ();
1626+ Object object = properties .get (name );
1627+ String value = null ;
1628+ if (object instanceof String ) {
1629+ value = (String ) object ;
1630+ }else {
1631+ continue ;
1632+ }
1633+ Element propNode = doc .createElement ("property" );
1634+ conf .appendChild (propNode );
1635+
1636+ if (updatingResource != null ) {
1637+ Comment commentNode = doc .createComment (
1638+ "Loaded from " + updatingResource .get (name ));
1639+ propNode .appendChild (commentNode );
1640+ }
1641+ Element nameNode = doc .createElement ("name" );
1642+ nameNode .appendChild (doc .createTextNode (name ));
1643+ propNode .appendChild (nameNode );
1644+
1645+ Element valueNode = doc .createElement ("value" );
1646+ valueNode .appendChild (doc .createTextNode (value ));
1647+ propNode .appendChild (valueNode );
1648+
1649+ conf .appendChild (doc .createTextNode ("\n " ));
1650+ }
1651+ return doc ;
16371652 }
16381653
16391654 /**
0 commit comments