001: /*-------------------------------------------------------------------------
002: *
003: * Copyright (c) 2003-2005, PostgreSQL Global Development Group
004: *
005: * IDENTIFICATION
006: * $PostgreSQL: pgjdbc/org/postgresql/largeobject/BlobOutputStream.java,v 1.12 2007/02/19 18:35:29 jurka Exp $
007: *
008: *-------------------------------------------------------------------------
009: */
010: package org.postgresql.largeobject;
011:
012: import java.io.IOException;
013: import java.io.OutputStream;
014: import java.sql.SQLException;
015:
016: /**
017: * This implements a basic output stream that writes to a LargeObject
018: */
019: public class BlobOutputStream extends OutputStream {
020: /**
021: * The parent LargeObject
022: */
023: private LargeObject lo;
024:
025: /**
026: * Buffer
027: */
028: private byte buf[];
029:
030: /**
031: * Size of the buffer (default 1K)
032: */
033: private int bsize;
034:
035: /**
036: * Position within the buffer
037: */
038: private int bpos;
039:
040: /**
041: * Create an OutputStream to a large object
042: * @param lo LargeObject
043: */
044: public BlobOutputStream(LargeObject lo) {
045: this (lo, 1024);
046: }
047:
048: /**
049: * Create an OutputStream to a large object
050: * @param lo LargeObject
051: * @param bsize The size of the buffer used to improve performance
052: */
053: public BlobOutputStream(LargeObject lo, int bsize) {
054: this .lo = lo;
055: this .bsize = bsize;
056: buf = new byte[bsize];
057: bpos = 0;
058: }
059:
060: public void write(int b) throws java.io.IOException {
061: checkClosed();
062: try {
063: if (bpos >= bsize) {
064: lo.write(buf);
065: bpos = 0;
066: }
067: buf[bpos++] = (byte) b;
068: } catch (SQLException se) {
069: throw new IOException(se.toString());
070: }
071: }
072:
073: public void write(byte[] buf, int off, int len)
074: throws java.io.IOException {
075: checkClosed();
076: try {
077: // If we have any internally buffered data, send it first
078: if (bpos > 0)
079: flush();
080:
081: if (off == 0 && len == buf.length)
082: lo.write(buf); // save a buffer creation and copy since full buffer written
083: else
084: lo.write(buf, off, len);
085: } catch (SQLException se) {
086: throw new IOException(se.toString());
087: }
088: }
089:
090: /**
091: * Flushes this output stream and forces any buffered output bytes
092: * to be written out. The general contract of <code>flush</code> is
093: * that calling it is an indication that, if any bytes previously
094: * written have been buffered by the implementation of the output
095: * stream, such bytes should immediately be written to their
096: * intended destination.
097: *
098: * @exception IOException if an I/O error occurs.
099: */
100: public void flush() throws IOException {
101: checkClosed();
102: try {
103: if (bpos > 0)
104: lo.write(buf, 0, bpos);
105: bpos = 0;
106: } catch (SQLException se) {
107: throw new IOException(se.toString());
108: }
109: }
110:
111: /**
112: * Closes this output stream and releases any system resources
113: * associated with this stream. The general contract of <code>close</code>
114: * is that it closes the output stream. A closed stream cannot perform
115: * output operations and cannot be reopened.
116: * <p>
117: * The <code>close</code> method of <code>OutputStream</code> does nothing.
118: *
119: * @exception IOException if an I/O error occurs.
120: */
121: public void close() throws IOException {
122: if (lo != null) {
123: try {
124: flush();
125: lo.close();
126: lo = null;
127: } catch (SQLException se) {
128: throw new IOException(se.toString());
129: }
130: }
131: }
132:
133: private void checkClosed() throws IOException {
134: if (lo == null)
135: throw new IOException("BlobOutputStream is closed");
136: }
137:
138: }
|