Skip to content

Commit

Permalink
HHH-14725 Fix reset handling on BlobProxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Naros authored and beikov committed Dec 18, 2024
1 parent f469677 commit 3f93ec8
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public final class BlobProxy implements Blob, BlobImplementer {
// no longer necessary. The class name could be updated to reflect this but that would break APIs.

private final BinaryStream binaryStream;
private final int markBytes;
private boolean resetAllowed;
private boolean needsReset;

/**
Expand All @@ -47,7 +49,9 @@ public final class BlobProxy implements Blob, BlobImplementer {
* @see #generateProxy(byte[])
*/
private BlobProxy(byte[] bytes) {
binaryStream = new BinaryStreamImpl( bytes );
binaryStream = new ArrayBackedBinaryStream( bytes );
markBytes = bytes.length + 1;
setStreamMark();
}

/**
Expand All @@ -59,6 +63,18 @@ private BlobProxy(byte[] bytes) {
*/
private BlobProxy(InputStream stream, long length) {
this.binaryStream = new StreamBackedBinaryStream( stream, length );
this.markBytes = (int) length + 1;
setStreamMark();
}

private void setStreamMark() {
if ( binaryStream.getInputStream().markSupported() ) {
binaryStream.getInputStream().mark( markBytes );
resetAllowed = true;
}
else {
resetAllowed = false;
}
}

private InputStream getStream() throws SQLException {
Expand All @@ -73,7 +89,12 @@ public BinaryStream getUnderlyingStream() throws SQLException {
private void resetIfNeeded() throws SQLException {
try {
if ( needsReset ) {
if ( !resetAllowed ) {
throw new SQLException( "Underlying stream does not allow reset" );
}

binaryStream.getInputStream().reset();
setStreamMark();
}
}
catch ( IOException ioe) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.envers.integration.blob;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.fail;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Blob;

import org.hamcrest.Matchers;
import org.hibernate.engine.jdbc.proxy.BlobProxy;
import org.hibernate.envers.Audited;
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
import org.hibernate.orm.test.envers.Priority;
import org.junit.Test;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

/**
* @author Chris Cranford
*/
public class BasicBlobTest extends BaseEnversJPAFunctionalTestCase {

@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Asset.class };
}

@Test
@Priority(10)
public void initData() {
final Path path = Path.of( getClass().getResource( "./blob.txt" ).getPath() );
doInJPA( this::entityManagerFactory, entityManager -> {
try {
final Asset asset = new Asset();
asset.setFileName( "blob.txt" );

final InputStream stream = new BufferedInputStream( Files.newInputStream( path ) );
assertThat( stream.markSupported(), Matchers.is( true ) );

Blob blob = BlobProxy.generateProxy( stream, Files.size( path ) );

asset.setData( blob );
entityManager.persist( asset );
}
catch (Exception e) {
e.printStackTrace();
fail( "Failed to persist the entity" );
}
} );
}

@Audited
@Entity(name = "Asset")
public static class Asset {
@Id
@GeneratedValue
private Integer id;
private String fileName;
private Blob data;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

public Blob getData() {
return data;
}

public void setData(Blob data) {
this.data = data;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version='1.0' encoding='utf-8'?>
<!--
~ SPDX-License-Identifier: LGPL-2.1-or-later
~ Copyright Red Hat Inc. and Hibernate Authors
-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">create-drop</property>

<property name="show_sql">false</property>
<property name="format_sql">false</property>

<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="connection.url">jdbc:h2:mem:envers</property>
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>

<!--<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>-->
<!--<property name="connection.url">jdbc:mysql:///hibernate_tests?useUnicode=true&amp;characterEncoding=UTF-8</property>-->
<!--<property name="connection.driver_class">com.mysql.jdbc.Driver</property>-->
<!--<property name="connection.username">root</property>-->
<!--<property name="connection.password"></property>-->

<!--<property name="hibernate.jdbc.batch_size">100</property>-->
</session-factory>
</hibernate-configuration>

0 comments on commit 3f93ec8

Please sign in to comment.