/*
* Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden
* Copyright (c) 2010, 2011 PostgreSQL Global Development Group
*
* Distributed under the terms shown in the file COPYRIGHT
* found in the root folder of this project or at
* http://wiki.tada.se/index.php?title=PLJava_License
*/
package org.postgresql.pljava.jdbc;
import java.io.BufferedInputStream;
import java.io.CharConversionException;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
/**
* @author Thomas Hallgren
*/
public class ClobValue extends Reader implements Clob
{
public static int getReaderLength(Reader value) throws SQLException
{
try
{
value.mark(Integer.MAX_VALUE);
long length = value.skip(Long.MAX_VALUE);
if(length > Integer.MAX_VALUE)
throw new SQLException("stream content too large");
value.reset();
return (int)length;
}
catch(IOException e)
{
throw new SQLException(e.getMessage());
}
}
private long m_markPos;
private final long m_nChars;
private final Reader m_reader;
private long m_readerPos;
public ClobValue(Reader reader, long nChars)
{
m_reader = reader;
m_nChars = nChars;
m_readerPos = 0L;
m_markPos = 0L;
}
public ClobValue(String value)
{
this(new StringReader(value), value.length());
}
public void close() throws IOException
{
m_reader.close();
m_readerPos = 0;
m_markPos = 0;
}
public InputStream getAsciiStream()
{
return new BufferedInputStream(new InputStream()
{
public int read() throws IOException
{
int nextChar = ClobValue.this.read();
if(nextChar > 127)
throw new CharConversionException(
"Non ascii character in Clob data");
return nextChar;
}
});
}
public Reader getCharacterStream()
{
return this;
}
public String getSubString(long pos, int length) throws SQLException
{
if(pos < 0L || length < 0)
throw new IllegalArgumentException();
if(length == 0)
return "";
if(pos + length > m_nChars)
throw new SQLException("Attempt to read beyond end of Clob data");
long skip = pos - m_readerPos;
if(skip < 0)
throw new SQLException("Cannot position Clob stream backwards");
try
{
if(skip > 0)
this.skip(skip);
char[] buf = new char[length];
int nr = this.read(buf);
if(nr < length)
throw new SQLException("Clob data read not fulfilled");
return new String(buf);
}
catch(IOException e)
{
throw new SQLException("Error reading Blob data: " + e.getMessage());
}
}
public long length()
{
return m_nChars;
}
public synchronized void mark(int readLimit) throws IOException
{
m_reader.mark(readLimit);
m_markPos = m_readerPos;
}
public boolean markSupported()
{
return m_reader.markSupported();
}
/**
* Not supported.
*/
public long position(Clob pattern, long start)
{
throw new UnsupportedOperationException();
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public long position(String pattern, long start)
{
throw new UnsupportedOperationException();
}
public synchronized int read() throws IOException
{
int rs = m_reader.read();
m_readerPos++;
return rs;
}
public synchronized int read(char[] b) throws IOException
{
int rs = m_reader.read(b);
m_readerPos += rs;
return rs;
}
public synchronized int read(char[] b, int off, int len) throws IOException
{
int rs = m_reader.read(b, off, len);
m_readerPos += rs;
return rs;
}
public synchronized boolean ready() throws IOException
{
return m_reader.ready();
}
public synchronized void reset() throws IOException
{
m_reader.reset();
m_readerPos = m_markPos;
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public OutputStream setAsciiStream(long pos)
{
throw new UnsupportedOperationException();
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public Writer setCharacterStream(long pos)
{
throw new UnsupportedOperationException();
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public int setString(long pos, String str)
{
throw new UnsupportedOperationException();
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public int setString(long pos, String str, int offset, int len)
{
throw new UnsupportedOperationException();
}
public synchronized long skip(long nBytes) throws IOException
{
long skipped = m_reader.skip(nBytes);
m_readerPos += skipped;
return skipped;
}
/**
* In this method is not supported by <code>ClobValue</code>
*/
public void truncate(long len)
{
throw new UnsupportedOperationException();
}
//************************************************************
// Non-implementation of JDBC 4 methods.
//************************************************************
public Reader getCharacterStream(long pos,
long length)
throws SQLException
{
throw new SQLFeatureNotSupportedException
( this.getClass()
+ ".getCharacterStream( long,long ) not implemented yet.",
"0A000" );
}
public void free()
throws SQLException
{
throw new SQLFeatureNotSupportedException
( this.getClass()
+ ".free() not implemented yet.",
"0A000" );
}
}