JPA persistence.xml files may use jar-file entries relative to the unit root (as per the JPA spec)
Issue: SPR-9797
This commit is contained in:
parent
92a92b7937
commit
efd872e35a
|
@ -173,12 +173,11 @@ class PersistenceUnitReader {
|
||||||
|
|
||||||
Element persistence = document.getDocumentElement();
|
Element persistence = document.getDocumentElement();
|
||||||
String version = persistence.getAttribute(PERSISTENCE_VERSION);
|
String version = persistence.getAttribute(PERSISTENCE_VERSION);
|
||||||
URL unitRootURL = determinePersistenceUnitRootUrl(resource);
|
URL rootUrl = determinePersistenceUnitRootUrl(resource);
|
||||||
|
|
||||||
List<Element> units = DomUtils.getChildElementsByTagName(persistence, PERSISTENCE_UNIT);
|
List<Element> units = DomUtils.getChildElementsByTagName(persistence, PERSISTENCE_UNIT);
|
||||||
for (Element unit : units) {
|
for (Element unit : units) {
|
||||||
SpringPersistenceUnitInfo info = parsePersistenceUnitInfo(unit, version);
|
infos.add(parsePersistenceUnitInfo(unit, version, rootUrl));
|
||||||
info.setPersistenceUnitRootUrl(unitRootURL);
|
|
||||||
infos.add(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return infos;
|
return infos;
|
||||||
|
@ -193,46 +192,52 @@ class PersistenceUnitReader {
|
||||||
*/
|
*/
|
||||||
protected URL determinePersistenceUnitRootUrl(Resource resource) throws IOException {
|
protected URL determinePersistenceUnitRootUrl(Resource resource) throws IOException {
|
||||||
URL originalURL = resource.getURL();
|
URL originalURL = resource.getURL();
|
||||||
String urlToString = originalURL.toExternalForm();
|
|
||||||
|
|
||||||
// If we get an archive, simply return the jar URL (section 6.2 from the JPA spec)
|
// If we get an archive, simply return the jar URL (section 6.2 from the JPA spec)
|
||||||
if (ResourceUtils.isJarURL(originalURL)) {
|
if (ResourceUtils.isJarURL(originalURL)) {
|
||||||
return ResourceUtils.extractJarFileURL(originalURL);
|
return ResourceUtils.extractJarFileURL(originalURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
// check META-INF folder
|
||||||
// check META-INF folder
|
String urlToString = originalURL.toExternalForm();
|
||||||
if (!urlToString.contains(META_INF)) {
|
if (!urlToString.contains(META_INF)) {
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info(resource.getFilename() +
|
logger.info(resource.getFilename() +
|
||||||
" should be located inside META-INF directory; cannot determine persistence unit root URL for " +
|
" should be located inside META-INF directory; cannot determine persistence unit root URL for " +
|
||||||
resource);
|
resource);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
if (urlToString.lastIndexOf(META_INF) == urlToString.lastIndexOf('/') - (1 + META_INF.length())) {
|
return null;
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info(resource.getFilename() +
|
|
||||||
" is not located in the root of META-INF directory; cannot determine persistence unit root URL for " +
|
|
||||||
resource);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String persistenceUnitRoot = urlToString.substring(0, urlToString.lastIndexOf(META_INF));
|
|
||||||
return new URL(persistenceUnitRoot);
|
|
||||||
}
|
}
|
||||||
|
if (urlToString.lastIndexOf(META_INF) == urlToString.lastIndexOf('/') - (1 + META_INF.length())) {
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info(resource.getFilename() +
|
||||||
|
" is not located in the root of META-INF directory; cannot determine persistence unit root URL for " +
|
||||||
|
resource);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String persistenceUnitRoot = urlToString.substring(0, urlToString.lastIndexOf(META_INF));
|
||||||
|
if (persistenceUnitRoot.endsWith("/")) {
|
||||||
|
persistenceUnitRoot = persistenceUnitRoot.substring(0, persistenceUnitRoot.length() - 1);
|
||||||
|
}
|
||||||
|
return new URL(persistenceUnitRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the unit info DOM element.
|
* Parse the unit info DOM element.
|
||||||
*/
|
*/
|
||||||
protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(Element persistenceUnit, String version) throws IOException {
|
protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(Element persistenceUnit, String version, URL rootUrl)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo();
|
SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo();
|
||||||
|
|
||||||
// set JPA version (1.0 or 2.0)
|
// set JPA version (1.0 or 2.0)
|
||||||
unitInfo.setPersistenceXMLSchemaVersion(version);
|
unitInfo.setPersistenceXMLSchemaVersion(version);
|
||||||
|
|
||||||
|
// set persistence unit root URL
|
||||||
|
unitInfo.setPersistenceUnitRootUrl(rootUrl);
|
||||||
|
|
||||||
// set unit name
|
// set unit name
|
||||||
unitInfo.setPersistenceUnitName(persistenceUnit.getAttribute(UNIT_NAME).trim());
|
unitInfo.setPersistenceUnitName(persistenceUnit.getAttribute(UNIT_NAME).trim());
|
||||||
|
|
||||||
|
@ -277,10 +282,10 @@ class PersistenceUnitReader {
|
||||||
unitInfo.setValidationModeName(validationMode);
|
unitInfo.setValidationModeName(validationMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseProperties(persistenceUnit, unitInfo);
|
||||||
|
parseManagedClasses(persistenceUnit, unitInfo);
|
||||||
parseMappingFiles(persistenceUnit, unitInfo);
|
parseMappingFiles(persistenceUnit, unitInfo);
|
||||||
parseJarFiles(persistenceUnit, unitInfo);
|
parseJarFiles(persistenceUnit, unitInfo);
|
||||||
parseClass(persistenceUnit, unitInfo);
|
|
||||||
parseProperty(persistenceUnit, unitInfo);
|
|
||||||
|
|
||||||
return unitInfo;
|
return unitInfo;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +294,7 @@ class PersistenceUnitReader {
|
||||||
* Parse the <code>property</code> XML elements.
|
* Parse the <code>property</code> XML elements.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void parseProperty(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
protected void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||||
Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES);
|
Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES);
|
||||||
if (propRoot == null) {
|
if (propRoot == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -306,7 +311,7 @@ class PersistenceUnitReader {
|
||||||
* Parse the <code>class</code> XML elements.
|
* Parse the <code>class</code> XML elements.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void parseClass(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
protected void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||||
List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME);
|
List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME);
|
||||||
for (Element element : classes) {
|
for (Element element : classes) {
|
||||||
String value = DomUtils.getTextValue(element).trim();
|
String value = DomUtils.getTextValue(element).trim();
|
||||||
|
@ -315,23 +320,6 @@ class PersistenceUnitReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the <code>jar-file</code> XML elements.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
|
|
||||||
List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL);
|
|
||||||
for (Element element : jars) {
|
|
||||||
String value = DomUtils.getTextValue(element).trim();
|
|
||||||
if (StringUtils.hasText(value)) {
|
|
||||||
Resource[] resources = this.resourcePatternResolver.getResources(value);
|
|
||||||
for (Resource resource : resources) {
|
|
||||||
unitInfo.addJarFileUrl(resource.getURL());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the <code>mapping-file</code> XML elements.
|
* Parse the <code>mapping-file</code> XML elements.
|
||||||
*/
|
*/
|
||||||
|
@ -346,4 +334,36 @@ class PersistenceUnitReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the <code>jar-file</code> XML elements.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
|
||||||
|
List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL);
|
||||||
|
for (Element element : jars) {
|
||||||
|
String value = DomUtils.getTextValue(element).trim();
|
||||||
|
if (StringUtils.hasText(value)) {
|
||||||
|
Resource[] resources = this.resourcePatternResolver.getResources(value);
|
||||||
|
boolean found = false;
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
if (resource.exists()) {
|
||||||
|
found = true;
|
||||||
|
unitInfo.addJarFileUrl(resource.getURL());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
// relative to the persistence unit root, according to the JPA spec
|
||||||
|
URL rootUrl = unitInfo.getPersistenceUnitRootUrl();
|
||||||
|
if (rootUrl != null) {
|
||||||
|
unitInfo.addJarFileUrl(new URL(rootUrl, value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.warn("Cannot resolve jar-file entry [" + value + "] in persistence unit '" +
|
||||||
|
unitInfo.getPersistenceUnitName() + "' without root URL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
|
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
|
||||||
|
|
||||||
<persistence-unit name="OrderManagement"/>
|
<persistence-unit name="OrderManagement">
|
||||||
|
<jar-file>order.jar</jar-file>
|
||||||
|
<jar-file>../../../order-supplemental.jar</jar-file>
|
||||||
|
</persistence-unit>
|
||||||
|
|
||||||
</persistence>
|
</persistence>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,7 +24,6 @@ import javax.persistence.spi.PersistenceUnitInfo;
|
||||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -37,13 +36,32 @@ import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
|
||||||
import org.springframework.jdbc.datasource.lookup.MapDataSourceLookup;
|
import org.springframework.jdbc.datasource.lookup.MapDataSourceLookup;
|
||||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit and integration tests for the JPA XML resource parsing support.
|
* Unit and integration tests for the JPA XML resource parsing support.
|
||||||
*
|
*
|
||||||
* @author Costin Leau
|
* @author Costin Leau
|
||||||
|
* @author Juergen Hoeller
|
||||||
*/
|
*/
|
||||||
public class PersistenceXmlParsingTests {
|
public class PersistenceXmlParsingTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaInfCase() throws Exception {
|
||||||
|
PersistenceUnitReader reader = new PersistenceUnitReader(
|
||||||
|
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
|
||||||
|
String resource = "/org/springframework/orm/jpa/META-INF/persistence.xml";
|
||||||
|
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
|
||||||
|
|
||||||
|
assertNotNull(info);
|
||||||
|
assertEquals(1, info.length);
|
||||||
|
assertEquals("OrderManagement", info[0].getPersistenceUnitName());
|
||||||
|
|
||||||
|
assertEquals(2, info[0].getJarFileUrls().size());
|
||||||
|
assertEquals(new ClassPathResource("order.jar").getURL(), info[0].getJarFileUrls().get(0));
|
||||||
|
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), info[0].getJarFileUrls().get(1));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExample1() throws Exception {
|
public void testExample1() throws Exception {
|
||||||
PersistenceUnitReader reader = new PersistenceUnitReader(
|
PersistenceUnitReader reader = new PersistenceUnitReader(
|
||||||
|
@ -87,6 +105,7 @@ public class PersistenceXmlParsingTests {
|
||||||
assertEquals(2, info[0].getJarFileUrls().size());
|
assertEquals(2, info[0].getJarFileUrls().size());
|
||||||
assertEquals(new ClassPathResource("order.jar").getURL(), info[0].getJarFileUrls().get(0));
|
assertEquals(new ClassPathResource("order.jar").getURL(), info[0].getJarFileUrls().get(0));
|
||||||
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), info[0].getJarFileUrls().get(1));
|
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), info[0].getJarFileUrls().get(1));
|
||||||
|
|
||||||
assertEquals(0, info[0].getProperties().keySet().size());
|
assertEquals(0, info[0].getProperties().keySet().size());
|
||||||
assertNull(info[0].getJtaDataSource());
|
assertNull(info[0].getJtaDataSource());
|
||||||
assertNull(info[0].getNonJtaDataSource());
|
assertNull(info[0].getNonJtaDataSource());
|
||||||
|
@ -120,12 +139,6 @@ public class PersistenceXmlParsingTests {
|
||||||
assertSame(PersistenceUnitTransactionType.RESOURCE_LOCAL, info[0].getTransactionType());
|
assertSame(PersistenceUnitTransactionType.RESOURCE_LOCAL, info[0].getTransactionType());
|
||||||
assertEquals(0, info[0].getProperties().keySet().size());
|
assertEquals(0, info[0].getProperties().keySet().size());
|
||||||
|
|
||||||
// TODO this is undefined as yet. Do we look up Spring datasource?
|
|
||||||
// assertNotNull(info[0].getNonJtaDataSource());
|
|
||||||
//
|
|
||||||
// assertEquals(ds .toString(),
|
|
||||||
// info[0].getNonJtaDataSource().toString());
|
|
||||||
|
|
||||||
builder.clear();
|
builder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,9 +215,6 @@ public class PersistenceXmlParsingTests {
|
||||||
assertEquals(1, pu2.getMappingFileNames().size());
|
assertEquals(1, pu2.getMappingFileNames().size());
|
||||||
assertEquals("order2.xml", pu2.getMappingFileNames().get(0));
|
assertEquals("order2.xml", pu2.getMappingFileNames().get(0));
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
Ignore ignore; // the following assertions fail only during coverage runs
|
|
||||||
/*
|
|
||||||
assertEquals(1, pu2.getJarFileUrls().size());
|
assertEquals(1, pu2.getJarFileUrls().size());
|
||||||
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), pu2.getJarFileUrls().get(0));
|
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), pu2.getJarFileUrls().get(0));
|
||||||
assertTrue(pu2.excludeUnlistedClasses());
|
assertTrue(pu2.excludeUnlistedClasses());
|
||||||
|
@ -213,7 +223,6 @@ public class PersistenceXmlParsingTests {
|
||||||
|
|
||||||
// TODO need to define behaviour with non jta datasource
|
// TODO need to define behaviour with non jta datasource
|
||||||
assertEquals(ds, pu2.getNonJtaDataSource());
|
assertEquals(ds, pu2.getNonJtaDataSource());
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -265,7 +274,7 @@ public class PersistenceXmlParsingTests {
|
||||||
assertNull(url);
|
assertNull(url);
|
||||||
|
|
||||||
url = reader.determinePersistenceUnitRootUrl(new ClassPathResource("/org/springframework/orm/jpa/META-INF/persistence.xml"));
|
url = reader.determinePersistenceUnitRootUrl(new ClassPathResource("/org/springframework/orm/jpa/META-INF/persistence.xml"));
|
||||||
assertTrue("the containing folder should have been returned", url.toString().endsWith("/org/springframework/orm/jpa/"));
|
assertTrue("the containing folder should have been returned", url.toString().endsWith("/org/springframework/orm/jpa"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue