4444import java .util .List ;
4545import java .util .ListIterator ;
4646import java .util .Map ;
47+ import java .util .Map .Entry ;
4748import java .util .Properties ;
4849import java .util .Set ;
4950import java .util .StringTokenizer ;
@@ -611,7 +612,12 @@ public void addResource(Path file) {
611612 * The properties of this resource will override properties of previously
612613 * added resources, unless they were marked <a href="#Final">final</a>.
613614 *
614- * @param in InputStream to deserialize the object from.
615+ * WARNING: The contents of the InputStream will be cached, by this method.
616+ * So use this sparingly because it does increase the memory consumption.
617+ *
618+ * @param in InputStream to deserialize the object from. In will be read from
619+ * when a get or set is called next. After it is read the stream will be
620+ * closed.
615621 */
616622 public void addResource (InputStream in ) {
617623 addResourceObject (new Resource (in ));
@@ -1837,13 +1843,20 @@ private void loadResources(Properties properties,
18371843 }
18381844 }
18391845
1840- for (Resource resource : resources ) {
1841- loadResource (properties , resource , quiet );
1846+ for (int i = 0 ; i < resources .size (); i ++) {
1847+ Resource ret = loadResource (properties , resources .get (i ), quiet );
1848+ if (ret != null ) {
1849+ resources .set (i , ret );
1850+ }
18421851 }
18431852 }
18441853
1845- private void loadResource (Properties properties , Resource wrapper , boolean quiet ) {
1854+ private Resource loadResource (Properties properties , Resource wrapper , boolean quiet ) {
1855+ String name = UNKNOWN_RESOURCE ;
18461856 try {
1857+ Object resource = wrapper .getResource ();
1858+ name = wrapper .getName ();
1859+
18471860 DocumentBuilderFactory docBuilderFactory
18481861 = DocumentBuilderFactory .newInstance ();
18491862 //ignore all comments inside the xml file
@@ -1862,9 +1875,7 @@ private void loadResource(Properties properties, Resource wrapper, boolean quiet
18621875 DocumentBuilder builder = docBuilderFactory .newDocumentBuilder ();
18631876 Document doc = null ;
18641877 Element root = null ;
1865-
1866- Object resource = wrapper .getResource ();
1867- String name = wrapper .getName ();
1878+ boolean returnCachedProperties = false ;
18681879
18691880 if (resource instanceof URL ) { // an URL resource
18701881 URL url = (URL )resource ;
@@ -1901,22 +1912,29 @@ private void loadResource(Properties properties, Resource wrapper, boolean quiet
19011912 } else if (resource instanceof InputStream ) {
19021913 try {
19031914 doc = builder .parse ((InputStream )resource );
1915+ returnCachedProperties = true ;
19041916 } finally {
19051917 ((InputStream )resource ).close ();
19061918 }
1919+ } else if (resource instanceof Properties ) {
1920+ overlay (properties , (Properties )resource );
19071921 } else if (resource instanceof Element ) {
19081922 root = (Element )resource ;
19091923 }
19101924
19111925 if (doc == null && root == null ) {
19121926 if (quiet )
1913- return ;
1927+ return null ;
19141928 throw new RuntimeException (resource + " not found" );
19151929 }
19161930
19171931 if (root == null ) {
19181932 root = doc .getDocumentElement ();
19191933 }
1934+ Properties toAddTo = properties ;
1935+ if (returnCachedProperties ) {
1936+ toAddTo = new Properties ();
1937+ }
19201938 if (!"configuration" .equals (root .getTagName ()))
19211939 LOG .fatal ("bad conf file: top-level element not <configuration>" );
19221940 NodeList props = root .getChildNodes ();
@@ -1926,7 +1944,7 @@ private void loadResource(Properties properties, Resource wrapper, boolean quiet
19261944 continue ;
19271945 Element prop = (Element )propNode ;
19281946 if ("configuration" .equals (prop .getTagName ())) {
1929- loadResource (properties , new Resource (prop , name ), quiet );
1947+ loadResource (toAddTo , new Resource (prop , name ), quiet );
19301948 continue ;
19311949 }
19321950 if (!"property" .equals (prop .getTagName ()))
@@ -1959,32 +1977,43 @@ private void loadResource(Properties properties, Resource wrapper, boolean quiet
19591977 keyInfo .accessed = false ;
19601978 for (String key :keyInfo .newKeys ) {
19611979 // update new keys with deprecated key's value
1962- loadProperty (properties , name , key , value , finalParameter ,
1980+ loadProperty (toAddTo , name , key , value , finalParameter ,
19631981 source .toArray (new String [source .size ()]));
19641982 }
19651983 }
19661984 else {
1967- loadProperty (properties , name , attr , value , finalParameter ,
1985+ loadProperty (toAddTo , name , attr , value , finalParameter ,
19681986 source .toArray (new String [source .size ()]));
19691987 }
19701988 }
19711989 }
1972-
1990+
1991+ if (returnCachedProperties ) {
1992+ overlay (properties , toAddTo );
1993+ return new Resource (toAddTo , name );
1994+ }
1995+ return null ;
19731996 } catch (IOException e ) {
1974- LOG .fatal ("error parsing conf file: " + e );
1997+ LOG .fatal ("error parsing conf " + name , e );
19751998 throw new RuntimeException (e );
19761999 } catch (DOMException e ) {
1977- LOG .fatal ("error parsing conf file: " + e );
2000+ LOG .fatal ("error parsing conf " + name , e );
19782001 throw new RuntimeException (e );
19792002 } catch (SAXException e ) {
1980- LOG .fatal ("error parsing conf file: " + e );
2003+ LOG .fatal ("error parsing conf " + name , e );
19812004 throw new RuntimeException (e );
19822005 } catch (ParserConfigurationException e ) {
1983- LOG .fatal ("error parsing conf file: " + e );
2006+ LOG .fatal ("error parsing conf " + name , e );
19842007 throw new RuntimeException (e );
19852008 }
19862009 }
19872010
2011+ private void overlay (Properties to , Properties from ) {
2012+ for (Entry <Object , Object > entry : from .entrySet ()) {
2013+ to .put (entry .getKey (), entry .getValue ());
2014+ }
2015+ }
2016+
19882017 private void loadProperty (Properties properties , String name , String attr ,
19892018 String value , boolean finalParameter , String [] source ) {
19902019 if (value != null ) {
0 commit comments