src-main.org.awakefw.sql.jdbc.BlobHttp Maven / Gradle / Ivy
Show all versions of awake-sql Show documentation
/*
* This file is part of Awake SQL.
* Awake SQL: Remote JDBC access over HTTP.
* Copyright (C) 2013, KawanSoft SAS
* (http://www.kawansoft.com). All rights reserved.
*
* Awake SQL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Awake SQL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*
* If you develop commercial activities using Awake SQL, you must:
* a) disclose and distribute all source code of your own product,
* b) license your own product under the GNU General Public License.
*
* You can be released from the requirements of the license by
* purchasing a commercial license. Buying such a license will allow you
* to ship Awake SQL with your closed source products without disclosing
* the source code.
*
* For more information, please contact KawanSoft SAS at this
* address: [email protected]
*
* Any modifications to this file must keep this entire header
* intact.
*/
package org.awakefw.sql.jdbc;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import org.apache.commons.io.IOUtils;
import org.awakefw.file.util.AwakeFileUtil;
import org.awakefw.file.util.KeepTempFilePolicyParms;
import org.awakefw.file.util.Tag;
/**
* Awake Blob.
*/
public class BlobHttp implements Blob {
private static final String BLOB_IS_NOT_ACCESSIBLE_ANYMORE = "BLOB is not accessible anymore.";
private static final String BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION = Tag.AWAKE
+ "BLOB method is not yet implemented in Awake SQL.";
/** The file that wrap the Blob */
private File file = null;
/**
* The Output Stream returned by setBinaryStream(long pos). Keep as field to
* close it if necessary
*/
private OutputStream outputStream = null;
/** The InputStream returned by getBinaryStream(). Keep as field to close it if necessary */
private InputStream inputStream = null;
/**
* Default Constructor
*/
public BlobHttp() {
}
/**
* Constructor used when reading a downloaded Blob
*
* @param in
* the input stream of the Blob
*/
public BlobHttp(InputStream in) throws SQLException {
file = BlobHttp.createUniqueBlobFile();
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
IOUtils.copy(in, out);
} catch (Exception e) {
throw new SQLException(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
/**
* Create a unique blob file container
*
* @return a unique blob file container
*/
static File createUniqueBlobFile() {
String unique = AwakeFileUtil.getUniqueId();
File file = new File(AwakeFileUtil.getAwakeTempDir() + File.separator + "local-blob-" + unique
+ ".awake");
return file;
}
/**
* Returns the underlying file
*
* @return the underlying file
*/
public File getFile() {
return file;
}
/**
* Returns the number of bytes in the BLOB
value designated by
* this Blob
object.
*
* @return length of the BLOB
in bytes
* @exception SQLException
* if there is an error accessing the length of the
* BLOB
* @since 1.2
*/
@Override
public long length() throws SQLException {
// Before reading, close the Output Stream if user forgot it
IOUtils.closeQuietly(outputStream);
if (file == null) {
return 0;
}
if (!file.exists()) {
throw new SQLException(BLOB_IS_NOT_ACCESSIBLE_ANYMORE);
}
return this.file.length();
}
/**
* Retrieves all or part of the BLOB
value that this
* Blob
object represents, as an array of bytes. This
* byte
array contains up to length
consecutive
* bytes starting at position pos
.
*
* @param pos
* the ordinal position of the first byte in the
* BLOB
value to be extracted; the first byte is at
* position 1
* @param length
* the number of consecutive bytes to be copied
* @return a byte array containing up to length
consecutive
* bytes from the BLOB
value designated by this
* Blob
object, starting with the byte at position
* pos
* @exception SQLException
* if there is an error accessing the BLOB
value
* @see #setBytes
* @since 1.2
*/
@Override
public byte[] getBytes(long pos, int length) throws SQLException {
// Before reading, close the Output Stream if user forgot it
IOUtils.closeQuietly(outputStream);
if (!file.exists()) {
throw new SQLException(BLOB_IS_NOT_ACCESSIBLE_ANYMORE);
}
// Close silently the OutputStream if use forgot it
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[length];
in.skip(pos - 1);
in.read(b);
return b;
} catch (IOException e) {
throw new SQLException(e);
} finally {
IOUtils.closeQuietly(in);
}
}
/**
* Retrieves the BLOB
value designated by this
* Blob
instance as a stream.
*
* @return a stream containing the BLOB
data
* @exception SQLException
* if there is an error accessing the BLOB
value
* @see #setBinaryStream
* @since 1.2
*/
@Override
public InputStream getBinaryStream() throws SQLException {
// Before reading, close the Output Stream if user forgot it
IOUtils.closeQuietly(outputStream);
if (file == null) {
return null;
}
if (!file.exists()) {
throw new SQLException(BLOB_IS_NOT_ACCESSIBLE_ANYMORE);
}
try {
inputStream = new BufferedInputStream(
new FileInputStream(file));
return inputStream;
} catch (IOException e) {
throw new SQLException(e);
}
}
/**
* Retrieves the byte position at which the specified byte array
* pattern
begins within the BLOB
value that this
* Blob
object represents. The search for pattern
* begins at position start
.
*
* @param pattern
* the byte array for which to search
* @param start
* the position at which to begin searching; the first position
* is 1
* @return the position at which the pattern appears, else -1
* @exception SQLException
* if there is an error accessing the BLOB
* @since 1.2
*/
@Override
public long position(byte[] pattern, long start) throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
/**
* Retrieves the byte position in the BLOB
value designated by
* this Blob
object at which pattern
begins. The
* search begins at position start
.
*
* @param pattern
* the Blob
object designating the BLOB
* value for which to search
* @param start
* the position in the BLOB
value at which to begin
* searching; the first position is 1
* @return the position at which the pattern begins, else -1
* @exception SQLException
* if there is an error accessing the BLOB
value
* @since 1.2
*/
@Override
public long position(Blob pattern, long start) throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
//
//
// -------------------------- JDBC 3.0 -----------------------------------
//
//
/**
* Writes the given array of bytes to the BLOB
value that this
* Blob
object represents, starting at position
* pos
, and returns the number of bytes written.
*
* @param pos
* the position in the BLOB
object at which to start
* writing
* @param bytes
* the array of bytes to be written to the BLOB
* value that this Blob
object represents
* @return the number of bytes written
* @exception SQLException
* if there is an error accessing the BLOB
value
* @see #getBytes
* @since 1.4
*/
@Override
public int setBytes(long pos, byte[] bytes) throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
/**
* Writes all or part of the given byte
array to the
* BLOB
value that this Blob
object represents and
* returns the number of bytes written. Writing starts at position
* pos
in the BLOB
value; len
bytes
* from the given byte array are written.
*
* @param pos
* the position in the BLOB
object at which to start
* writing
* @param bytes
* the array of bytes to be written to this BLOB
* object
* @param offset
* the offset into the array bytes
at which to start
* reading the bytes to be set
* @param len
* the number of bytes to be written to the BLOB
* value from the array of bytes bytes
* @return the number of bytes written
* @exception SQLException
* if there is an error accessing the BLOB
value
* @see #getBytes
* @since 1.4
*/
@Override
public int setBytes(long pos, byte[] bytes, int offset, int len)
throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
/**
* Retrieves a stream that can be used to write to the BLOB
* value that this Blob
object represents. The stream begins at
* position pos
.
*
* @param pos
* the position in the BLOB
value at which to start
* writing
* @return a java.io.OutputStream
object to which data can be
* written
* @exception SQLException
* if there is an error accessing the BLOB
value
* @see #getBinaryStream
* @since 1.4
*/
@Override
public OutputStream setBinaryStream(long pos) throws SQLException {
file = createUniqueBlobFile();
try {
outputStream = new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
throw new SQLException(e);
}
return outputStream;
}
/**
* Truncates the BLOB
value that this Blob
object
* represents to be len
bytes in length.
*
* @param len
* the length, in bytes, to which the BLOB
value
* that this Blob
object represents should be
* truncated
* @exception SQLException
* if there is an error accessing the BLOB
value
* @since 1.4
*/
@Override
public void truncate(long len) throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
/**
* This method frees the Blob
object and releases the resources
* that it holds. The object is invalid once the free
method is
* called.
*
* After free
has been called, any attempt to invoke a method
* other than free
will result in a SQLException
* being thrown. If free
is called multiple times, the
* subsequent calls to free
are treated as a no-op.
*
*
* @throws SQLException
* if an error occurs releasing the Blob's resources
* @exception SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.6
*/
@Override
public void free() throws SQLException {
if (!KeepTempFilePolicyParms.KEEP_TEMP_FILE) {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
if (file != null) {
this.file.delete();
}
}
}
/**
* Closes the underlying input/output stream
*/
public void close() {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
/**
* Returns an InputStream
object that contains a partial
* Blob
value, starting with the byte specified by pos, which
* is length bytes in length.
*
* @param pos
* the offset to the first byte of the partial value to be
* retrieved. The first byte in the Blob
is at
* position 1
* @param length
* the length in bytes of the partial value to be retrieved
* @return InputStream
through which the partial
* Blob
value can be read.
* @throws SQLException
* if pos is less than 1 or if pos is greater than the number of
* bytes in the Blob
or if pos + length is greater
* than the number of bytes in the Blob
*
* @exception SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.6
*/
@Override
public InputStream getBinaryStream(long pos, long length)
throws SQLException {
throw new SQLFeatureNotSupportedException(
BLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
}
}
// EOF