DATAJPA-519 - Spec compliant mapping file URI handling in ClasspathScanningPersistenceUnitPostProcessor.
JPA requires mapping file locations to be classpath relative. Previously we handed the full path to the file (including protocol and JAR path) to the provider, which they happened to understand by accident. To be more spec compliant, we now massage the detected URIs into the expected format. Original pull request: #81.
This commit is contained in:
committed by
Oliver Gierke
parent
68e2ee5ed9
commit
fe55862bcf
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.jpa.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -51,6 +52,7 @@ public class ClasspathScanningPersistenceUnitPostProcessor implements Persistenc
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClasspathScanningPersistenceUnitPostProcessor.class);
|
||||
|
||||
private final String basePackage;
|
||||
|
||||
private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(getClass().getClassLoader());
|
||||
private String mappingFileNamePattern;
|
||||
|
||||
@@ -142,7 +144,7 @@ public class ClasspathScanningPersistenceUnitPostProcessor implements Persistenc
|
||||
|
||||
for (Resource resource : scannedResources) {
|
||||
try {
|
||||
String resourcePath = resource.getURI().getPath();
|
||||
String resourcePath = getResourcePath(resource.getURI());
|
||||
String resourcePathInClasspath = resourcePath.substring(resourcePath.indexOf(basePackagePathComponent));
|
||||
mappingFileUris.add(resourcePathInClasspath);
|
||||
} catch (IOException e) {
|
||||
@@ -152,4 +154,30 @@ public class ClasspathScanningPersistenceUnitPostProcessor implements Persistenc
|
||||
|
||||
return mappingFileUris;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path from the given {@link URI}. In case the given {@link URI} is opaque, e.g. beginning with jar:file,
|
||||
* the path is extracted from URI by leaving out the protocol prefix.
|
||||
*
|
||||
* @param uri
|
||||
* @return
|
||||
* @see DATAJPA-519
|
||||
*/
|
||||
private static String getResourcePath(URI uri) throws IOException {
|
||||
|
||||
if (uri.isOpaque()) {
|
||||
// e.g. jar:file:/foo/lib/somelib.jar!/com/acme/orm.xml
|
||||
String rawPath = uri.toString();
|
||||
if (rawPath != null) {
|
||||
int exclamationMarkIndex = rawPath.lastIndexOf('!');
|
||||
if (exclamationMarkIndex > -1) {
|
||||
|
||||
// /com/acme/orm.xml
|
||||
return rawPath.substring(exclamationMarkIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uri.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,11 @@ package org.springframework.data.jpa.support;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -24,8 +29,13 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
|
||||
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ClasspathScanningPersistenceUnitPostProcessor}.
|
||||
@@ -108,6 +118,49 @@ public class ClasspathScanningPersistenceUnitPostProcessorUnitTests {
|
||||
verify(pui).addMappingFileName("org/springframework/data/jpa/support/module2/module2-orm.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-519
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindJpaMappingFilesFromNestedJarLocationsOnClasspath() {
|
||||
|
||||
String nestedModule3Path = "org/springframework/data/jpa/support/module3/module3-orm.xml";
|
||||
final String fileInJarUrl = "jar:file:/foo/bar/lib/somelib.jar!/" + nestedModule3Path;
|
||||
|
||||
ResourceLoader resolver = new PathMatchingResourcePatternResolver(new DefaultResourceLoader()) {
|
||||
|
||||
public Resource[] getResources(String locationPattern) throws IOException {
|
||||
|
||||
Resource[] resources = super.getResources(locationPattern);
|
||||
resources = Arrays.copyOf(resources, resources.length + 1);
|
||||
resources[resources.length - 1] = new UrlResource(fileInJarUrl);
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, String subPattern)
|
||||
throws IOException {
|
||||
|
||||
if (fileInJarUrl.equals(rootDirResource.getURI().toString())) {
|
||||
return Collections.singleton(rootDirResource);
|
||||
}
|
||||
|
||||
return super.doFindPathMatchingJarResources(rootDirResource, subPattern);
|
||||
}
|
||||
};
|
||||
|
||||
ClasspathScanningPersistenceUnitPostProcessor processor = new ClasspathScanningPersistenceUnitPostProcessor(
|
||||
basePackage);
|
||||
ReflectionTestUtils.setField(processor, "resolver", resolver);
|
||||
processor.setMappingFileNamePattern("**/*orm.xml");
|
||||
processor.postProcessPersistenceUnitInfo(pui);
|
||||
|
||||
verify(pui).addMappingFileName("org/springframework/data/jpa/support/module1/module1-orm.xml");
|
||||
verify(pui).addMappingFileName("org/springframework/data/jpa/support/module2/module2-orm.xml");
|
||||
verify(pui).addMappingFileName(nestedModule3Path);
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class SampleEntity {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user