killbill-developers

Refactoring multi-versioned catalog to improve File/URI/URL/Stream

11/19/2011 11:15:52 PM

Details

diff --git a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
index 3d02d70..9b09f31 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
@@ -20,9 +20,7 @@ import org.skife.config.ConfigurationObjectFactory;
 
 import com.google.inject.AbstractModule;
 import com.ning.billing.catalog.CatalogService;
-import com.ning.billing.catalog.CatalogUserApi;
 import com.ning.billing.catalog.api.ICatalogService;
-import com.ning.billing.catalog.api.ICatalogUserApi;
 import com.ning.billing.catalog.io.ICatalogLoader;
 import com.ning.billing.catalog.io.VersionedCatalogLoader;
 import com.ning.billing.config.ICatalogConfig;
@@ -35,7 +33,6 @@ public class CatalogModule extends AbstractModule {
     }
 
     protected void installCatalog() {
-        bind(ICatalogUserApi.class).to(CatalogUserApi.class).asEagerSingleton();
         bind(ICatalogService.class).to(CatalogService.class).asEagerSingleton();
         bind(ICatalogLoader.class).to(VersionedCatalogLoader.class).asEagerSingleton();
     }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
index 9c1aaf9..52f92ef 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
@@ -16,35 +16,19 @@
 
 package com.ning.billing.catalog.io;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
-import org.xml.sax.SAXException;
 
 import com.google.inject.Inject;
 import com.ning.billing.catalog.Catalog;
 import com.ning.billing.catalog.VersionedCatalog;
-import com.ning.billing.catalog.api.InvalidConfigException;
 import com.ning.billing.lifecycle.IService.ServiceException;
 import com.ning.billing.util.clock.IClock;
+import com.ning.billing.util.config.UriAccessor;
 import com.ning.billing.util.config.XMLLoader;
 
 public class VersionedCatalogLoader implements ICatalogLoader  {
@@ -64,21 +48,21 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 	 * @see com.ning.billing.catalog.io.ICatalogLoader#load(java.lang.String)
 	 */
 	@Override
-	public  VersionedCatalog load(String urlString) throws ServiceException{
+	public  VersionedCatalog load(String uriString) throws ServiceException{
 		try {
-			List<URL> xmlURLs = null;
+			List<URI> xmlURIs = null;
 			
-			if(urlString.endsWith(XML_EXTENSION)) { //assume its an xml file
-				xmlURLs = new ArrayList<URL>();
-	        	xmlURLs.add(new URL(urlString));
+			if(uriString.endsWith(XML_EXTENSION)) { //assume its an xml file
+				xmlURIs = new ArrayList<URI>();
+	        	xmlURIs.add(new URI(uriString));
 			} else { //assume its a directory
-				String[] directoryContents = getResourceListing(urlString);
-				xmlURLs = findXmlReferences(directoryContents, url);
+				String directoryContents = UriAccessor.accessUriAsString(uriString);
+				xmlURIs = findXmlReferences(directoryContents, new URL(uriString));
 			}
 			
 			VersionedCatalog result = new VersionedCatalog();
-			for(URL u : xmlURLs) {
-				Catalog catalog = XMLLoader.getObjectFromURL(u, Catalog.class);
+			for(URI u : xmlURIs) {
+				Catalog catalog = XMLLoader.getObjectFromUri(u, Catalog.class);
 				result.add(catalog);
 			}
 			Date now = clock.getUTCNow().toDate();
@@ -88,26 +72,25 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 			throw new ServiceException("Problem encountered loading catalog", e);
 		}
 	}
-
 	
-	protected  List<URL> findXmlReferences(String directoryContents, URL url) throws MalformedURLException {
+	protected  List<URI> findXmlReferences(String directoryContents, URL url) throws URISyntaxException {
 		if(url.getProtocol().equals(PROTOCOL_FOR_FILE)) {
 			return findXmlFileReferences(directoryContents, url);
 		} 
 		return findXmlUrlReferences(directoryContents, url);
 	}
 
-	protected  List<URL> findXmlUrlReferences(String directoryContents, URL url) throws MalformedURLException {
-		List<URL> results = new ArrayList<URL>();
+	protected  List<URI> findXmlUrlReferences(String directoryContents, URL url) throws URISyntaxException {
+		List<URI> results = new ArrayList<URI>();
 		List<String> urlFragments = extractHrefs(directoryContents);
 		for(String u : urlFragments) {
 			if(u.endsWith(XML_EXTENSION)) { //points to xml
 				if(u.startsWith("/")) { //absolute path need to add the protocol
-					results.add(new URL(url.getProtocol() + ":" + u));
+					results.add(new URI(url.getProtocol() + ":" + u));
 				} else if (u.startsWith("http:")) { // full url
-					results.add(new URL(u));
+					results.add(new URI(u));
 				} else { // relative url stick the name on the end
-					results.add(appendToURL(url,u));
+					results.add(appendToURI(url,u));
 				}
 			}
 		}
@@ -142,70 +125,24 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 		return results;
 	}
 
-	protected  List<URL> findXmlFileReferences(String directoryContents, URL url) throws MalformedURLException {
-		List<URL> results = new ArrayList<URL>();
+	protected  List<URI> findXmlFileReferences(String directoryContents, URL url) throws URISyntaxException {
+		List<URI> results = new ArrayList<URI>();
 		String[] filenames = directoryContents.split("\\n");
 		for(String filename : filenames) {
 			if(filename.endsWith(XML_EXTENSION)) {
-				results.add(appendToURL(url,filename));
+				results.add(appendToURI(url,filename));
 			}
 		}
 		return results;
 	}
 
-	protected  URL appendToURL(final URL url, final String filename) throws MalformedURLException {
+	protected  URI appendToURI(final URL url, final String filename) throws URISyntaxException {
 		String f = filename;
 		if (!url.toString().endsWith("/")) {
 			f = "/" + filename;
 		}
-		return new URL(url.toString() + f);
-	}
-
-	protected  String pullContentsFrom(final URL url) throws IOException {
-		URLConnection connection = url.openConnection();
-		InputStream content = connection.getInputStream();
-		return new Scanner(content).useDelimiter("\\A").next();
+		return new URI(url.toString() + f);
 	}
-//	
-//	private String[] getResourceListing(String path) throws URISyntaxException, IOException {
-//	      URL dirURL = this.getClass().getClassLoader().getResource(path);
-//	      if (dirURL != null && dirURL.getProtocol().equals("file")) {
-//	        /* A file path: easy enough */
-//	        return new File(dirURL.toURI()).list();
-//	      } 
-//
-//	      if (dirURL == null) {
-//	        /* 
-//	         * In case of a jar file, we can't actually find a directory.
-//	         * Have to assume the same jar as clazz.
-//	         */
-//	        String me = clazz.getName().replace(".", "/")+".class";
-//	        dirURL = clazz.getClassLoader().getResource(me);
-//	      }
-//	      
-//	      if (dirURL.getProtocol().equals("jar")) {
-//	        /* A JAR path */
-//	        String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
-//	        JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
-//	        Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
-//	        Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
-//	        while(entries.hasMoreElements()) {
-//	          String name = entries.nextElement().getName();
-//	          if (name.startsWith(path)) { //filter according to the path
-//	            String entry = name.substring(path.length());
-//	            int checkSubdir = entry.indexOf("/");
-//	            if (checkSubdir >= 0) {
-//	              // if it is a subdirectory, we just return the directory name
-//	              entry = entry.substring(0, checkSubdir);
-//	            }
-//	            result.add(entry);
-//	          }
-//	        }
-//	        return result.toArray(new String[result.size()]);
-//	      } 
-//	        
-//	      throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
-//	  }
 
 	
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
index 0e2510f..1b4703c 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
@@ -16,10 +16,10 @@
 package com.ning.billing.catalog.io;
 
 import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertTrue;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Iterator;
@@ -36,27 +36,20 @@ import com.google.common.io.Resources;
 import com.ning.billing.catalog.Catalog;
 import com.ning.billing.catalog.VersionedCatalog;
 import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.lifecycle.IService.ServiceException;
 import com.ning.billing.util.clock.Clock;
 
 public class TestVersionedCatalogLoader {
 	private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new Clock());
 
-
-	@Test(enabled=true)
-	public void testPullContentsFrom() throws MalformedURLException, IOException {
-		String contents = loader.pullContentsFrom(Resources.getResource("WeaponsHireSmall.xml"));
-
-		assertTrue(contents.length() > 0);
-		
-	}
 	
 	@Test(enabled=true)
-	public void testAppendToURL() throws MalformedURLException, IOException {
+	public void testAppendToURI() throws MalformedURLException, IOException, URISyntaxException {
 		URL u1 = new URL("http://www.ning.com/foo");
-		assertEquals("http://www.ning.com/foo/bar",loader.appendToURL(u1, "bar").toString());
+		assertEquals("http://www.ning.com/foo/bar",loader.appendToURI(u1, "bar").toString());
 
 		URL u2 = new URL("http://www.ning.com/foo/");
-		assertEquals("http://www.ning.com/foo/bar",loader.appendToURL(u2, "bar").toString());
+		assertEquals("http://www.ning.com/foo/bar",loader.appendToURI(u2, "bar").toString());
 		
 	}
 	
@@ -64,12 +57,12 @@ public class TestVersionedCatalogLoader {
 
 	
 	@Test(enabled=true)
-	public void testFindXmlFileReferences() throws MalformedURLException {
+	public void testFindXmlFileReferences() throws MalformedURLException, URISyntaxException {
 		String page = "dg.xml\n" + 
 				"replica.foo\n" + 
 				"snv1/\n" + 
 				"viking.xml\n" ;
-		List<URL> urls = loader.findXmlFileReferences(page, new URL("http://ning.com/"));
+		List<URI> urls = loader.findXmlFileReferences(page, new URL("http://ning.com/"));
 		assertEquals(2, urls.size());
 		assertEquals("http://ning.com/dg.xml", urls.get(0).toString());
 		assertEquals("http://ning.com/viking.xml", urls.get(1).toString());
@@ -102,7 +95,7 @@ public class TestVersionedCatalogLoader {
 	}
 	
 	@Test(enabled=true)
-	public void testFindXmlUrlReferences() throws MalformedURLException {
+	public void testFindXmlUrlReferences() throws MalformedURLException, URISyntaxException {
 		String page = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">" + 
 				"<html>" + 
 				" <head>" + 
@@ -120,16 +113,16 @@ public class TestVersionedCatalogLoader {
 				"</ul>" + 
 				"<address>Apache/2.2.3 (CentOS) Server at <a href=\"mailto:kate@ning.com\">gepo.ningops.net</a> Port 80</address>" + 
 				"</body></html>" ;
-		List<URL> urls = loader.findXmlUrlReferences(page, new URL("http://ning.com/"));
-		assertEquals(2, urls.size());
-		assertEquals("http://ning.com/dg.xml", urls.get(0).toString());
-		assertEquals("http://ning.com/viking.xml", urls.get(1).toString());
+		List<URI> uris = loader.findXmlUrlReferences(page, new URL("http://ning.com/"));
+		assertEquals(2, uris.size());
+		assertEquals("http://ning.com/dg.xml", uris.get(0).toString());
+		assertEquals("http://ning.com/viking.xml", uris.get(1).toString());
 		
 	}
 	
 	@Test(enabled=true)
-	public void testLoad() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
-		VersionedCatalog c = loader.load(Resources.getResource("versionedCatalog"));
+	public void testLoad() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException {
+		VersionedCatalog c = loader.load(Resources.getResource("versionedCatalog").toString());
 		assertEquals(4, c.size());
 		Iterator<Catalog> it = c.iterator();
 		it.next(); //discard the baseline
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
index a75cb06..01b436e 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
@@ -16,26 +16,18 @@
 
 package com.ning.billing.catalog.io;
 
-import java.io.IOException;
-import java.net.URISyntaxException;
-
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
 import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
 
 import com.google.common.io.Resources;
 import com.ning.billing.catalog.Catalog;
-import com.ning.billing.catalog.api.InvalidConfigException; 
 import com.ning.billing.util.config.XMLLoader;
 
 public class TestXMLReader {
 
 	@Test(enabled=true)
-	public void testCatalogLoad() throws IOException, TransformerException, JAXBException, SAXException, InvalidConfigException, URISyntaxException {
-		XMLLoader.getObjectFromURL(Resources.getResource("WeaponsHire.xml"), Catalog.class);
-		XMLLoader.getObjectFromURL(Resources.getResource("WeaponsHireSmall.xml"), Catalog.class);
+	public void testCatalogLoad() throws Exception {
+		XMLLoader.getObjectFromString(Resources.getResource("WeaponsHire.xml").toExternalForm(), Catalog.class);
+		XMLLoader.getObjectFromString(Resources.getResource("WeaponsHireSmall.xml").toExternalForm(), Catalog.class);
 	}
 	
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index a857176..c6da79d 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -32,21 +32,22 @@ import org.xml.sax.SAXException;
 import com.google.common.io.Resources;
 import com.ning.billing.catalog.api.InvalidConfigException;
 import com.ning.billing.catalog.io.VersionedCatalogLoader;
+import com.ning.billing.lifecycle.IService.ServiceException;
 import com.ning.billing.util.clock.Clock;
 
 public class TestVersionedCatalog {
 	private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new Clock());
 
 	@Test(enabled=true)
-	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
-		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog"));
+	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException {
+		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog").toString());
 		vc.add(new Catalog(new Date()));
 		assertEquals(5, vc.size());
 	}
 	
 	@Test(enabled=true)
-	public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
-		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog"));
+	public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException {
+		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog").toString());
 		Date d = new Date(1L);
 		vc.configureEffectiveDate(d);
 		assertEquals(new Date(0), vc.getEffectiveDate()); // Start at the begining of time
diff --git a/util/src/main/java/com/ning/billing/util/config/UriAccessor.java b/util/src/main/java/com/ning/billing/util/config/UriAccessor.java
new file mode 100644
index 0000000..931b5f9
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/config/UriAccessor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.util.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Scanner;
+
+public class UriAccessor {
+	private static final String URI_SCHEME_FOR_CLASSPATH = "jar";
+	private static final String URI_SCHEME_FOR_FILE = "file";
+
+	public static InputStream accessUri(String uri)  throws IOException, URISyntaxException {
+		return accessUri(new URI(uri));
+	}
+	
+	public static InputStream accessUri(URI uri) throws IOException {
+		String scheme = uri.getScheme();
+        URL url = uri.toURL();
+        if (scheme.equals(URI_SCHEME_FOR_CLASSPATH)) {
+        	return UriAccessor.class.getResourceAsStream(uri.getPath());
+        } else if (scheme.equals(URI_SCHEME_FOR_FILE) &&
+        	!uri.getSchemeSpecificPart().startsWith("/")) { // interpret URIs of this form as relative path uris
+        	url = new File(uri.getSchemeSpecificPart()).toURI().toURL();
+        }
+    	return url.openConnection().getInputStream();
+	}
+	
+	public static String accessUriAsString(String uri)  throws IOException, URISyntaxException {
+		return accessUriAsString(new URI(uri));
+	}
+	
+	public static String accessUriAsString(URI uri) throws IOException {
+		InputStream stream = accessUri(uri);
+		return new Scanner(stream).useDelimiter("\\A").next();
+	}
+}
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
index 8aaaf14..481447c 100644
--- a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
+++ b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
@@ -16,12 +16,9 @@
 
 package com.ning.billing.util.config;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
 
 import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
@@ -39,46 +36,27 @@ import org.xml.sax.SAXException;
 import com.ning.billing.catalog.api.InvalidConfigException;
 
 public class XMLLoader {
-	private static final String URI_SCHEME_FOR_CLASSPATH = "jar";
-	private static final String URI_SCHEME_FOR_FILE = "file";
 	public static Logger log = LoggerFactory.getLogger(XMLLoader.class);
 
-	public static <T extends ValidatingConfig<T>> T getObjectFromProperty(String property, Class<T> objectType) throws Exception {
-		if (property == null) {
+	public static <T extends ValidatingConfig<T>> T getObjectFromString(String uri, Class<T> objectType) throws Exception {
+		if (uri == null) {
 			return null;
 		}
-		log.info("Initializing an object of class " + objectType.getName() + " from xml file at: " + property);
+		log.info("Initializing an object of class " + objectType.getName() + " from xml file at: " + uri);
 					
-		return getObjectFromURI(new URI(property), objectType);
+		return getObjectFromStream(new URI(uri), UriAccessor.accessUri(uri), objectType);
 	}
 	
-	public static <T extends ValidatingConfig<T>> T getObjectFromURI(final URI uri, final Class<T> objectType) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException, URISyntaxException {
-        String scheme = uri.getScheme();
-        URI uriToCall = uri;
-        if (scheme.equals(URI_SCHEME_FOR_CLASSPATH)) {
-        	InputStream resourceStream = XMLLoader.class.getResourceAsStream(uri.getPath());
-        	return getObjectFromStream(uri, resourceStream, objectType);
-        } else if (scheme.equals(URI_SCHEME_FOR_FILE) &&
-        	!uri.getSchemeSpecificPart().startsWith("/")) { // interpret URIs of this form as relative path uris
-        	uriToCall = new File(uri.getSchemeSpecificPart()).toURI();
-        }
-        return getObjectFromURL(uriToCall.toURL(), objectType);
-    }
-
-	public static <T extends ValidatingConfig<T>> T getObjectFromURL(URL url, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException, URISyntaxException {
-        Object o = unmarshaller(clazz).unmarshal(url);
-    
-        if (clazz.isInstance(o)) {
-            @SuppressWarnings("unchecked")
-			T castObject = (T)o;
-            validate(url.toURI(),castObject);
-            return castObject;
-        } else {
-            return null;
-        }
-    }
-
-	public static <T extends ValidatingConfig<T>> T getObjectFromStream(URI uri,InputStream stream, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException {
+	public static <T extends ValidatingConfig<T>> T getObjectFromUri(URI uri, Class<T> objectType) throws Exception {
+		if (uri == null) {
+			return null;
+		}
+		log.info("Initializing an object of class " + objectType.getName() + " from xml file at: " + uri);
+					
+		return getObjectFromStream(uri, UriAccessor.accessUri(uri), objectType);
+	}
+	
+	public static <T extends ValidatingConfig<T>> T getObjectFromStream(URI uri, InputStream stream, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException {
         Object o = unmarshaller(clazz).unmarshal(stream);
         if (clazz.isInstance(o)) {
         	@SuppressWarnings("unchecked")
@@ -88,9 +66,7 @@ public class XMLLoader {
         } else {
             return null;
         }
-    }
-
-    
+    } 
 
 	public static <T extends ValidatingConfig<T>> void validate(URI uri, T c) {
             c.initialize(c, uri);