diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/DataBinder.java b/ebean-core-type/src/main/java/io/ebean/core/type/DataBinder.java index b08bb529a..d955445b9 100644 --- a/ebean-core-type/src/main/java/io/ebean/core/type/DataBinder.java +++ b/ebean-core-type/src/main/java/io/ebean/core/type/DataBinder.java @@ -174,4 +174,9 @@ public interface DataBinder { */ String popJson(); + /** + * Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo. + */ + Object popLastObject(); + } diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/InputStreamInfo.java b/ebean-core-type/src/main/java/io/ebean/core/type/InputStreamInfo.java new file mode 100644 index 000000000..67394a62b --- /dev/null +++ b/ebean-core-type/src/main/java/io/ebean/core/type/InputStreamInfo.java @@ -0,0 +1,27 @@ +package io.ebean.core.type; + +import java.io.InputStream; + +/** + * Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation + * + * @author Roland Praml, FOCONIS AG + */ +public class InputStreamInfo { + private final InputStream stream; + + private final long length; + + public InputStreamInfo(InputStream stream, long length) { + this.stream = stream; + this.length = length; + } + + public InputStream stream() { + return stream; + } + + public long length() { + return length; + } +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/bind/DataBind.java b/ebean-core/src/main/java/io/ebeaninternal/server/bind/DataBind.java index 3c4c1aedb..371a8cc3a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/bind/DataBind.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/bind/DataBind.java @@ -1,10 +1,14 @@ package io.ebeaninternal.server.bind; import io.ebean.core.type.DataBinder; +import io.ebean.core.type.InputStreamInfo; import io.ebeaninternal.api.CoreLog; import io.ebeaninternal.server.core.timezone.DataTimeZone; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; @@ -15,6 +19,7 @@ import static java.lang.System.Logger.Level.WARNING; public class DataBind implements DataBinder { + private static final Object UNBOUND = new Object(); private final DataTimeZone dataTimeZone; private final PreparedStatement pstmt; private final Connection connection; @@ -23,6 +28,8 @@ public class DataBind implements DataBinder { protected int pos; private String json; + private Object lastObject = UNBOUND; + public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) { this.dataTimeZone = dataTimeZone; this.pstmt = pstmt; @@ -65,16 +72,19 @@ public class DataBind implements DataBinder { @Override public void setObject(Object value) throws SQLException { pstmt.setObject(++pos, value); + lastObject = value; } @Override public final void setObject(Object value, int sqlType) throws SQLException { pstmt.setObject(++pos, value, sqlType); + lastObject = value; } @Override public void setNull(int jdbcType) throws SQLException { pstmt.setNull(++pos, jdbcType); + lastObject = null; } @Override @@ -96,7 +106,7 @@ public class DataBind implements DataBinder { } } - private void closeInputStreams() { + public void closeInputStreams() { if (inputStreams != null) { for (InputStream inputStream : inputStreams) { try { @@ -117,36 +127,43 @@ public class DataBind implements DataBinder { @Override public void setString(String value) throws SQLException { pstmt.setString(++pos, value); + lastObject = value; } @Override public final void setInt(int value) throws SQLException { pstmt.setInt(++pos, value); + lastObject = value; } @Override public final void setLong(long value) throws SQLException { pstmt.setLong(++pos, value); + lastObject = value; } @Override public final void setShort(short value) throws SQLException { pstmt.setShort(++pos, value); + lastObject = value; } @Override public final void setFloat(float value) throws SQLException { pstmt.setFloat(++pos, value); + lastObject = value; } @Override public final void setDouble(double value) throws SQLException { pstmt.setDouble(++pos, value); + lastObject = value; } @Override public final void setBigDecimal(BigDecimal value) throws SQLException { pstmt.setBigDecimal(++pos, value); + lastObject = value; } @Override @@ -157,6 +174,7 @@ public class DataBind implements DataBinder { } else { pstmt.setDate(++pos, value); } + lastObject = value; } @Override @@ -167,6 +185,7 @@ public class DataBind implements DataBinder { } else { pstmt.setTimestamp(++pos, value); } + lastObject = value; } @Override @@ -177,26 +196,31 @@ public class DataBind implements DataBinder { } else { pstmt.setTime(++pos, value); } + lastObject = value; } @Override public void setBoolean(boolean value) throws SQLException { pstmt.setBoolean(++pos, value); + lastObject = value; } @Override public void setBytes(byte[] value) throws SQLException { pstmt.setBytes(++pos, value); + lastObject = value; } @Override public void setByte(byte value) throws SQLException { pstmt.setByte(++pos, value); + lastObject = value; } @Override public void setChar(char value) throws SQLException { pstmt.setString(++pos, String.valueOf(value)); + lastObject = value; } @Override @@ -211,21 +235,34 @@ public class DataBind implements DataBinder { } inputStreams.add(inputStream); pstmt.setBinaryStream(++pos, inputStream, length); + lastObject = new InputStreamInfo(inputStream, length); } @Override public void setBlob(byte[] bytes) throws SQLException { pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length); + lastObject = bytes; } @Override public void setClob(String content) throws SQLException { pstmt.setCharacterStream(++pos, new StringReader(content), content.length()); + lastObject = content; } @Override public void setArray(String arrayType, Object[] elements) throws SQLException { pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements)); + lastObject = elements; } + @Override + public Object popLastObject() { + Object ret = lastObject; + lastObject = UNBOUND; + if (ret == UNBOUND) { + throw new IllegalStateException("No object bound"); + } + return ret; + } }