001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency.type;
010:
011: import com.completex.objective.components.persistency.OdalRuntimePersistencyException;
012:
013: import java.io.ByteArrayInputStream;
014: import java.io.ByteArrayOutputStream;
015: import java.io.Externalizable;
016: import java.io.IOException;
017: import java.io.InputStream;
018: import java.io.ObjectInput;
019: import java.io.ObjectOutput;
020: import java.io.OutputStream;
021: import java.sql.Blob;
022: import java.sql.SQLException;
023:
024: /**
025: * @author Gennady Krizhevsky
026: */
027: public class BlobImpl implements Blob, Externalizable {
028:
029: public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
030: public static final BlobImpl NULL_BLOB = new BlobImpl();
031:
032: static {
033: NULL_BLOB.bytes = EMPTY_BYTE_ARRAY;
034: }
035:
036: private int chunkSize = TypeHandler.DEFAULT_CHUNK_SIZE;
037: private InputStream inputStream;
038: private long length;
039: protected byte[] bytes;
040: private static final String MESSAGE = "This operation is unsupported in the implementation that is used to set data only";
041:
042: public BlobImpl() {
043: }
044:
045: public BlobImpl(InputStream inputStream, long length) {
046: this .inputStream = inputStream;
047: this .length = length;
048: }
049:
050: public BlobImpl(byte[] bytes) {
051: this .bytes = bytes;
052: this .inputStream = new ByteArrayInputStream(bytes);
053: this .length = bytes.length;
054: }
055:
056: public long length() throws SQLException {
057: return length > 0 ? length : (bytes != null ? bytes.length : 0);
058: }
059:
060: public void writeExternal(ObjectOutput out) throws IOException {
061: try {
062: out.write(getBytes());
063: } catch (SQLException e) {
064: throw new IOException(e.toString());
065: }
066: }
067:
068: public void readExternal(ObjectInput in) throws IOException,
069: ClassNotFoundException {
070: ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
071: writeBlob(chunkSize, in, outputStream);
072: bytes = outputStream.toByteArray();
073: }
074:
075: public byte[] getBytes() throws SQLException {
076: InputStream inputStream = this .inputStream;
077: getBytes(inputStream);
078: return bytes;
079: }
080:
081: protected void getBytes(InputStream inputStream) {
082: if (this .bytes == null && inputStream != null) {
083: ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
084: writeBlob(chunkSize, inputStream, outputStream);
085: this .bytes = outputStream.toByteArray();
086: }
087: }
088:
089: public static void writeBlob(InputStream inputStream,
090: OutputStream outputStream) {
091: writeBlob(TypeHandler.DEFAULT_CHUNK_SIZE, inputStream,
092: outputStream);
093: }
094:
095: public static void writeBlob(int chunkSize,
096: ObjectInput inputStream, OutputStream outputStream) {
097: if (outputStream == null) {
098: throw new NullPointerException("outputStream is not set");
099: }
100: byte[] chunk = new byte[chunkSize];
101: int len;
102: try {
103: while ((len = inputStream.read(chunk, 0, chunkSize)) > -1) {
104: outputStream.write(chunk, 0, len);
105: }
106: } catch (IOException e) {
107: new SQLException(e.getMessage());
108: }
109: }
110:
111: public static void writeBlob(int chunkSize,
112: InputStream inputStream, OutputStream outputStream) {
113: if (outputStream == null) {
114: throw new NullPointerException("outputStream is not set");
115: }
116: byte[] chunk = new byte[chunkSize];
117: int len;
118: try {
119: while ((len = inputStream.read(chunk, 0, chunkSize)) > -1) {
120: outputStream.write(chunk, 0, len);
121: }
122: } catch (IOException e) {
123: new SQLException(e.getMessage());
124: }
125: }
126:
127: public int getChunkSize() {
128: return chunkSize;
129: }
130:
131: public void setChunkSize(int chunkSize) {
132: this .chunkSize = chunkSize;
133: }
134:
135: public byte[] getBytes(long pos, int length) throws SQLException {
136: if (bytes == null) {
137: return EMPTY_BYTE_ARRAY;
138: }
139: int len = bytes.length;
140: if (length > len) {
141: length = len;
142: }
143:
144: if (pos < 1 || length - pos < 0) {
145: throw new OdalRuntimePersistencyException(
146: "Invalid arguments: position cannot be less that 1");
147: }
148:
149: pos--; // correct pos to array index
150:
151: byte[] b = new byte[length];
152:
153: for (int i = 0; i < length; i++) {
154: b[i] = bytes[(int) pos];
155: pos++;
156: }
157: return b;
158: }
159:
160: public InputStream getBinaryStream() {
161: if (bytes != null) {
162: return new ByteArrayInputStream(bytes);
163: } else {
164: return inputStream;
165: }
166: }
167:
168: public long position(byte pattern[], long start)
169: throws SQLException {
170: throw new UnsupportedOperationException(MESSAGE);
171: }
172:
173: public long position(Blob pattern, long start) throws SQLException {
174: throw new UnsupportedOperationException(MESSAGE);
175: }
176:
177: public int setBytes(long pos, byte[] bytes) throws SQLException {
178: throw new UnsupportedOperationException(MESSAGE);
179: }
180:
181: public int setBytes(long pos, byte[] bytes, int offset, int len)
182: throws SQLException {
183: throw new UnsupportedOperationException(MESSAGE);
184: }
185:
186: public OutputStream setBinaryStream(long pos) throws SQLException {
187: throw new UnsupportedOperationException(MESSAGE);
188: }
189:
190: public void truncate(long len) throws SQLException {
191: throw new UnsupportedOperationException(MESSAGE);
192: }
193:
194: public InputStream getInputStream() {
195: return inputStream;
196: }
197:
198: public void setInputStream(InputStream inputStream) {
199: this .inputStream = inputStream;
200: }
201:
202: public String toReadableString() {
203: return String.valueOf(bytes);
204: }
205:
206: public void free() throws SQLException {
207: }
208:
209: public InputStream getBinaryStream(long pos, long length)
210: throws SQLException {
211: return null;
212: }
213: }
|