diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java index 9b1b4af37b..35ec1b75f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java @@ -68,8 +68,8 @@ public class PersistenceXmlParser { ClassLoaderServiceImpl.fromConfigSettings( integration ), PersistenceUnitTransactionType.RESOURCE_LOCAL ); - - return new ArrayList<>( parser.doResolve( integration ).values() ); + parser.doResolve( integration ); + return new ArrayList<>( parser.persistenceUnits.values() ); } /** @@ -118,10 +118,11 @@ public class PersistenceXmlParser { transactionType ); - final Map persistenceUnits = parser.parsePersistenceXml( persistenceXmlUrl, integration ); - assert persistenceUnits.size() == 1; + parser.parsePersistenceXml( persistenceXmlUrl, integration ); - return persistenceUnits.values().iterator().next(); + assert parser.persistenceUnits.size() == 1; + + return parser.persistenceUnits.values().iterator().next(); } /** @@ -173,10 +174,10 @@ public class PersistenceXmlParser { transactionType ); - final Map persistenceUnits = parser.parsePersistenceXml( persistenceXmlUrl, integration ); - assert persistenceUnits.containsKey( name ); + parser.parsePersistenceXml( persistenceXmlUrl, integration ); + assert parser.persistenceUnits.containsKey( name ); - return persistenceUnits.get( name ); + return parser.persistenceUnits.get( name ); } /** @@ -200,51 +201,52 @@ public class PersistenceXmlParser { * * @return Map of persistence-unit descriptors keyed by the PU name */ - public static Map parse( + public static Map parse( URL persistenceXmlUrl, PersistenceUnitTransactionType transactionType, - Map integration) { + Map integration + ) { PersistenceXmlParser parser = new PersistenceXmlParser( ClassLoaderServiceImpl.fromConfigSettings( integration ), transactionType ); - return parser.doResolve( integration ); + parser.doResolve( integration ); + return parser.persistenceUnits; } - private final ClassLoaderService classLoaderService; private final PersistenceUnitTransactionType defaultTransactionType; + private final Map persistenceUnits; private PersistenceXmlParser(ClassLoaderService classLoaderService, PersistenceUnitTransactionType defaultTransactionType) { this.classLoaderService = classLoaderService; this.defaultTransactionType = defaultTransactionType; + this.persistenceUnits = new ConcurrentHashMap<>(); } - private Map doResolve(Map integration) { - final Map persistenceUnits = new ConcurrentHashMap<>(); - + private void doResolve(Map integration) { final List xmlUrls = classLoaderService.locateResources( "META-INF/persistence.xml" ); if ( xmlUrls.isEmpty() ) { LOG.unableToFindPersistenceXmlInClasspath(); } else { - for ( URL xmlUrl : xmlUrls ) { - persistenceUnits.putAll( parsePersistenceXml( xmlUrl, integration ) ); - } + parsePersistenceXml( xmlUrls, integration ); } - - return persistenceUnits; } - private Map parsePersistenceXml(URL xmlUrl, Map integration) { + private void parsePersistenceXml(List xmlUrls, Map integration) { + for ( URL xmlUrl : xmlUrls ) { + parsePersistenceXml( xmlUrl, integration ); + } + } + + private void parsePersistenceXml(URL xmlUrl, Map integration) { LOG.tracef( "Attempting to parse persistence.xml file : %s", xmlUrl.toExternalForm() ); final Document doc = loadUrl( xmlUrl ); final Element top = doc.getDocumentElement(); - final Map persistenceUnits = new ConcurrentHashMap<>(); - final NodeList children = top.getChildNodes(); for ( int i = 0; i < children.getLength() ; i++ ) { if ( children.item( i ).getNodeType() == Node.ELEMENT_NODE ) { @@ -285,7 +287,6 @@ public class PersistenceXmlParser { } } } - return persistenceUnits; } private void decodeTransactionType(ParsedPersistenceXmlDescriptor persistenceUnit) { diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/persistenceunit/DuplicatePersistenceUnitNameTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/persistenceunit/DuplicatePersistenceUnitNameTest.java new file mode 100644 index 0000000000..f75c0b0466 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/persistenceunit/DuplicatePersistenceUnitNameTest.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpa.test.persistenceunit; + +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.boot.internal.PersistenceXmlParser; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.jboss.byteman.contrib.bmunit.BMUnitRunner; +import org.jboss.logging.Logger; + +import static org.hibernate.internal.util.ConfigHelper.findAsResource; +import static org.junit.Assert.assertTrue; + +/** + * @author Andrea Boriero + */ +@TestForIssue(jiraKey = "HHH-11845") +@RunWith(BMUnitRunner.class) +public class DuplicatePersistenceUnitNameTest extends BaseUnitTestCase { + private Triggerable triggerable; + + @Rule + public LoggerInspectionRule logInspection = new LoggerInspectionRule( + Logger.getMessageLogger( CoreMessageLogger.class, PersistenceXmlParser.class.getName() ) + ); + + @Before + public void setUp() { + final Set messagesPrefixes = new HashSet<>(); + messagesPrefixes.add( "HHH015018" ); + triggerable = logInspection.watchForLogMessages( messagesPrefixes ); + } + + @After + public void tearDown() { + triggerable.reset(); + } + + @Test + public void testDuplicatePersistenceUnitNameLogAWarnMessage() { + final Map properties = new HashMap(); + properties.put( AvailableSettings.CLASSLOADERS, Arrays.asList( new TestClassLoader() ) ); + PersistenceXmlParser.locatePersistenceUnits( properties ); + assertTrue( "The warn HHH015018 has not been logged ", triggerable.wasTriggered() ); + } + + private static class TestClassLoader extends ClassLoader { + final List urls; + + public TestClassLoader() { + urls = Arrays.asList( + findAsResource( + "org/hibernate/jpa/test/persistenceunit/META-INF/persistence.xml" + ) + , + findAsResource( + "org/hibernate/jpa/test/persistenceunit/META-INF/persistenceUnitForNameDuplicationTest.xml" + ) + ); + } + + @Override + protected Enumeration findResources(String name) throws IOException { + return name.equals( "META-INF/persistence.xml" ) ? + Collections.enumeration( urls ) : + Collections.emptyEnumeration(); + } + } +} diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/persistenceunit/META-INF/persistenceUnitForNameDuplicationTest.xml b/hibernate-core/src/test/resources/org/hibernate/jpa/test/persistenceunit/META-INF/persistenceUnitForNameDuplicationTest.xml new file mode 100644 index 0000000000..513173e8df --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/persistenceunit/META-INF/persistenceUnitForNameDuplicationTest.xml @@ -0,0 +1,24 @@ + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + org.hibernate.jpa.test.persistenceunit.DataPoint + + \ No newline at end of file