001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.sql.rowset.serial;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.io.Serializable;
024: import java.sql.Blob;
025: import java.sql.SQLException;
026:
027: import org.apache.harmony.sql.internal.nls.Messages;
028:
029: public class SerialBlob implements Blob, Serializable, Cloneable {
030:
031: private static final long serialVersionUID = -8144641928112860441L;
032:
033: // required by serialized form
034: private byte[] buf;
035:
036: // required by serialized form
037: @SuppressWarnings("unused")
038: private Blob blob;
039:
040: // required by serialized form
041: private long len;
042:
043: // required by serialized form
044: @SuppressWarnings("unused")
045: private long origLen;
046:
047: /**
048: * Constructs an instance by the given <code>blob</code>
049: *
050: * @param blob
051: * the given blob
052: * @throws SerialException
053: * if an error is encountered during serialization
054: * @throws SQLException
055: * if <code>blob</code> is null
056: */
057: public SerialBlob(Blob blob) throws SerialException, SQLException {
058: if (blob == null) {
059: throw new SQLException(Messages.getString("sql.13")); //$NON-NLS-1$
060: }
061: this .blob = blob;
062: buf = blob.getBytes(1, (int) blob.length());
063: len = buf.length;
064: origLen = len;
065: }
066:
067: /**
068: * Constructs an instance by the given <code>buf</code>
069: *
070: * @param buf
071: * the given buffer
072: * @throws SerialException
073: * if an error is encountered during serialization
074: * @throws SQLException
075: * if a SQL error is encountered
076: */
077: public SerialBlob(byte[] buf) throws SerialException, SQLException {
078: this .buf = new byte[buf.length];
079: len = buf.length;
080: origLen = len;
081: System.arraycopy(buf, 0, this .buf, 0, (int) len);
082: }
083:
084: /**
085: * Returns an input stream of this SerialObject.
086: *
087: * @throws SerialException
088: * if an error is encountered
089: */
090: public InputStream getBinaryStream() throws SerialException {
091: return new ByteArrayInputStream(buf);
092: }
093:
094: /**
095: * Returns a copied array of this SerialObject, starting at the
096: * <code> pos </code> with the given <code> length</code> number. If
097: * <code> pos </code> + <code> length </code> - 1 is larger than the length
098: * of this SerialObject array, the <code> length </code> will be shortened
099: * to the length of array - <code>pos</code> + 1.
100: *
101: * @param pos
102: * the starting position of the array to be copied.
103: * @param length
104: * the total length of bytes to be copied
105: * @throws SerialException
106: * if an error is encountered
107: */
108: public byte[] getBytes(long pos, int length) throws SerialException {
109: if (pos < 1 || pos > len || length < 0) {
110: throw new SerialException(Messages.getString("sql.14")); //$NON-NLS-1$
111: }
112: if (length > len - pos + 1) {
113: length = (int) (len - pos + 1);
114: }
115: byte[] copiedArray = new byte[length];
116: System.arraycopy(buf, (int) pos - 1, copiedArray, 0, length);
117: return copiedArray;
118: }
119:
120: /**
121: * Gets the number of bytes in this SerialBlob object.
122: *
123: * @return an long value with the length of the SerialBlob in bytes
124: * @throws SerialException
125: * if an error is encoutnered
126: */
127: public long length() throws SerialException {
128: return len;
129: }
130:
131: /**
132: * Search for the position in this Blob at which a specified pattern begins,
133: * starting at a specified position within the Blob.
134: *
135: * @param pattern
136: * a Blob containing the pattern of data to search for in this
137: * Blob
138: * @param start
139: * the position within this Blob to start the search, where the
140: * first position in the Blob is 1
141: * @return a long value with the position at which the pattern begins. -1 if
142: * the pattern is not found in this Blob.
143: * @throws SQLException
144: * if an error occurs accessing the Blob
145: * @throws SerialException
146: * if an error is encountered
147: */
148: public long position(Blob pattern, long start)
149: throws SerialException, SQLException {
150: byte[] patternBytes = pattern.getBytes(1, (int) pattern
151: .length());
152: return position(patternBytes, start);
153: }
154:
155: /**
156: * Search for the position in this Blob at which the specified pattern
157: * begins, starting at a specified position within the Blob.
158: *
159: * @param pattern
160: * a byte array containing the pattern of data to search for in
161: * this Blob
162: * @param start
163: * the position within this Blob to start the search, where the
164: * first position in the Blob is 1
165: * @return a long value with the position at which the pattern begins. -1 if
166: * the pattern is not found in this Blob.
167: * @throws SerialException
168: * if an error is encountered
169: * @throws SQLException
170: * if an error occurs accessing the Blob
171: */
172: public long position(byte[] pattern, long start)
173: throws SerialException, SQLException {
174: if (start < 1 || len - (start - 1) < pattern.length) {
175: return -1;
176: }
177:
178: for (int i = (int) (start - 1); i <= (len - pattern.length); ++i) {
179: if (match(buf, i, pattern)) {
180: return i + 1;
181: }
182: }
183: return -1;
184: }
185:
186: /*
187: * Returns true if the bytes array contains exactly the same elements from
188: * start position to start + subBytes.length as subBytes. Otherwise returns
189: * false.
190: */
191: private boolean match(byte[] bytes, int start, byte[] subBytes) {
192: for (int i = 0; i < subBytes.length;) {
193: if (bytes[start++] != subBytes[i++]) {
194: return false;
195: }
196: }
197: return true;
198: }
199:
200: public OutputStream setBinaryStream(long pos)
201: throws SerialException, SQLException {
202: if (blob == null) {
203: throw new SerialException(Messages.getString("sql.18")); //$NON-NLS-1$
204: }
205: OutputStream os = blob.setBinaryStream(pos);
206: if (os == null) {
207: throw new SerialException(Messages.getString("sql.18")); //$NON-NLS-1$
208: }
209: return os;
210: }
211:
212: public int setBytes(long pos, byte[] theBytes)
213: throws SerialException, SQLException {
214: return setBytes(pos, theBytes, 0, theBytes.length);
215: }
216:
217: public int setBytes(long pos, byte[] theBytes, int offset,
218: int length) throws SQLException {
219: if (pos < 1 || length < 0 || pos > (len - length + 1)) {
220: throw new SerialException(Messages.getString("sql.15")); // $NON-NLS-1$
221: }
222: if (offset < 0 || length < 0
223: || offset > (theBytes.length - length)) {
224: throw new SerialException(Messages.getString("sql.16")); // $NON-NLS-1$
225: }
226: System.arraycopy(theBytes, offset, buf, (int) pos - 1, length);
227: return length;
228: }
229:
230: public void truncate(long length) throws SerialException {
231: if (length > this .len) {
232: throw new SerialException(Messages.getString("sql.17")); //$NON-NLS-1$
233: }
234: buf = getBytes(1, (int) length);
235: len = length;
236: }
237:
238: }
|