/*******************************************************************************
* Copyright (c) 2014 BestSolution.at and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
*******************************************************************************/
package at.bestsolution.persistence.java.internal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import at.bestsolution.persistence.java.JavaSession;
public class LazyBlob implements Blob {
private Object id;
private String table;
private String blobColumn;
private String idColumn;
private JavaSession session;
private static final Logger LOGGER = Logger.getLogger(LazyBlob.class);
public LazyBlob(JavaSession session, String table, String blobColumn, String idColumn, Object id) {
if( LOGGER.isDebugEnabled() ) {
LOGGER.debug("LazyBlob Table: '"+table+"', Id-Column: '"+idColumn+"' = '"+id+"', Blob-Column: '"+blobColumn+"' ");
}
this.session = session;
this.table = table;
this.blobColumn = blobColumn;
this.idColumn = idColumn;
this.id = id;
}
@Override
public void free() throws SQLException {
}
@Override
public InputStream getBinaryStream() throws SQLException {
return new BlobDataInputStream();
}
private class BlobDataInputStream extends InputStream {
private Connection blobConnection;
private Blob blob;
private InputStream realStream;
public BlobDataInputStream() throws SQLException {
final boolean debug = LOGGER.isDebugEnabled();
if (debug) {
LOGGER.debug("begin binary stream for blob data: Table: '"+table+"', Id-Column: '"+idColumn+"' = '"+id+"', Blob-Column: '"+blobColumn+"' ");
}
blobConnection = session.checkoutConnection();
final String query = "SELECT \"" + blobColumn + "\" FROM " + table + " WHERE " + idColumn + " = ?";
if( debug ) {
LOGGER.debug("Query:" + query);
LOGGER.debug("Parameter: " + id);
}
final PreparedStatement stmt = blobConnection.prepareStatement(query);
stmt.setObject(1, id);
final ResultSet set = stmt.executeQuery();
if( set.next() ) {
blob = set.getBlob(1);
realStream = blob.getBinaryStream();
}
else {
throw new SQLException("could not fetch blob!");
}
}
@Override
public int read() throws IOException {
return realStream.read();
}
@Override
public int read(byte[] b) throws IOException {
return realStream.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return realStream.read(b, off, len);
}
@Override
public synchronized void reset() throws IOException {
realStream.reset();
}
@Override
public boolean markSupported() {
return realStream.markSupported();
}
@Override
public int available() throws IOException {
return realStream.available();
}
@Override
public synchronized void mark(int readlimit) {
realStream.mark(readlimit);
}
@Override
public long skip(long n) throws IOException {
return realStream.skip(n);
}
@Override
public void close() throws IOException {
final boolean debug = LOGGER.isDebugEnabled();
if (debug) {
LOGGER.debug("end binary stream for blob data: Table: '"+table+"', Id-Column: '"+idColumn+"' = '"+id+"', Blob-Column: '"+blobColumn+"' ");
}
try {
blob.free();
} catch (SQLException e) {
}
session.returnConnection(blobConnection);
}
}
@Override
public InputStream getBinaryStream(long pos, long length) throws SQLException {
throw new UnsupportedOperationException("This blob only supports an input stream");
}
@Override
public byte[] getBytes(long pos, int length) throws SQLException {
throw new UnsupportedOperationException("This blob only supports an input stream");
}
@Override
public long length() throws SQLException {
throw new UnsupportedOperationException("This blob only supports an input stream");
}
@Override
public long position(byte[] pattern, long start) throws SQLException {
throw new UnsupportedOperationException("This blob only supports an input stream");
}
@Override
public long position(Blob pattern, long start) throws SQLException {
throw new UnsupportedOperationException("This blob only supports an input stream");
}
@Override
public OutputStream setBinaryStream(long pos) throws SQLException {
throw new UnsupportedOperationException("This is a readonly blob");
}
@Override
public int setBytes(long pos, byte[] bytes) throws SQLException {
throw new UnsupportedOperationException("This is a readonly blob");
}
@Override
public int setBytes(long pos, byte[] bytes, int offset, int len)
throws SQLException {
throw new UnsupportedOperationException("This is a readonly blob");
}
@Override
public void truncate(long len) throws SQLException {
throw new UnsupportedOperationException("This is a readonly blob");
}
// class WrappedInputStream extends InputStream {
// private InputStream wrapped;
//
// public WrappedInputStream(InputStream wrapped) {
// this.wrapped = wrapped;
// }
//
// @Override
// public int read() throws IOException {
// return wrapped.read();
// }
//
// @Override
// public int available() throws IOException {
// return wrapped.available();
// }
//
// @Override
// public void close() throws IOException {
// wrapped.close();
// }
//
// @Override
// public synchronized void mark(int readlimit) {
// wrapped.mark(readlimit);
// }
//
// @Override
// public boolean markSupported() {
// return wrapped.markSupported();
// }
//
// @Override
// public int read(byte[] b) throws IOException {
// return wrapped.read(b);
// }
//
// @Override
// public int read(byte[] b, int off, int len) throws IOException {
// return wrapped.read(b, off, len);
// }
//
// @Override
// public boolean equals(Object obj) {
// return wrapped.equals(obj);
// }
//
// @Override
// public int hashCode() {
// return wrapped.hashCode();
// }
//
// @Override
// public synchronized void reset() throws IOException {
// wrapped.reset();
// }
//
// @Override
// public long skip(long n) throws IOException {
// return wrapped.skip(n);
// }
//
// @Override
// public String toString() {
// return wrapped.toString();
// }
// }
}