org.kawanfw.sql.jdbc.ClobHttp.java Source code

Java tutorial

Introduction

Here is the source code for org.kawanfw.sql.jdbc.ClobHttp.java

Source

/*
 * This file is part of AceQL. 
 * AceQL: Remote JDBC access over HTTP.                                     
 * Copyright (C) 2015,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.                                
 *                                                                               
 * AceQL is free software; you can redistribute it and/or                 
 * modify it under the terms of the GNU Lesser General Public                    
 * License as published by the Free Software Foundation; either                  
 * version 2.1 of the License, or (at your option) any later version.            
 *                                                                               
 * AceQL 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 Lesser General Public              
 * License along with this library; if not, write to the Free Software           
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
 * 02110-1301  USA
 *
 * Any modifications to this file must keep this entire header
 * intact.
 */
package org.kawanfw.sql.jdbc;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;

import org.apache.commons.io.IOUtils;
import org.kawanfw.commons.util.FrameworkFileUtil;
import org.kawanfw.commons.util.Tag;

/**
 * Clob Wrapper. <br>
 * Implements all the Connection methods. Usage is exactly the same as a Clob.
 */

public class ClobHttp implements Clob {

    private static final String CLOB_IS_NOT_ACCESSIBLE_ANYMORE = "CLOB is not accessible anymore.)";

    private static final String CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION = Tag.PRODUCT
            + "CLOB method is not yet implemented.";

    /** The file that wrap the Blob */
    private File file = null;

    private Reader reader = null;
    private InputStream inputStream = null;

    private OutputStream outputStream = null;
    private Writer writer = null;

    /**
     * Default Constructor
     */
    ClobHttp() {
        file = ClobHttp.createUniqueClobFile();
    }

    /**
     * Constructor used when reading a downloaded Clob
     * 
     * @param reader
     *            the reader of the Clob
     */
    ClobHttp(Reader reader) throws SQLException {

        this();

        Writer writer = null;

        try {
            writer = new BufferedWriter(new FileWriter(file));
            IOUtils.copy(reader, writer);

        } catch (Exception e) {
            throw new SQLException(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(reader);
            IOUtils.closeQuietly(writer);
        }
    }

    // /**
    // * Constructor
    // *
    // * @param file
    // * a file that is wrapped by this CLOB
    // */
    // public ClobHttp(File file) {
    // this.file = file;
    // }

    /**
     * Create a unique clob file container
     * 
     * @return a unique clob file container
     */
    static File createUniqueClobFile() {
        String unique = FrameworkFileUtil.getUniqueId();
        File file = new File(
                FrameworkFileUtil.getKawansoftTempDir() + File.separator + "local-clob-" + unique + ".text");
        return file;
    }

    /**
     * Returns the underlying file
     * 
     * @return the underlying file
     */
    public File getFile() {
        return file;
    }

    /**
     * Retrieves the number of characters in the <code>CLOB</code> value
     * designated by this <code>Clob</code> object.
     * 
     * @return length of the <code>CLOB</code> in characters
     * @exception SQLException
     *                if there is an error accessing the length of the
     *                <code>CLOB</code> value
     * @since 1.2
     */
    @Override
    public long length() throws SQLException {

        // Before reading, close the Output Stream if user forgot it
        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(writer);

        if (file == null) {
            return 0;
        }

        if (!file.exists()) {
            throw new SQLException(CLOB_IS_NOT_ACCESSIBLE_ANYMORE);
        }

        return this.file.length();

    }

    /**
     * Retrieves a copy of the specified substring in the <code>CLOB</code>
     * value designated by this <code>Clob</code> object. The substring begins
     * at position <code>pos</code> and has up to <code>length</code>
     * consecutive characters.
     * 
     * @param pos
     *            the first character of the substring to be extracted. The
     *            first character is at position 1.
     * @param length
     *            the number of consecutive characters to be copied
     * @return a <code>String</code> that is the specified substring in the
     *         <code>CLOB</code> value designated by this <code>Clob</code>
     *         object
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @since 1.2
     */
    @Override
    public String getSubString(long pos, int length) throws SQLException {

        // Before reading, close the Output Stream if user forgot it
        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(writer);

        if (file == null) {
            return null;
        }

        if (!file.exists()) {
            throw new SQLException(CLOB_IS_NOT_ACCESSIBLE_ANYMORE);
        }

        try {
            reader = new BufferedReader(new FileReader(file));

            char[] c = new char[length];

            reader.skip(pos - 1);
            reader.read(c);

            return new String(c);
        } catch (IOException e) {
            throw new SQLException(e);
        } finally {
            IOUtils.closeQuietly(reader);
        }

    }

    /**
     * Retrieves the <code>CLOB</code> value designated by this
     * <code>Clob</code> object as a <code>java.io.Reader</code> object (or as a
     * stream of characters).
     * 
     * @return a <code>java.io.Reader</code> object containing the
     *         <code>CLOB</code> data
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @see #setCharacterStream
     * @since 1.2
     */
    @Override
    public Reader getCharacterStream() throws SQLException {

        // Before reading, close the Output Stream if user forgot it
        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(writer);

        if (file == null) {
            return null;
        }

        if (!file.exists()) {
            throw new SQLException(CLOB_IS_NOT_ACCESSIBLE_ANYMORE);
        }

        try {
            reader = new BufferedReader(new FileReader(file));
            return reader;
        } catch (IOException e) {
            throw new SQLException(e);
        }

    }

    /**
     * Retrieves the <code>CLOB</code> value designated by this
     * <code>Clob</code> object as an ascii stream.
     * 
     * @return a <code>java.io.InputStream</code> object containing the
     *         <code>CLOB</code> data
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @see #setAsciiStream
     * @since 1.2
     */
    @Override
    public InputStream getAsciiStream() throws SQLException {

        if (file == null) {
            return null;
        }

        if (!file.exists()) {
            throw new SQLException(CLOB_IS_NOT_ACCESSIBLE_ANYMORE);
        }

        try {
            inputStream = new BufferedInputStream(new FileInputStream(file));
            return inputStream;
        } catch (IOException e) {
            throw new SQLException(e);
        }
    }

    /**
     * Retrieves the character position at which the specified substring
     * <code>searchstr</code> appears in the SQL <code>CLOB</code> value
     * represented by this <code>Clob</code> object. The search begins at
     * position <code>start</code>.
     * 
     * @param searchstr
     *            the substring for which to search
     * @param start
     *            the position at which to begin searching; the first position
     *            is 1
     * @return the position at which the substring appears or -1 if it is not
     *         present; the first position is 1
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @since 1.2
     */
    @Override
    public long position(String searchstr, long start) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

    /**
     * Retrieves the character position at which the specified <code>Clob</code>
     * object <code>searchstr</code> appears in this <code>Clob</code> object.
     * The search begins at position <code>start</code>.
     * 
     * @param searchstr
     *            the <code>Clob</code> object for which to search
     * @param start
     *            the position at which to begin searching; the first position
     *            is 1
     * @return the position at which the <code>Clob</code> object appears or -1
     *         if it is not present; the first position is 1
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @since 1.2
     */
    @Override
    public long position(Clob searchstr, long start) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

    // ---------------------------- jdbc 3.0 -----------------------------------

    /**
     * Writes the given Java <code>String</code> to the <code>CLOB</code> value
     * that this <code>Clob</code> object designates at the position
     * <code>pos</code>.
     * 
     * @param pos
     *            the position at which to start writing to the
     *            <code>CLOB</code> value that this <code>Clob</code> object
     *            represents
     * @param str
     *            the string to be written to the <code>CLOB</code> value that
     *            this <code>Clob</code> designates
     * @return the number of characters written
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * 
     * @since 1.4
     */
    @Override
    public int setString(long pos, String str) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

    /**
     * Writes <code>len</code> characters of <code>str</code>, starting at
     * character <code>offset</code>, to the <code>CLOB</code> value that this
     * <code>Clob</code> represents.
     * 
     * @param pos
     *            the position at which to start writing to this
     *            <code>CLOB</code> object
     * @param str
     *            the string to be written to the <code>CLOB</code> value that
     *            this <code>Clob</code> object represents
     * @param offset
     *            the offset into <code>str</code> to start reading the
     *            characters to be written
     * @param len
     *            the number of characters to be written
     * @return the number of characters written
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * 
     * @since 1.4
     */
    @Override
    public int setString(long pos, String str, int offset, int len) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

    /**
     * Retrieves a stream to be used to write Ascii characters to the
     * <code>CLOB</code> value that this <code>Clob</code> object represents,
     * starting at position <code>pos</code>.
     * 
     * @param pos
     *            the position at which to start writing to this
     *            <code>CLOB</code> object
     * @return the stream to which ASCII encoded characters can be written
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @see #getAsciiStream
     * 
     * @since 1.4
     */
    @Override
    public OutputStream setAsciiStream(long pos) throws SQLException {

        // file = createUniqueClobFile();

        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
        } catch (FileNotFoundException e) {
            throw new SQLException(e);
        }

        return outputStream;

    }

    /**
     * Retrieves a stream to be used to write a stream of Unicode characters to
     * the <code>CLOB</code> value that this <code>Clob</code> object
     * represents, at position <code>pos</code>.
     * 
     * @param pos
     *            the position at which to start writing to the
     *            <code>CLOB</code> value
     * 
     * @return a stream to which Unicode encoded characters can be written
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * @see #getCharacterStream
     * 
     * @since 1.4
     */
    @Override
    public Writer setCharacterStream(long pos) throws SQLException {

        // file = createUniqueClobFile();

        try {
            writer = new BufferedWriter(new FileWriter(file));
        } catch (IOException e) {
            throw new SQLException(e);
        }

        return writer;

    }

    /**
     * Truncates the <code>CLOB</code> value that this <code>Clob</code>
     * designates to have a length of <code>len</code> characters.
     * 
     * @param len
     *            the length, in bytes, to which the <code>CLOB</code> value
     *            should be truncated
     * @exception SQLException
     *                if there is an error accessing the <code>CLOB</code> value
     * 
     * @since 1.4
     */
    @Override
    public void truncate(long len) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

    /**
     * This method frees the <code>Clob</code> object and releases the resources
     * the resources that it holds. The object is invalid once the
     * <code>free</code> method is called.
     * <p>
     * After <code>free</code> has been called, any attempt to invoke a method
     * other than <code>free</code> will result in a <code>SQLException</code>
     * being thrown. If <code>free</code> is called multiple times, the
     * subsequent calls to <code>free</code> are treated as a no-op.
     * <p>
     * 
     * @throws SQLException
     *             if an error occurs releasing the Clob's resources
     * 
     * @exception SQLFeatureNotSupportedException
     *                if the JDBC driver does not support this method
     * @since 1.6
     */
    @Override
    public void free() throws SQLException {

        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(reader);

        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(writer);

        if (file != null) {
            this.file.delete();
        }

    }

    /**
     * Closes the underlying input/output stream
     */
    public void close() {
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(reader);

        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(writer);
    }

    /**
     * Returns a <code>Reader</code> object that contains a partial
     * <code>Clob</code> value, starting with the character specified by pos,
     * which is length characters in length.
     * 
     * @param pos
     *            the offset to the first character of the partial value to be
     *            retrieved. The first character in the Clob is at position 1.
     * @param length
     *            the length in characters of the partial value to be retrieved.
     * @return <code>Reader</code> through which the partial <code>Clob</code>
     *         value can be read.
     * @throws SQLException
     *             if pos is less than 1 or if pos is greater than the number of
     *             characters in the <code>Clob</code> or if pos + length is
     *             greater than the number of characters in the
     *             <code>Clob</code>
     * 
     * @exception SQLFeatureNotSupportedException
     *                if the JDBC driver does not support this method
     * @since 1.6
     */
    @Override
    public Reader getCharacterStream(long pos, long length) throws SQLException {
        throw new SQLFeatureNotSupportedException(CLOB_FEATURE_NOT_SUPPORTED_IN_THIS_VERSION);
    }

}