001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.db.store;
031:
032: import com.caucho.vfs.TempBuffer;
033:
034: import java.io.IOException;
035: import java.io.Writer;
036:
037: class ClobWriter extends Writer {
038: private Store _store;
039:
040: private StoreTransaction _xa;
041:
042: private TempBuffer _tempBuffer;
043: private byte[] _buffer;
044: private int _offset;
045: private int _bufferEnd;
046:
047: private long _length;
048:
049: private Inode _inode;
050:
051: private byte[] _inodeBuffer;
052: private int _inodeOffset;
053:
054: /**
055: * Creates a blob output stream.
056: *
057: * @param store the output store
058: */
059: ClobWriter(StoreTransaction xa, Store store, byte[] inode,
060: int inodeOffset) {
061: init(xa, store, inode, inodeOffset);
062: }
063:
064: /**
065: * Creates a blob output stream.
066: *
067: * @param store the output store
068: */
069: ClobWriter(Inode inode) {
070: init(null, inode.getStore(), inode.getBuffer(), 0);
071:
072: _inode = inode;
073: }
074:
075: /**
076: * Initialize the output stream.
077: */
078: public void init(StoreTransaction xa, Store store, byte[] inode,
079: int inodeOffset) {
080: if (xa == null)
081: xa = RawTransaction.create();
082:
083: _xa = xa;
084:
085: _store = store;
086:
087: _length = 0;
088:
089: _inodeBuffer = inode;
090: _inodeOffset = inodeOffset;
091:
092: Inode.clear(_inodeBuffer, _inodeOffset);
093:
094: _offset = 0;
095:
096: _tempBuffer = TempBuffer.allocate();
097: _buffer = _tempBuffer.getBuffer();
098: _bufferEnd = _buffer.length;
099: }
100:
101: /**
102: * Writes a byte.
103: */
104: @Override
105: public void write(int v) throws IOException {
106: if (_bufferEnd <= _offset) {
107: flushBlock();
108: }
109:
110: _buffer[_offset++] = (byte) (v >> 8);
111: _buffer[_offset++] = (byte) (v);
112:
113: _length += 2;
114: }
115:
116: /**
117: * Writes a buffer.
118: */
119: public void write(char[] buffer, int offset, int length)
120: throws IOException {
121: byte[] byteBuffer = _buffer;
122: int byteOffset = _offset;
123:
124: while (length > 0) {
125: if (_bufferEnd <= byteOffset) {
126: _offset = byteOffset;
127: flushBlock();
128: byteOffset = _offset;
129: }
130:
131: int sublen = (_bufferEnd - byteOffset) >> 1;
132: if (length < sublen)
133: sublen = length;
134:
135: for (int i = 0; i < sublen; i++) {
136: char ch = buffer[offset + i];
137:
138: byteBuffer[byteOffset++] = (byte) (ch >> 8);
139: byteBuffer[byteOffset++] = (byte) (ch);
140: }
141:
142: offset += sublen;
143:
144: length -= sublen;
145: _length += 2 * sublen;
146: }
147:
148: _offset = byteOffset;
149: }
150:
151: /**
152: * Updates the buffer.
153: */
154: private void flushBlock() throws IOException {
155: int length = _offset;
156: _offset = 0;
157:
158: Inode.append(_inodeBuffer, _inodeOffset, _store, _xa, _buffer,
159: 0, length);
160: }
161:
162: /**
163: * Flushes the stream.
164: */
165: public void flush() {
166: }
167:
168: /**
169: * Completes the stream.
170: */
171: public void close() throws IOException {
172: try {
173: flushBlock();
174:
175: TempBuffer.free(_tempBuffer);
176: _tempBuffer = null;
177: } finally {
178: if (_inode != null)
179: _inode.closeOutputStream();
180: }
181: }
182:
183: /**
184: * Writes the long.
185: */
186: private static void writeLong(byte[] buffer, int offset, long v) {
187: buffer[offset + 0] = (byte) (v >> 56);
188: buffer[offset + 1] = (byte) (v >> 48);
189: buffer[offset + 2] = (byte) (v >> 40);
190: buffer[offset + 3] = (byte) (v >> 32);
191:
192: buffer[offset + 4] = (byte) (v >> 24);
193: buffer[offset + 5] = (byte) (v >> 16);
194: buffer[offset + 6] = (byte) (v >> 8);
195: buffer[offset + 7] = (byte) (v);
196: }
197:
198: /**
199: * Reads a long.
200: */
201: private static long readLong(byte[] buffer, int offset) {
202: return (((buffer[offset + 0] & 0xffL) << 56)
203: | ((buffer[offset + 1] & 0xffL) << 48)
204: | ((buffer[offset + 2] & 0xffL) << 40)
205: | ((buffer[offset + 3] & 0xffL) << 32) |
206:
207: ((buffer[offset + 4] & 0xffL) << 24)
208: | ((buffer[offset + 4] & 0xffL) << 16)
209: | ((buffer[offset + 4] & 0xffL) << 8) | ((buffer[offset + 4] & 0xffL)));
210: }
211:
212: /**
213: * Writes the short.
214: */
215: private static void writeShort(byte[] buffer, int offset, short v) {
216: buffer[offset + 0] = (byte) (v >> 8);
217: buffer[offset + 1] = (byte) (v);
218: }
219:
220: /**
221: * Reads a short.
222: */
223: private static int readShort(byte[] buffer, int offset) {
224: return (((buffer[offset + 0] & 0xff) << 8) | ((buffer[offset + 1] & 0xff)));
225: }
226: }
|