Skip to content

Commit b3e614d

Browse files
beikovsebersole
authored andcommitted
HHH-18987 Implement discovery for META-INF/orm.xml also for DisabledScanner
1 parent 8b64878 commit b3e614d

File tree

7 files changed

+314
-13
lines changed

7 files changed

+314
-13
lines changed

hibernate-core/src/main/java/org/hibernate/boot/archive/internal/ExplodedArchiveDescriptor.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.jar.JarFile;
1313
import java.util.zip.ZipEntry;
1414

15+
import org.checkerframework.checker.nullness.qual.Nullable;
1516
import org.hibernate.boot.archive.spi.AbstractArchiveDescriptor;
1617
import org.hibernate.boot.archive.spi.ArchiveContext;
1718
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
@@ -57,6 +58,39 @@ public void visitArchive(ArchiveContext context) {
5758
}
5859
}
5960

61+
@Override
62+
public @Nullable ArchiveEntry findEntry(String path) {
63+
final File rootDirectory = resolveRootDirectory();
64+
if ( rootDirectory == null ) {
65+
return null;
66+
}
67+
final File localFile = new File( rootDirectory, path );
68+
if ( !localFile.exists() ) {
69+
return null;
70+
}
71+
72+
final String name = localFile.getAbsolutePath();
73+
final String relativeName = path + localFile.getName();
74+
final InputStreamAccess inputStreamAccess = new FileInputStreamAccess( name, localFile );
75+
76+
return new ArchiveEntry() {
77+
@Override
78+
public String getName() {
79+
return name;
80+
}
81+
82+
@Override
83+
public String getNameWithinArchive() {
84+
return relativeName;
85+
}
86+
87+
@Override
88+
public InputStreamAccess getStreamAccess() {
89+
return inputStreamAccess;
90+
}
91+
};
92+
}
93+
6094
private File resolveRootDirectory() {
6195
final File archiveUrlDirectory;
6296
try {

hibernate-core/src/main/java/org/hibernate/boot/archive/internal/JarFileBasedArchiveDescriptor.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.net.URISyntaxException;
1111
import java.net.URL;
1212
import java.util.Enumeration;
13+
import java.util.jar.JarEntry;
1314
import java.util.jar.JarFile;
1415
import java.util.jar.JarInputStream;
1516
import java.util.zip.ZipEntry;
1617

18+
import org.checkerframework.checker.nullness.qual.Nullable;
1719
import org.hibernate.boot.archive.spi.AbstractArchiveDescriptor;
1820
import org.hibernate.boot.archive.spi.ArchiveContext;
1921
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
@@ -155,6 +157,60 @@ public InputStreamAccess getStreamAccess() {
155157
}
156158
}
157159

160+
@Override
161+
public @Nullable ArchiveEntry findEntry(String path) {
162+
final JarFile jarFile = resolveJarFileReference();
163+
if ( jarFile == null ) {
164+
return null;
165+
}
166+
167+
try {
168+
final JarEntry jarEntry = jarFile.getJarEntry( path );
169+
if ( jarEntry == null ) {
170+
return null;
171+
}
172+
final String name = extractName( jarEntry );
173+
final String relativeName = extractRelativeName( jarEntry );
174+
final InputStreamAccess inputStreamAccess;
175+
try (InputStream is = jarFile.getInputStream( jarEntry )) {
176+
inputStreamAccess = buildByteBasedInputStreamAccess( name, is );
177+
}
178+
catch (IOException e) {
179+
throw new ArchiveException(
180+
String.format(
181+
"Unable to access stream from jar file [%s] for entry [%s]",
182+
jarFile.getName(),
183+
jarEntry.getName()
184+
)
185+
);
186+
}
187+
188+
return new ArchiveEntry() {
189+
@Override
190+
public String getName() {
191+
return name;
192+
}
193+
194+
@Override
195+
public String getNameWithinArchive() {
196+
return relativeName;
197+
}
198+
199+
@Override
200+
public InputStreamAccess getStreamAccess() {
201+
return inputStreamAccess;
202+
}
203+
};
204+
}
205+
finally {
206+
try {
207+
jarFile.close();
208+
}
209+
catch ( Exception ignore ) {
210+
}
211+
}
212+
}
213+
158214
private JarFile resolveJarFileReference() {
159215
try {
160216
final String filePart = getArchiveUrl().getFile();

hibernate-core/src/main/java/org/hibernate/boot/archive/internal/JarInputStreamBasedArchiveDescriptor.java

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.jar.JarInputStream;
1111
import java.util.zip.ZipEntry;
1212

13+
import org.checkerframework.checker.nullness.qual.Nullable;
1314
import org.hibernate.boot.archive.spi.AbstractArchiveDescriptor;
1415
import org.hibernate.boot.archive.spi.ArchiveContext;
1516
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
@@ -148,4 +149,119 @@ public InputStreamAccess getStreamAccess() {
148149
);
149150
}
150151
}
152+
153+
@Override
154+
public @Nullable ArchiveEntry findEntry(String path) {
155+
final JarInputStream jarInputStream;
156+
try {
157+
jarInputStream = new JarInputStream( getArchiveUrl().openStream() );
158+
}
159+
catch (Exception e) {
160+
//really should catch IOException but Eclipse is buggy and raise NPE...
161+
URL_MESSAGE_LOGGER.logUnableToFindFileByUrl( getArchiveUrl(), e );
162+
return null;
163+
}
164+
165+
try {
166+
JarEntry jarEntry;
167+
while ( ( jarEntry = jarInputStream.getNextJarEntry() ) != null ) {
168+
final String jarEntryName = jarEntry.getName();
169+
if ( getEntryBasePrefix() != null && ! jarEntryName.startsWith( getEntryBasePrefix() ) ) {
170+
continue;
171+
}
172+
173+
if ( jarEntry.isDirectory() ) {
174+
continue;
175+
}
176+
177+
if ( jarEntryName.equals( getEntryBasePrefix() ) ) {
178+
// exact match, might be a nested jar entry (ie from jar:file:..../foo.ear!/bar.jar)
179+
//
180+
// This algorithm assumes that the zipped file is only the URL root (including entry), not
181+
// just any random entry
182+
try {
183+
final JarInputStream subJarInputStream = new JarInputStream( jarInputStream );
184+
try {
185+
ZipEntry subZipEntry = jarInputStream.getNextEntry();
186+
while (subZipEntry != null) {
187+
if ( ! subZipEntry.isDirectory() ) {
188+
final String subName = extractName( subZipEntry );
189+
if ( path.equals( subName ) ) {
190+
final InputStreamAccess inputStreamAccess = buildByteBasedInputStreamAccess(
191+
subName,
192+
subJarInputStream
193+
);
194+
195+
return new ArchiveEntry() {
196+
@Override
197+
public String getName() {
198+
return subName;
199+
}
200+
201+
@Override
202+
public String getNameWithinArchive() {
203+
return subName;
204+
}
205+
206+
@Override
207+
public InputStreamAccess getStreamAccess() {
208+
return inputStreamAccess;
209+
}
210+
};
211+
}
212+
}
213+
subZipEntry = jarInputStream.getNextJarEntry();
214+
}
215+
}
216+
finally {
217+
subJarInputStream.close();
218+
}
219+
}
220+
catch (Exception e) {
221+
throw new ArchiveException( "Error accessing nested jar", e );
222+
}
223+
}
224+
else if ( path.equals( jarEntryName ) ) {
225+
final String entryName = extractName( jarEntry );
226+
final InputStreamAccess inputStreamAccess
227+
= buildByteBasedInputStreamAccess( entryName, jarInputStream );
228+
229+
final String relativeName = extractRelativeName( jarEntry );
230+
231+
return new ArchiveEntry() {
232+
@Override
233+
public String getName() {
234+
return entryName;
235+
}
236+
237+
@Override
238+
public String getNameWithinArchive() {
239+
return relativeName;
240+
}
241+
242+
@Override
243+
public InputStreamAccess getStreamAccess() {
244+
return inputStreamAccess;
245+
}
246+
};
247+
}
248+
}
249+
250+
}
251+
catch (IOException ioe) {
252+
throw new ArchiveException(
253+
String.format( "Error accessing JarInputStream [%s]", getArchiveUrl() ),
254+
ioe
255+
);
256+
}
257+
finally {
258+
try {
259+
jarInputStream.close();
260+
}
261+
catch (IOException e) {
262+
// Ignore
263+
}
264+
}
265+
return null;
266+
}
151267
}

hibernate-core/src/main/java/org/hibernate/boot/archive/internal/JarProtocolArchiveDescriptor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
import java.net.URL;
88

9+
import org.checkerframework.checker.nullness.qual.Nullable;
910
import org.hibernate.AssertionFailure;
1011
import org.hibernate.boot.archive.spi.ArchiveContext;
1112
import org.hibernate.boot.archive.spi.ArchiveDescriptor;
1213
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
14+
import org.hibernate.boot.archive.spi.ArchiveEntry;
1315

1416
/**
1517
* An ArchiveDescriptor implementation for handling archives whose url reported a JAR protocol (i.e., jar://).
@@ -56,4 +58,9 @@ public JarProtocolArchiveDescriptor(
5658
public void visitArchive(ArchiveContext context) {
5759
delegateDescriptor.visitArchive( context );
5860
}
61+
62+
@Override
63+
public @Nullable ArchiveEntry findEntry(String path) {
64+
return delegateDescriptor.findEntry( path );
65+
}
5966
}

hibernate-core/src/main/java/org/hibernate/boot/archive/scan/internal/DisabledScanner.java

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
*/
55
package org.hibernate.boot.archive.scan.internal;
66

7+
import java.net.URL;
78
import java.util.Collections;
9+
import java.util.HashSet;
810
import java.util.Set;
911

12+
import org.hibernate.boot.archive.internal.StandardArchiveDescriptorFactory;
1013
import org.hibernate.boot.archive.scan.spi.ClassDescriptor;
1114
import org.hibernate.boot.archive.scan.spi.MappingFileDescriptor;
1215
import org.hibernate.boot.archive.scan.spi.PackageDescriptor;
@@ -15,6 +18,10 @@
1518
import org.hibernate.boot.archive.scan.spi.ScanParameters;
1619
import org.hibernate.boot.archive.scan.spi.ScanResult;
1720
import org.hibernate.boot.archive.scan.spi.Scanner;
21+
import org.hibernate.boot.archive.spi.ArchiveDescriptor;
22+
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
23+
import org.hibernate.boot.archive.spi.ArchiveEntry;
24+
import org.hibernate.boot.archive.spi.InputStreamAccess;
1825

1926
/**
2027
* Implementation of Scanner that does nothing. Used for optimizing startup
@@ -23,25 +30,74 @@
2330
* @author Petteri Pitkanen
2431
*/
2532
public class DisabledScanner implements Scanner {
26-
private static final ScanResult emptyScanResult = new ScanResult() {
27-
@Override
28-
public Set<PackageDescriptor> getLocatedPackages() {
29-
return Collections.emptySet();
33+
34+
private final ArchiveDescriptorFactory archiveDescriptorFactory;
35+
36+
public DisabledScanner() {
37+
this( StandardArchiveDescriptorFactory.INSTANCE );
38+
}
39+
40+
private DisabledScanner(ArchiveDescriptorFactory archiveDescriptorFactory) {
41+
this.archiveDescriptorFactory = archiveDescriptorFactory;
42+
}
43+
44+
@Override
45+
public ScanResult scan(final ScanEnvironment environment, final ScanOptions options, final ScanParameters parameters) {
46+
final Set<MappingFileDescriptor> discoveredMappingFiles = new HashSet<>();
47+
48+
if ( environment.getNonRootUrls() != null ) {
49+
for ( URL url : environment.getNonRootUrls() ) {
50+
final ArchiveDescriptor archiveDescriptor = archiveDescriptorFactory.buildArchiveDescriptor( url );
51+
final ArchiveEntry entry = archiveDescriptor.findEntry( "META-INF/orm.xml" );
52+
if ( entry != null ) {
53+
discoveredMappingFiles.add( new MappingFileDescriptorImpl( entry.getNameWithinArchive(), entry.getStreamAccess() ) );
54+
}
55+
}
3056
}
3157

32-
@Override
33-
public Set<ClassDescriptor> getLocatedClasses() {
34-
return Collections.emptySet();
58+
if ( environment.getRootUrl() != null ) {
59+
final ArchiveDescriptor archiveDescriptor = archiveDescriptorFactory.buildArchiveDescriptor( environment.getRootUrl() );
60+
final ArchiveEntry entry = archiveDescriptor.findEntry( "META-INF/orm.xml" );
61+
if ( entry != null ) {
62+
discoveredMappingFiles.add( new MappingFileDescriptorImpl( entry.getNameWithinArchive(), entry.getStreamAccess() ) );
63+
}
64+
}
65+
66+
return new ScanResult() {
67+
@Override
68+
public Set<PackageDescriptor> getLocatedPackages() {
69+
return Collections.emptySet();
70+
}
71+
72+
@Override
73+
public Set<ClassDescriptor> getLocatedClasses() {
74+
return Collections.emptySet();
75+
}
76+
77+
@Override
78+
public Set<MappingFileDescriptor> getLocatedMappingFiles() {
79+
return discoveredMappingFiles;
80+
}
81+
};
82+
}
83+
84+
public static class MappingFileDescriptorImpl implements MappingFileDescriptor {
85+
private final String name;
86+
private final InputStreamAccess streamAccess;
87+
88+
public MappingFileDescriptorImpl(String name, InputStreamAccess streamAccess) {
89+
this.name = name;
90+
this.streamAccess = streamAccess;
3591
}
3692

3793
@Override
38-
public Set<MappingFileDescriptor> getLocatedMappingFiles() {
39-
return Collections.emptySet();
94+
public String getName() {
95+
return name;
4096
}
41-
};
4297

43-
@Override
44-
public ScanResult scan(final ScanEnvironment environment, final ScanOptions options, final ScanParameters parameters) {
45-
return emptyScanResult;
98+
@Override
99+
public InputStreamAccess getStreamAccess() {
100+
return streamAccess;
101+
}
46102
}
47103
}

0 commit comments

Comments
 (0)