1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/*-------------------------------------------------------------------------
*
* Copyright (c) 2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2BlobClob.java,v 1.3 2005/05/09 03:17:18 jurka Exp $
*
*-------------------------------------------------------------------------
*/
package org.postgresql.jdbc2;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.SQLException;
import org.postgresql.PGConnection;
import org.postgresql.largeobject.LargeObject;
import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.util.GT;
import org.postgresql.util.PSQLState;
import org.postgresql.util.PSQLException;
/**
* This class holds all of the methods common to both Blobs and Clobs.
*
* At the moment only Blob uses this, but the intention is that Clob
* eventually will once we figure out what to do with encodings.
*
* @author Michael Barker <mailto:mike@middlesoft.co.uk>
*
*/
public class AbstractJdbc2BlobClob
{
private LargeObject lo;
public AbstractJdbc2BlobClob(PGConnection conn, int oid) throws SQLException
{
LargeObjectManager lom = conn.getLargeObjectAPI();
this.lo = lom.open(oid);
}
public long length() throws SQLException
{
return lo.size();
}
public byte[] getBytes(long pos, int length) throws SQLException
{
assertPosition(pos);
lo.seek((int)(pos-1), LargeObject.SEEK_SET);
return lo.read(length);
}
public InputStream getBinaryStream() throws SQLException
{
return lo.getInputStream();
}
/**
* Iterate over the buffer looking for the specified pattern
*
* @param pattern A pattern of bytes to search the blob for.
* @param start The position to start reading from.
*/
public long position(byte[] pattern, long start) throws SQLException
{
assertPosition(start, pattern.length);
int position = 1;
int patternIdx = 0;
long result = -1;
int tmpPosition = 1;
for (LOIterator i = new LOIterator(start-1); i.hasNext(); position++)
{
byte b = i.next();
if (b == pattern[patternIdx])
{
if (patternIdx == 0)
{
tmpPosition = position;
}
patternIdx++;
if (patternIdx == pattern.length)
{
result = tmpPosition;
break;
}
}
else
{
patternIdx = 0;
}
}
return result;
}
/**
* Iterates over a large object returning byte values. Will buffer
* the data from the large object.
*
*
*/
private class LOIterator
{
private static final int BUFFER_SIZE = 8096;
private byte buffer[] = new byte[BUFFER_SIZE];
private int idx = BUFFER_SIZE;
private int numBytes = BUFFER_SIZE;
public LOIterator(long start) throws SQLException
{
lo.seek((int) start);
}
public boolean hasNext() throws SQLException
{
boolean result = false;
if (idx < numBytes)
{
result = true;
}
else
{
numBytes = lo.read(buffer, 0, BUFFER_SIZE);
idx = 0;
result = (numBytes > 0);
}
return result;
}
private byte next()
{
return buffer[idx++];
}
}
/**
* This is simply passing the byte value of the pattern Blob
*/
public long position(Blob pattern, long start) throws SQLException
{
return position(pattern.getBytes(1, (int)pattern.length()), start);
}
/**
* Expose large object to derived classes.
*/
protected LargeObject getLO()
{
return lo;
}
/**
* Throws an exception if the pos value exceeds the max value by
* which the large object API can index.
*
* @param pos Position to write at.
*/
protected void assertPosition(long pos) throws SQLException
{
assertPosition(pos, 0);
}
/**
* Throws an exception if the pos value exceeds the max value by
* which the large object API can index.
*
* @param pos Position to write at.
* @param len number of bytes to write.
*/
protected void assertPosition(long pos, long len) throws SQLException
{
if (pos < 1)
{
throw new PSQLException(GT.tr("LOB positioning offsets start at 1."), PSQLState.INVALID_PARAMETER_VALUE);
}
if (pos + len - 1 > Integer.MAX_VALUE)
{
throw new PSQLException(GT.tr("PostgreSQL LOBs can only index to: {0}", new Integer(Integer.MAX_VALUE)), PSQLState.INVALID_PARAMETER_VALUE);
}
}
}
|