Permalink
Browse files

[jdbc-driver] Support for binary types (BLOB, byte array, input stream)

  • Loading branch information...
cchantep
cchantep committed Aug 2, 2014
1 parent 43257c1 commit 194d549fca55e35ea07c175f0f12edda1c79a85a
@@ -0,0 +1,297 @@
package acolyte.jdbc;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialBlob;
/**
* Binary large object.
*
* @author Cedric Chantepie
*/
final class Blob implements java.sql.Blob {
// --- Shared ---
/**
* Empty data
*/
private static final byte[] NO_BYTE = new byte[0];
/**
* Empty stream
*/
private static final ByteArrayInputStream NO_DATA =
new ByteArrayInputStream(NO_BYTE);
// --- Properties ---
/**
* Underlying blob
*/
private java.sql.Blob underlying = null;
// --- Constructors ---
/**
* No-arg constructor.
*/
private Blob() throws SQLException { }
/**
* Bulk constructor.
*/
public Blob(final byte[] bytes) throws SQLException {
this.underlying = new SerialBlob(bytes);
} // end of <init>
/**
* Returns nil BLOB.
*/
public static Blob Nil() throws SQLException { return new Blob(); }
// --- Blob implementation ---
/**
* {@inheritDoc}
*/
public void free() throws SQLException {
synchronized (this) {
if (this.underlying == null) return;
// ---
this.underlying.free();
} // end of sync
} // end of free
/**
* {@inheritDoc}
*/
public InputStream getBinaryStream() throws SQLException {
synchronized (this) {
if (this.underlying == null) return NO_DATA;
// ---
return this.underlying.getBinaryStream();
} // end of sync
} // end of getBinaryStream
/**
* {@inheritDoc}
*/
public InputStream getBinaryStream(final long pos, final long length)
throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (pos > 1) {
throw new SQLException("Invalid position: " + pos);
} // end of if
return NO_DATA;
} // end of if
// ---
return this.underlying.getBinaryStream(pos, length);
} // end of sync
} // end of getBinaryStream
/**
* {@inheritDoc}
*/
public byte[] getBytes(final long pos, final int length)
throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (pos > 1) {
throw new SQLException("Invalid position: " + pos);
} // end of if
return NO_BYTE;
} // end of if
// ---
return this.underlying.getBytes(pos, length);
} // end of sync
} // end of getBytes
/**
* {@inheritDoc}
*/
public long length() throws SQLException {
synchronized (this) {
if (this.underlying == null) {
return 0L;
} // end of if
return this.underlying.length();
} // end of sync
} // end of length
/**
* {@inheritDoc}
*/
public long position(final java.sql.Blob pattern, final long start)
throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (start > 1) {
throw new SQLException("Invalid offset: " + start);
} // end of if
return -1L;
} // end of if
return this.underlying.position(pattern, start);
} // end of sync
} // end of position
/**
* {@inheritDoc}
*/
public long position(final byte[] pattern, final long start)
throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (start > 1) {
throw new SQLException("Invalid offset: " + start);
} // end of if
return -1L;
} // end of if
return this.underlying.position(pattern, start);
} // end of sync
} // end of position
/**
* {@inheritDoc}
* @throw SQLFeatureNotSupportedException if this BLOB is empty
*/
public OutputStream setBinaryStream(final long pos) throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (pos > 1) {
throw new SQLException("Invalid position: " + pos);
} // end of if
throw new SQLFeatureNotSupportedException("Cannot write to empty BLOB");
} // end of if
// ---
return this.underlying.setBinaryStream(pos);
} // end of sync
} // end of setBinaryStream
/**
* {@inheritDoc}
* @see #setBytes(long, bytes[], offset, int)
*/
public int setBytes(final long pos, byte[] bytes) throws SQLException {
if (bytes == null) {
throw new IllegalArgumentException("No byte to be set");
} // end of if
return setBytes(pos, bytes, 0, bytes.length);
} // end of setBytes
/**
* {@inheritDoc}
*/
public int setBytes(final long pos, byte[] bytes,
final int offset, final int len) throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (pos > 1) {
throw new SQLException("Invalid position: " + pos);
} // end of if
if (len < 0) {
throw new IllegalArgumentException("Invalid bytes length: "
+ len);
} // end of if
// ---
final byte[] copy = new byte[len];
try {
System.arraycopy(bytes, offset, copy, 0, len);
} catch (Exception e) {
throw new IllegalArgumentException("Fails to prepare binary data", e);
} // end of catch
// ---
this.underlying = new SerialBlob(copy);
return len;
} // end of if
// ---
return this.underlying.setBytes(pos, bytes, offset, len);
} // end of sync
} // end of setBytes
/**
* {@inheritDoc}
*/
public void truncate(final long len) throws SQLException {
synchronized (this) {
if (this.underlying == null) {
if (len < 0) {
throw new SQLException("Invalid length: " + len);
} // end of if
return;
} // end of if
// ---
this.underlying.truncate(len);
} // end of truncate
} // end of truncate
// --- Object support ---
/**
* {@inheritDoc}
*/
public boolean equals(Object o) {
if (o == null || !(o instanceof Blob)) {
return false;
} // end of if
// ---
final Blob other = (Blob) o;
return ((this.underlying == null && other.underlying == null) ||
(this.underlying != null &&
this.underlying.equals(other.underlying)));
} // end of equals
/**
* {@inheritDoc}
*/
public int hashCode() {
return (this.underlying == null) ? 3 : this.underlying.hashCode();
} // end of hashCode
} // end of class Blob
@@ -28,7 +28,7 @@
*
* @author Cedric Chantepie
*/
public final class Connection implements java.sql.Connection {
public class Connection implements java.sql.Connection {
// --- Properties ---
/**
@@ -578,10 +578,17 @@ public Clob createClob() throws SQLException {
/**
* {@inheritDoc}
* @throws java.sql.SQLFeatureNotSupportedException
* @see #createBlob(byte[])
*/
public Blob createBlob() throws SQLException {
throw new SQLFeatureNotSupportedException();
return acolyte.jdbc.Blob.Nil();
} // end of createBlob
/**
* Returns a BLOB with given |data|.
*/
public Blob createBlob(final byte[] data) throws SQLException {
return new javax.sql.rowset.serial.SerialBlob(data);
} // end of createBlob
/**
Oops, something went wrong.

0 comments on commit 194d549

Please sign in to comment.