[hibernate-commits] Hibernate SVN: r18263 - in core/trunk: annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3 and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Dec 18 05:02:27 EST 2009


Author: epbernard
Date: 2009-12-18 05:02:26 -0500 (Fri, 18 Dec 2009)
New Revision: 18263

Modified:
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
   core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm.xml
   core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm3.xml
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java
Log:
HHH-4667 accept orm 2 and orm 1 files. Also improved error reports

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java	2009-12-18 06:23:17 UTC (rev 18262)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java	2009-12-18 10:02:26 UTC (rev 18263)
@@ -26,6 +26,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringReader;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -54,6 +55,8 @@
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ErrorHandler;
 
 import org.hibernate.AnnotationException;
 import org.hibernate.DuplicateMappingException;
@@ -67,6 +70,7 @@
 import org.hibernate.annotations.common.reflection.ReflectionManager;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
+import org.hibernate.annotations.common.AssertionFailure;
 import org.hibernate.cfg.annotations.Version;
 import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
 import org.hibernate.cfg.beanvalidation.BeanValidationActivator;
@@ -839,32 +843,76 @@
 	@Override
 	public AnnotationConfiguration addInputStream(InputStream xmlInputStream) throws MappingException {
 		try {
-			List errors = new ArrayList();
-			SAXReader saxReader = xmlHelper.createSAXReader( "XML InputStream", errors, getEntityResolver() );
+			/*
+			 * try and parse the document:
+			 *  - try and validate the document with orm_2_0.xsd
+			  * - if it fails because of the version attribute mismatch, try and validate the document with orm_1_0.xsd
+			 */
+			List<SAXParseException> errors = new ArrayList<SAXParseException>();
+			SAXReader saxReader = new SAXReader( );
+			saxReader.setEntityResolver( getEntityResolver() );
+			saxReader.setErrorHandler( new ErrorLogger(errors) );
+			saxReader.setMergeAdjacentText(true);
+			saxReader.setValidation(true);
+
+			setValidationFor( saxReader, "orm_2_0.xsd" );
+
+			org.dom4j.Document doc = null;
 			try {
-				saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true );
-				//saxReader.setFeature( "http://apache.org/xml/features/validation/dynamic", true );
-				//set the default schema locators
-				saxReader.setProperty(
-						"http://apache.org/xml/properties/schema/external-schemaLocation",
-						"http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
-				);
+				doc = saxReader.read( new InputSource( xmlInputStream ) );
 			}
-			catch ( SAXException e ) {
-				saxReader.setValidation( false );
+			catch ( DocumentException e ) {
+				//the document is syntactically incorrect
+
+				//DOM4J sometimes wraps the SAXParseException wo much interest
+				final Throwable throwable = e.getCause();
+				if ( e.getCause() == null || !( throwable instanceof SAXParseException ) ) {
+					throw new MappingException( "Could not parse JPA mapping document", e );
+				}
+				errors.add( (SAXParseException) throwable );
 			}
-			org.dom4j.Document doc = saxReader
-					.read( new InputSource( xmlInputStream ) );
 
+			boolean isV1Schema = false;
 			if ( errors.size() != 0 ) {
-				throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) );
+				SAXParseException exception = errors.get( 0 );
+				final String errorMessage = exception.getMessage();
+				//does the error look like a schema mismatch?
+				isV1Schema = doc != null
+						&& errorMessage.contains("1.0")
+						&& errorMessage.contains("2.0")
+						&& errorMessage.contains("version");
 			}
+			if (isV1Schema) {
+				//reparse with v1
+				errors.clear();
+				setValidationFor( saxReader, "orm_1_0.xsd" );
+				try {
+					//too bad we have to reparse to validate again :(
+					saxReader.read( new StringReader( doc.asXML() ) );
+				}
+				catch ( DocumentException e ) {
+					//oops asXML fails even if the core doc parses initially
+					new AssertionFailure("Error in DOM4J leads to a bug in Hibernate", e);
+				}
+
+			}
+			if ( errors.size() != 0 ) {
+				//report errors in exception
+				StringBuilder errorMessage = new StringBuilder( );
+				for (SAXParseException error : errors) {
+					errorMessage.append("Error parsing XML (line")
+								.append(error.getLineNumber())
+								.append(" : column ")
+								.append(error.getColumnNumber())
+								.append("): ")
+								.append(error.getMessage())
+								.append("\n");
+				}
+				throw new MappingException( "Invalid ORM mapping file.\n" + errorMessage.toString() );
+			}
 			add( doc );
 			return this;
 		}
-		catch ( DocumentException e ) {
-			throw new MappingException( "Could not parse mapping document in input stream", e );
-		}
 		finally {
 			try {
 				xmlInputStream.close();
@@ -875,6 +923,40 @@
 		}
 	}
 
+	private static class ErrorLogger implements ErrorHandler {
+		private List<SAXParseException> errors;
+
+		public ErrorLogger(List<SAXParseException> errors) {
+			this.errors = errors;
+		}
+
+		public void warning(SAXParseException exception) throws SAXException {
+			errors.add( exception );
+		}
+
+		public void error(SAXParseException exception) throws SAXException {
+			errors.add( exception );
+		}
+
+		public void fatalError(SAXParseException exception) throws SAXException {
+		}
+	}
+
+	private void setValidationFor(SAXReader saxReader, String xsd) {
+		try {
+			saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true );
+			//saxReader.setFeature( "http://apache.org/xml/features/validation/dynamic", true );
+			//set the default schema locators
+			saxReader.setProperty(
+					"http://apache.org/xml/properties/schema/external-schemaLocation",
+					"http://java.sun.com/xml/ns/persistence/orm " + xsd
+			);
+		}
+		catch ( SAXException e ) {
+			saxReader.setValidation( false );
+		}
+	}
+
 	public SessionFactory buildSessionFactory() throws HibernateException {
 		enableLegacyHibernateValidator();
 		enableBeanValidation();

Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm.xml	2009-12-18 06:23:17 UTC (rev 18262)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm.xml	2009-12-18 10:02:26 UTC (rev 18263)
@@ -1,9 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
-                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-                 version="1.0"
-        >
+                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+                 version="2.0">
     <!-- no grammar specified should pass -->
     <persistence-unit-metadata>
         <persistence-unit-defaults>

Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm3.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm3.xml	2009-12-18 06:23:17 UTC (rev 18262)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/xml/ejb3/orm3.xml	2009-12-18 10:02:26 UTC (rev 18263)
@@ -2,9 +2,8 @@
 
 <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
-                 version="1.0"
-        >
+                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm/orm_2_0.xsd"
+                 version="2.0">
     <package>org.hibernate.test.annotations.xml.ejb3</package>
     <entity class="Lighter" access="FIELD" metadata-complete="true">
         <attributes>

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java	2009-12-18 06:23:17 UTC (rev 18262)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java	2009-12-18 10:02:26 UTC (rev 18263)
@@ -68,6 +68,11 @@
 	}
 
 	private static Document loadURL(URL configURL, EntityResolver resolver) throws Exception {
+		/*
+		 * try and parse the document:
+		 *  - try and validate the document with persistence_2_0.xsd
+		  * - if it fails because of the version attribute mismatch, try and validate the document with persistence_1_0.xsd
+		 */
 		InputStream is = null;
 		if (configURL != null) {
 			URLConnection conn = configURL.openConnection();
@@ -75,8 +80,9 @@
 			is = conn.getInputStream();
 		}
 		if ( is == null ) {
-			throw new IOException( "Failed to obtain InputStream from url: " + configURL );
+			throw new IOException( "Failed to obtain InputStream while reading persistence.xml file: " + configURL );
 		}
+
 		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
 		docBuilderFactory.setNamespaceAware( true );
 		final Schema v2Schema = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI )
@@ -91,6 +97,8 @@
 		docBuilder.setEntityResolver( resolver );
 		List<SAXParseException> errors = new ArrayList<SAXParseException>();
 		Document doc = null;
+
+		//first sparse document and collect syntaxic errors
 		try {
 			doc = docBuilder.parse( source );
 		}
@@ -99,7 +107,7 @@
 		}
 
 		if (errors.size() == 0) {
-			v2Validator.setErrorHandler( new ErrorLogger( "XML InputStream", errors, resolver ) );
+			v2Validator.setErrorHandler( new ErrorLogger( errors ) );
 			log.trace("Validate with persistence_2_0.xsd schema on file {}", configURL);
 			v2Validator.validate( new DOMSource( doc ) );
 			boolean isV1Schema = false;
@@ -108,6 +116,7 @@
 				log.trace("Found error with persistence_2_0.xsd schema on file {}", configURL);
 				SAXParseException exception = errors.get( 0 );
 				final String errorMessage = exception.getMessage();
+				//is it a validation error due to a v1 schema validated by a v2
 				isV1Schema = errorMessage.contains("1.0")
 						&& errorMessage.contains("2.0")
 						&& errorMessage.contains("version");
@@ -116,11 +125,12 @@
 			if (isV1Schema) {
 				log.trace("Validate with persistence_1_0.xsd schema on file {}", configURL);
 				errors.clear();
-				v1Validator.setErrorHandler( new ErrorLogger( "XML InputStream", errors, resolver ) );
+				v1Validator.setErrorHandler( new ErrorLogger( errors ) );
 				v1Validator.validate( new DOMSource( doc ) );
 			}
 		}
 		if ( errors.size() != 0 ) {
+			//report all errors in the exception
 			StringBuilder errorMessage = new StringBuilder( );
 			for (SAXParseException error : errors) {
 				errorMessage.append("Error parsing XML (line")
@@ -310,17 +320,14 @@
 	}
 
 	public static class ErrorLogger implements ErrorHandler {
-		private String file;
-		private List errors;
-		private EntityResolver resolver;
+		private List<SAXParseException> errors;
 
-		ErrorLogger(String file, List errors, EntityResolver resolver) {
-			this.file = file;
+		ErrorLogger(List<SAXParseException> errors) {
 			this.errors = errors;
-			this.resolver = resolver;
 		}
 
 		public void error(SAXParseException error) {
+			//what was this commented code about?
 //			if ( resolver instanceof EJB3DTDEntityResolver ) {
 //				if ( ( (EJB3DTDEntityResolver) resolver ).isResolved() == false ) return;
 //			}



More information about the hibernate-commits mailing list