/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.ejb.plugins.cmp.jdbc; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.io.OutputStream; import java.sql.SQLException; import java.sql.Blob; /** * The representation (mapping) in the Java<sup><font size=-2>TM</font></sup> * programming language of an SQL <code>BLOB</code> value to an array of bytes. * A ByteArrayBlob contains an internal buffer that contains bytes that may be * read from the stream. The <code>Blob</code> interface provides methods for * getting the length of an SQL <code>BLOB</code> (Binary Large Object) value, * for materializing a <code>BLOB</code> value on the client, and for * determining the position of a pattern of bytes within a <code>BLOB</code> * value. The ByteArrayBlob has static factory methods for construting an * <code>BLOB</code> using either an existing serializable object, or an array * of bytes. This is a nice way to store serialized objects in a relational * field of type SQL <code>BLOB</code>. * * @author <a href="mailto:amccullo@sourceforge.new">Andrew McCulloch</a> * @author <a href="mailto:abrock@jboss.org">Adrian Brock</a> * @version $Revision: 81030 $ */ public final class ByteArrayBlob implements Blob { /** * The internal buffer for the bytes of the Blob. */ private final byte[] mBytes; public ByteArrayBlob(byte[] bytes) { if (bytes == null) { bytes = new byte[0]; } mBytes = bytes; } public InputStream getBinaryStream() throws SQLException { return new ByteArrayInputStream(mBytes); } public byte[] getBytes(long pos, int length) throws SQLException { // Defensive code, parameter checks. if (length < 0 || length > mBytes.length || pos > mBytes.length) { return new byte[0]; } if (pos <= 0) { pos = 1; // One since the copy starts at pos. } byte[] buffer = new byte[length]; System.arraycopy(mBytes, (int)pos - 1, buffer, 0, length); return buffer; } public long length() throws SQLException { return mBytes.length; } public long position(Blob pattern , long start) throws SQLException { return position(pattern.getBytes(0, (int)pattern.length()), start); } public long position(byte pattern[], long start) throws SQLException { // Small optimization, no need to look beyond this. int max = mBytes.length - pattern.length; if (start < 0) { start = 0; // Cannot start negative, so put it at the beginning. } else if (start >= mBytes.length) { return -1; // Out of bounds, start was past the end of the buffer. } if (pattern.length == 0) { return -1; // Indicate that the pattern was not found. } byte first = pattern[0]; int i = (int)start; while (true) { // Look for the first character. while (i <= max && mBytes[i] != first) { i++; } if (i > max) { return -1; // Went to far, reject the pattern. } // Found the first character, now look for remainder of v2. int j = i + 1; int end = j + pattern.length - 1; int k = 1; boolean cont = true; // While the bytes remain equal and the end of v1 is not reached // continue the either rejecting this match, or accepting it. while (cont && j < end) { if (mBytes[j++] != pattern[k++]) { i++; cont = false; } } // If cont == false then the pattern was found. if (cont) { return i; } } } public void free() throws SQLException { } public InputStream getBinaryStream(long pos, long length) throws SQLException { throw new UnsupportedOperationException("Unimplemented JDK6 method"); } public OutputStream setBinaryStream(long pos) throws SQLException { throw new UnsupportedOperationException("ByteArrayBlob is immutable"); } public int setBytes(long pos, byte[] bytes) throws SQLException { throw new UnsupportedOperationException("ByteArrayBlob is immutable"); } public int setBytes(long pos, byte[] bytes, int offset, int length) throws SQLException { throw new UnsupportedOperationException("ByteArrayBlob is immutable"); } public void truncate(long length) throws SQLException { throw new UnsupportedOperationException("ByteArrayBlob is immutable"); } }