Java tutorial
/* * 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); } }