From 5ed9f08834b90776bed4ed7fc2ff6079a0d64157 Mon Sep 17 00:00:00 2001 From: mehmetali2003 Date: Tue, 28 Oct 2025 17:38:25 +0300 Subject: [PATCH] HHH-12986 HHH-12986 ConfigLoader does not close file when loading hibernate.cfg.xml --- .../boot/cfgxml/internal/ConfigLoader.java | 24 +++- .../cfgXml/CfgXmlResourceFileClosingTest.java | 110 ++++++++++++++++++ .../orm/test/boot/cfgXml/hibernate.cfg.xml | 30 +++++ 3 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/CfgXmlResourceFileClosingTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml diff --git a/hibernate-core/src/main/java/org/hibernate/boot/cfgxml/internal/ConfigLoader.java b/hibernate-core/src/main/java/org/hibernate/boot/cfgxml/internal/ConfigLoader.java index e25c28864dff..7f34393ee039 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/cfgxml/internal/ConfigLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/cfgxml/internal/ConfigLoader.java @@ -71,12 +71,26 @@ public LoadedConfig loadConfigXmlResource(String cfgXmlResourceName) { public LoadedConfig loadConfigXmlFile(File cfgXmlFile) { try { - final JaxbCfgHibernateConfiguration jaxbCfg = jaxbProcessorHolder.getValue().unmarshal( - new FileInputStream( cfgXmlFile ), - new Origin( SourceType.FILE, cfgXmlFile.getAbsolutePath() ) - ); + FileInputStream cfgFileStream = null; + try { + cfgFileStream = new FileInputStream( cfgXmlFile ); - return LoadedConfig.consume( jaxbCfg ); + final JaxbCfgHibernateConfiguration jaxbCfg = jaxbProcessorHolder.getValue().unmarshal( + cfgFileStream, + new Origin( SourceType.FILE, cfgXmlFile.getAbsolutePath() ) + ); + + return LoadedConfig.consume( jaxbCfg ); + } + finally { + try { + assert cfgFileStream != null; + cfgFileStream.close(); + } + catch (IOException e) { + log.debug( "Unable to close cfg.xml URL stream", e ); + } + } } catch (FileNotFoundException e) { throw new ConfigurationException( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/CfgXmlResourceFileClosingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/CfgXmlResourceFileClosingTest.java new file mode 100644 index 000000000000..7be0d48634c1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/CfgXmlResourceFileClosingTest.java @@ -0,0 +1,110 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.boot.cfgXml; + +import org.hibernate.boot.cfgxml.internal.ConfigLoader; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.util.ServiceRegistryUtil; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +/** + * Test that makes sure the input stream inside {@link ConfigLoader#loadConfigXmlFile(File)} + * gets closed. + * + * @author Mehmet Ali Emektar(inspired from CfgXmlResourceNameClosingTest) + */ +@JiraKey( value = "HHH-12986" ) +public class CfgXmlResourceFileClosingTest extends BaseUnitTestCase { + private static class InputStreamWrapper extends InputStream { + private final InputStream wrapped; + private boolean wasClosed = false; + + public InputStreamWrapper(InputStream wrapped) { + this.wrapped = wrapped; + } + + @Override + public int read() throws IOException { + return wrapped.read(); + } + + @Override + public void close() throws IOException { + wrapped.close(); + wasClosed = true; + super.close(); + } + + public boolean wasClosed() { + return wasClosed; + } + } + + private static class LocalClassLoaderServiceImpl extends ClassLoaderServiceImpl { + final List openedStreams = new ArrayList(); + boolean stopped = false; + + @Override + public InputStream locateResourceStream(String name) { + InputStreamWrapper stream = new InputStreamWrapper( super.locateResourceStream( name ) ); + openedStreams.add( stream ); + return stream; + } + + @Override + public void stop() { + for ( InputStreamWrapper openedStream : openedStreams ) { + if ( !openedStream.wasClosed ) { + try { + openedStream.close(); + } + catch (IOException ignore) { + } + } + } + openedStreams.clear(); + stopped = true; + super.stop(); + } + } + + LocalClassLoaderServiceImpl classLoaderService = new LocalClassLoaderServiceImpl(); + + @Test + public void testStreamClosing() { + String filePath = "src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml"; + File cfgXmlFile = new File(filePath); + BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder() + .applyClassLoaderService( classLoaderService ) + .build(); + StandardServiceRegistry ssr = ServiceRegistryUtil.serviceRegistryBuilder( bsr ) + .configure( cfgXmlFile) + .build(); + try { + for ( InputStreamWrapper openedStream : classLoaderService.openedStreams ) { + assertTrue( openedStream.wasClosed ); + } + } + finally { + StandardServiceRegistryBuilder.destroy( ssr ); + } + + assertTrue( classLoaderService.stopped ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml new file mode 100644 index 000000000000..9b428e6691d3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/boot/cfgXml/hibernate.cfg.xml @@ -0,0 +1,30 @@ + + + + + + org.hibernate.dialect.HSQLDialect + org.hsqldb.jdbcDriver + sa + + jdbc:hsqldb:. + true + hibernate.test + 0 + 3 + create-drop + true + org.hibernate.testing.cache.CachingRegionFactory + + + + + + + + \ No newline at end of file