Skip to content

Commit 5ed9f08

Browse files
committed
HHH-12986
HHH-12986 ConfigLoader does not close file when loading hibernate.cfg.xml
1 parent 058c56d commit 5ed9f08

File tree

3 files changed

+159
-5
lines changed

3 files changed

+159
-5
lines changed

hibernate-core/src/main/java/org/hibernate/boot/cfgxml/internal/ConfigLoader.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,26 @@ public LoadedConfig loadConfigXmlResource(String cfgXmlResourceName) {
7171

7272
public LoadedConfig loadConfigXmlFile(File cfgXmlFile) {
7373
try {
74-
final JaxbCfgHibernateConfiguration jaxbCfg = jaxbProcessorHolder.getValue().unmarshal(
75-
new FileInputStream( cfgXmlFile ),
76-
new Origin( SourceType.FILE, cfgXmlFile.getAbsolutePath() )
77-
);
74+
FileInputStream cfgFileStream = null;
75+
try {
76+
cfgFileStream = new FileInputStream( cfgXmlFile );
7877

79-
return LoadedConfig.consume( jaxbCfg );
78+
final JaxbCfgHibernateConfiguration jaxbCfg = jaxbProcessorHolder.getValue().unmarshal(
79+
cfgFileStream,
80+
new Origin( SourceType.FILE, cfgXmlFile.getAbsolutePath() )
81+
);
82+
83+
return LoadedConfig.consume( jaxbCfg );
84+
}
85+
finally {
86+
try {
87+
assert cfgFileStream != null;
88+
cfgFileStream.close();
89+
}
90+
catch (IOException e) {
91+
log.debug( "Unable to close cfg.xml URL stream", e );
92+
}
93+
}
8094
}
8195
catch (FileNotFoundException e) {
8296
throw new ConfigurationException(
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.boot.cfgXml;
6+
7+
import org.hibernate.boot.cfgxml.internal.ConfigLoader;
8+
import org.hibernate.boot.registry.BootstrapServiceRegistry;
9+
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
10+
import org.hibernate.boot.registry.StandardServiceRegistry;
11+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
12+
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
13+
import org.hibernate.testing.junit4.BaseUnitTestCase;
14+
import org.hibernate.testing.orm.junit.JiraKey;
15+
import org.hibernate.testing.util.ServiceRegistryUtil;
16+
import org.junit.Test;
17+
18+
import java.io.File;
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
24+
import static org.junit.Assert.assertTrue;
25+
26+
/**
27+
* Test that makes sure the input stream inside {@link ConfigLoader#loadConfigXmlFile(File)}
28+
* gets closed.
29+
*
30+
* @author Mehmet Ali Emektar(inspired from CfgXmlResourceNameClosingTest)
31+
*/
32+
@JiraKey( value = "HHH-12986" )
33+
public class CfgXmlResourceFileClosingTest extends BaseUnitTestCase {
34+
private static class InputStreamWrapper extends InputStream {
35+
private final InputStream wrapped;
36+
private boolean wasClosed = false;
37+
38+
public InputStreamWrapper(InputStream wrapped) {
39+
this.wrapped = wrapped;
40+
}
41+
42+
@Override
43+
public int read() throws IOException {
44+
return wrapped.read();
45+
}
46+
47+
@Override
48+
public void close() throws IOException {
49+
wrapped.close();
50+
wasClosed = true;
51+
super.close();
52+
}
53+
54+
public boolean wasClosed() {
55+
return wasClosed;
56+
}
57+
}
58+
59+
private static class LocalClassLoaderServiceImpl extends ClassLoaderServiceImpl {
60+
final List<InputStreamWrapper> openedStreams = new ArrayList<InputStreamWrapper>();
61+
boolean stopped = false;
62+
63+
@Override
64+
public InputStream locateResourceStream(String name) {
65+
InputStreamWrapper stream = new InputStreamWrapper( super.locateResourceStream( name ) );
66+
openedStreams.add( stream );
67+
return stream;
68+
}
69+
70+
@Override
71+
public void stop() {
72+
for ( InputStreamWrapper openedStream : openedStreams ) {
73+
if ( !openedStream.wasClosed ) {
74+
try {
75+
openedStream.close();
76+
}
77+
catch (IOException ignore) {
78+
}
79+
}
80+
}
81+
openedStreams.clear();
82+
stopped = true;
83+
super.stop();
84+
}
85+
}
86+
87+
LocalClassLoaderServiceImpl classLoaderService = new LocalClassLoaderServiceImpl();
88+
89+
@Test
90+
public void testStreamClosing() {
91+
String filePath = "src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml";
92+
File cfgXmlFile = new File(filePath);
93+
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
94+
.applyClassLoaderService( classLoaderService )
95+
.build();
96+
StandardServiceRegistry ssr = ServiceRegistryUtil.serviceRegistryBuilder( bsr )
97+
.configure( cfgXmlFile)
98+
.build();
99+
try {
100+
for ( InputStreamWrapper openedStream : classLoaderService.openedStreams ) {
101+
assertTrue( openedStream.wasClosed );
102+
}
103+
}
104+
finally {
105+
StandardServiceRegistryBuilder.destroy( ssr );
106+
}
107+
108+
assertTrue( classLoaderService.stopped );
109+
}
110+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!--
2+
~ SPDX-License-Identifier: Apache-2.0
3+
~ Copyright Red Hat Inc. and Hibernate Authors
4+
-->
5+
<!DOCTYPE hibernate-configuration PUBLIC
6+
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
7+
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
8+
9+
<hibernate-configuration>
10+
<session-factory>
11+
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
12+
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
13+
<property name="hibernate.connection.username">sa</property>
14+
<property name="hibernate.connection.password"></property>
15+
<property name="hibernate.connection.url">jdbc:hsqldb:.</property>
16+
<property name="hibernate.cache.use_query_cache">true</property>
17+
<property name="hibernate.cache.region_prefix">hibernate.test</property>
18+
<property name="hibernate.jdbc.batch_size">0</property>
19+
<property name="hibernate.max_fetch_depth">3</property>
20+
<property name="hibernate.hbm2ddl.auto">create-drop</property>
21+
<property name="hibernate.generate_statistics">true</property>
22+
<property name="hibernate.cache.region.factory_class">org.hibernate.testing.cache.CachingRegionFactory</property>
23+
<mapping class="org.hibernate.orm.test.jpa.Item"/>
24+
<mapping class="org.hibernate.orm.test.jpa.Cat"/>
25+
<mapping class="org.hibernate.orm.test.jpa.Kitten"/>
26+
<mapping class="org.hibernate.orm.test.jpa.Distributor"/>
27+
<class-cache class="org.hibernate.orm.test.jpa.Item" usage="read-write"/>
28+
<collection-cache collection="org.hibernate.orm.test.jpa.Item.distributors" usage="read-write" region="RegionName"/>
29+
</session-factory>
30+
</hibernate-configuration>

0 commit comments

Comments
 (0)