You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2006/07/15 16:06:38 UTC

svn commit: r422223 - in /db/ojb/trunk/src/java/org/apache/ojb/broker/lob: ./ BlobHandle.java BlobImpl.java ClobHandle.java ClobImpl.java InactiveLobException.java Lob.java LobException.java LobHandle.java LobHelper.java LobHelperImpl.java

Author: arminw
Date: Sat Jul 15 07:06:37 2006
New Revision: 422223

URL: http://svn.apache.org/viewvc?rev=422223&view=rev
Log:
merge trunk with 1.0.x, lob support

Added:
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobHandle.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobHandle.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/InactiveLobException.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/Lob.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobException.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHandle.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelper.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobHandle.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobHandle.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobHandle.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,125 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.Blob;
+import java.sql.SQLException;
+
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+
+/**
+ * This class is a wrapper for {@link java.sql.Blob} objects.
+ *
+ * @version $Id$
+ */
+public class BlobHandle extends LobHandle implements Blob
+{
+	/**
+	 * NB: update serialVersionUID when making class incompatible with serialized data!
+	 */
+	private static final long serialVersionUID = 1L;
+
+	BlobHandle(PersistenceBrokerInternal broker, Blob blob)
+    {
+        super(broker, blob);
+    }
+
+    private BlobHandle()
+    {
+        super();
+    }
+
+    public LobHandle decoupledCopy()
+    {
+        return new BlobHandle();
+    }
+
+    /**
+     * Returns the innermost {@link java.sql.Blob} instance.
+     *
+     * @return The innermost wrapped LOB instance.
+     */
+    public Blob getBlob()
+    {
+        Blob result = (Blob) getLocator(false);
+        if(result instanceof BlobHandle)
+        {
+            result = ((BlobHandle) result).getBlob();
+        }
+        return result;
+    }
+
+    private Blob getLocalBlob()
+    {
+        return (Blob) getLocator(true);
+    }
+
+    public long length() throws SQLException
+    {
+        return getLocalBlob().length();
+    }
+
+    public byte[] getBytes(long pos, int length) throws SQLException
+    {
+        return getLocalBlob().getBytes(pos, length);
+    }
+
+    public long position(byte pattern[], long start) throws SQLException
+    {
+        return getLocalBlob().position(pattern, start);
+    }
+
+    public InputStream getBinaryStream() throws SQLException
+    {
+        return getLocalBlob().getBinaryStream();
+    }
+
+    public long position(Blob pattern, long start) throws SQLException
+    {
+        return getLocalBlob().position(pattern, start);
+    }
+
+//#ifdef JDBC30
+
+    public OutputStream setBinaryStream(long pos) throws SQLException
+    {
+        markDirty();
+        return getLocalBlob().setBinaryStream(pos);
+    }
+
+    public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException
+    {
+        markDirty();
+        return getLocalBlob().setBytes(pos, bytes, offset, len);
+    }
+
+    public int setBytes(long pos, byte[] bytes) throws SQLException
+    {
+        markDirty();
+        return getLocalBlob().setBytes(pos, bytes);
+    }
+
+    public void truncate(long len) throws SQLException
+    {
+        markDirty();
+        getLocalBlob().truncate(len);
+    }
+
+//#endif
+
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobImpl.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobImpl.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/BlobImpl.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,185 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.sql.Blob;
+import java.sql.SQLException;
+
+import org.apache.commons.lang.ArrayUtils;
+
+/**
+ * This class is OJB's implementation of the {@link java.sql.Blob} interface.
+ *
+ * @version $Id$
+ */
+class BlobImpl implements Blob, Serializable, Lob
+{
+	/**
+	 * NB: update serialVersionUID when making class incompatible with serialized data!
+	 */
+	private static final long serialVersionUID = 1L;
+    private byte[] bytes = new byte[]{};
+    private transient InputStream in;
+
+    public BlobImpl()
+    {
+    }
+
+    public BlobImpl(byte[] value)
+    {
+        if(value != null) this.bytes = value;
+    }
+
+    public BlobImpl(InputStream in)
+    {
+        this.in = in;
+    }
+
+    private void checkMethod()
+    {
+        if(in != null)
+        {
+            throw new UnsupportedOperationException("Unsupported method when using this Blob implementation with InputStream");
+        }
+    }
+
+    public byte[] getBytes()
+    {
+        return bytes;
+    }
+
+    public byte[] getBytes(long pos, int length) throws SQLException
+    {
+        checkMethod();
+        pos--;
+        return ArrayUtils.subarray(bytes, (int) pos, (int) (pos + length));
+    }
+
+    public int setBytes(long pos, byte[] bytes) throws SQLException
+    {
+        return setBytes(pos, bytes, 1, bytes.length);
+    }
+
+    public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException
+    {
+        checkMethod();
+        offset--;
+        OJBStream out = prepareStream(pos);
+        out.write(bytes, offset, len);
+        try
+        {
+            out.close();
+        }
+        catch(IOException e)
+        {
+            throw new LobException("Unexpected failure while write bytes", e);
+        }
+        return len;
+    }
+
+    public InputStream getBinaryStream() throws SQLException
+    {
+        if(in != null) return in;
+        else return new ByteArrayInputStream(bytes);
+    }
+
+    public OutputStream setBinaryStream(long pos) throws SQLException
+    {
+        checkMethod();
+        return prepareStream(pos);
+    }
+
+    public OJBStream prepareStream(long pos) throws SQLException
+    {
+        if(pos < 1)
+        {
+            throw new IndexOutOfBoundsException("Invalid index: " + pos);
+        }
+
+        OJBStream out = new OJBStream(this);
+        if(this.bytes.length > 0) out.write(this.bytes, 0, (int) --pos);
+        return out;
+    }
+
+    public long length() throws SQLException
+    {
+        return in != null ? -1 : bytes.length;
+    }
+
+    public long position(byte pattern[], long start) throws SQLException
+    {
+        throw new UnsupportedOperationException("Not supported method");
+    }
+
+    public long position(Blob pattern, long start) throws SQLException
+    {
+        throw new UnsupportedOperationException("Not supported method");
+    }
+
+    public void truncate(long len) throws SQLException
+    {
+        checkMethod();
+        bytes = ArrayUtils.subarray(bytes, 0, (int) len);
+    }
+
+    public void streamClosed(OJBStream out)
+    {
+        int streamSize = out.size();
+        if(streamSize < this.bytes.length)
+        {
+            out.write(this.bytes, streamSize, this.bytes.length - streamSize);
+        }
+        this.bytes = out.toByteArray();
+    }
+
+//    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+//    {
+//        byte[] array = (byte[]) in.readObject();
+//        bytes.write(array);
+//    }
+//
+//    public void writeExternal(ObjectOutput out) throws IOException
+//    {
+//        out.writeObject(bytes.toByteArray());
+//    }
+
+    static class OJBStream extends ByteArrayOutputStream
+    {
+        BlobImpl home;
+
+        public OJBStream(BlobImpl home)
+        {
+            this.home = home;
+        }
+
+        byte[] getBytes()
+        {
+            return buf;
+        }
+
+        public void close() throws IOException
+        {
+            super.close();
+            home.streamClosed(this);
+        }
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobHandle.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobHandle.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobHandle.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,137 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.sql.Clob;
+import java.sql.SQLException;
+
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+
+/**
+ * This class is a wrapper for {@link java.sql.Clob} objects.
+ *
+ * @version $Id$
+ */
+public class ClobHandle extends LobHandle implements Clob
+{
+	/**
+	 * NB: update serialVersionUID when making class incompatible with serialized data!
+	 */
+	private static final long serialVersionUID = 1L;
+    ClobHandle(PersistenceBrokerInternal broker, Clob clob)
+    {
+        super(broker, clob);
+    }
+
+    private ClobHandle()
+    {
+        super();
+    }
+
+    public LobHandle decoupledCopy()
+    {
+        return new ClobHandle();
+    }
+
+    /**
+     * Returns the innermost {@link java.sql.Clob} instance.
+     *
+     * @return The innermost wrapped LOB instance.
+     */
+    public Clob getClob()
+    {
+        Clob result = (Clob) getLocator(false);
+        if(result instanceof ClobHandle)
+        {
+            result = ((ClobHandle) result).getClob();
+        }
+        return result;
+    }
+
+    private Clob getLocalClob()
+    {
+        return (Clob) getLocator(true);
+    }
+
+    public long length() throws SQLException
+    {
+        return getLocalClob().length();
+    }
+
+    public InputStream getAsciiStream() throws SQLException
+    {
+        return getLocalClob().getAsciiStream();
+    }
+
+    public Reader getCharacterStream() throws SQLException
+    {
+        return getLocalClob().getCharacterStream();
+    }
+
+    public String getSubString(long pos, int length) throws SQLException
+    {
+        return getLocalClob().getSubString(pos, length);
+    }
+
+    public long position(String searchstr, long start) throws SQLException
+    {
+        return getLocalClob().position(searchstr, start);
+    }
+
+    public long position(Clob searchstr, long start) throws SQLException
+    {
+        return getLocalClob().position(searchstr, start);
+    }
+
+//#ifdef JDBC30
+
+    public int setString(long pos, String str) throws SQLException
+    {
+        markDirty();
+        return getLocalClob().setString(pos, str);
+    }
+
+    public int setString(long pos, String str, int offset, int len) throws SQLException
+    {
+        markDirty();
+        return getLocalClob().setString(pos, str, offset, len);
+    }
+
+    public Writer setCharacterStream(long pos) throws SQLException
+    {
+        markDirty();
+        return getLocalClob().setCharacterStream(pos);
+    }
+
+    public OutputStream setAsciiStream(long pos) throws SQLException
+    {
+        markDirty();
+        return getLocalClob().setAsciiStream(pos);
+    }
+
+    public void truncate(long len) throws SQLException
+    {
+        markDirty();
+        getLocalClob().truncate(len);
+    }
+
+//#endif
+    
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobImpl.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobImpl.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/ClobImpl.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,189 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.sql.Clob;
+import java.sql.SQLException;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.ojb.broker.util.ReaderInputStream;
+
+/**
+ * This class is OJB's implementation of the {@link java.sql.Clob} interface.
+ *
+ * @version $Id$
+ */
+class ClobImpl implements Clob, Externalizable, Lob
+{
+	/**
+	 * NB: update serialVersionUID when making class incompatible with serialized data!
+	 */
+	private static final long serialVersionUID = 1L;
+    private transient StringWriter writer;
+    private transient Reader reader;
+
+    public ClobImpl()
+    {
+        this.writer = new StringWriter();
+    }
+
+    public ClobImpl(String str)
+    {
+        this();
+        if(str != null) writer.write(str);
+    }
+
+    public ClobImpl(Reader reader)
+    {
+        this.reader = reader;
+    }
+
+    private void checkMethod()
+    {
+        if(reader != null)
+        {
+            throw new UnsupportedOperationException("Unsupported method when using this Blob implementation with Reader");
+        }
+    }
+
+    protected StringWriter getWriter()
+    {
+        return writer;
+    }
+
+    public InputStream getAsciiStream() throws SQLException
+    {
+        if(reader != null)
+        {
+            return new ReaderInputStream(reader);
+        }
+        else return new ByteArrayInputStream(getWriter().toString().getBytes());
+    }
+
+    public OutputStream setAsciiStream(long pos) throws SQLException
+    {
+        checkMethod();
+        String str = getWriter().toString();
+        byte[] bytes = str.getBytes();
+        bytes = ArrayUtils.subarray(bytes, 0, (int) --pos);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        try
+        {
+            bos.write(bytes);
+        }
+        catch(IOException e)
+        {
+            throw new SQLException("Can't write existing bytes: " + ExceptionUtils.getFullStackTrace(e));
+        }
+        return bos;
+    }
+
+    public Reader getCharacterStream() throws SQLException
+    {
+        if(reader != null) return reader;
+        return new StringReader(getWriter().toString());
+    }
+
+    public Writer setCharacterStream(long pos) throws SQLException
+    {
+        checkMethod();
+        String result = getWriter().getBuffer().substring(0, (int) --pos);
+        writer = new StringWriter();
+        writer.write(result);
+        return getWriter();
+    }
+
+    public String getSubString(long pos, int length) throws SQLException
+    {
+        checkMethod();
+        pos--;
+        return getWriter().getBuffer().substring((int) pos, (int) (pos + length));
+    }
+
+    public int setString(long pos, String str) throws SQLException
+    {
+        checkMethod();
+        return setString(pos, str, 0, str.length());
+    }
+
+    public int setString(long pos, String str, int offset, int len) throws SQLException
+    {
+        checkMethod();
+        if(pos < 1)
+        {
+            throw new IndexOutOfBoundsException("Illegal start position: " + pos);
+        }
+        if(str == null)
+        {
+            throw new NullPointerException("Specified string is 'null'");
+        }
+        pos--;
+        StringBuffer charBuf = this.writer.getBuffer();
+        String replaceString = str.substring(offset, len);
+        charBuf.replace((int) pos, (int) (pos + replaceString.length()), replaceString);
+        return replaceString.length();
+    }
+
+    public long length() throws SQLException
+    {
+        return reader != null ? -1 : getWriter().getBuffer().length();
+    }
+
+    public long position(String searchstr, long start) throws SQLException
+    {
+        checkMethod();
+        return getWriter().getBuffer().toString().indexOf(searchstr, (int) --start);
+    }
+
+    public long position(Clob searchstr, long start) throws SQLException
+    {
+        checkMethod();
+        return getWriter().getBuffer().toString().indexOf(
+                searchstr.getSubString(0, (int) searchstr.length()), (int) --start);
+    }
+
+    public void truncate(long len) throws SQLException
+    {
+        checkMethod();
+        String str = getWriter().getBuffer().substring(0, (int) len);
+        writer = new StringWriter();
+        writer.write(str);
+    }
+
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+    {
+        String str = (String) in.readObject();
+        writer.write(str);
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException
+    {
+        out.writeObject(writer.toString());
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/InactiveLobException.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/InactiveLobException.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/InactiveLobException.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/InactiveLobException.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,43 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Thrown if access or usage of current LOB object isn't valid.
+ *
+ * @version $Id: $
+ */
+public class InactiveLobException extends LobException
+{
+    public InactiveLobException()
+    {
+    }
+
+    public InactiveLobException(String msg)
+    {
+        super(msg);
+    }
+
+    public InactiveLobException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public InactiveLobException(String msg, Throwable cause)
+    {
+        super(msg, cause);
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/Lob.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/Lob.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/Lob.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/Lob.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,26 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Marker interface for OJB's LOB object implementations.
+ *
+ * @version $Id: $
+ */
+public interface Lob
+{
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobException.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobException.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobException.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobException.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,46 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.ojb.broker.OJBRuntimeException;
+
+/**
+ * Thrown when an invalid LOB opertation occurs.
+ *
+ * @version $Id: $
+ */
+public class LobException extends OJBRuntimeException
+{
+    public LobException()
+    {
+    }
+
+    public LobException(String msg)
+    {
+        super(msg);
+    }
+
+    public LobException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public LobException(String msg, Throwable cause)
+    {
+        super(msg, cause);
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHandle.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHandle.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHandle.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,213 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.apache.ojb.broker.PBStateEvent;
+import org.apache.ojb.broker.PBStateListener;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+
+/**
+ * Base class for OJB LOB-object wrapper classes like Blob, Clob
+ * but also all other locator based advanced jdbc data types.
+ *
+ * @version $Id: $
+ */
+abstract public class LobHandle implements PBStateListener, Serializable
+{
+    private boolean active;
+    private boolean isTransient;
+    private transient Object locator;
+    private boolean dirty;
+
+    protected LobHandle()
+    {
+
+    }
+
+    LobHandle(PersistenceBrokerInternal broker, Object locator)
+    {
+        if(locator == null)
+        {
+            throw new NullPointerException("The locator object may not be 'null'");
+        }
+        this.locator = locator;
+        isTransient = false;
+        active = broker.isInTransaction();
+        if(locator instanceof Lob)
+        {
+            isTransient = true;
+            markDirty();
+        }
+        if(active)
+        {
+            broker.addListener(this, false);
+        }
+    }
+
+    /**
+     * Returns a <em>deactivated, decoupled</em> locator copy
+     * of this instance.
+     *
+     * @return A decoupled locator wrapper instance copy of this locator.
+     */
+    abstract public LobHandle decoupledCopy();
+
+    /**
+     * Returns <em>true</em> if the locator object was manipulated.
+     *
+     * @return If the locator object was modified <em>true</em> is returned, else <em>false</em>.
+     */
+    public boolean isDirty()
+    {
+        return dirty && this.locator != null;
+    }
+
+    /**
+     * Set the state of this locator.
+     *
+     * @param dirty The state flag of this locator.
+     */
+    public void setDirty(boolean dirty)
+    {
+        this.dirty = dirty;
+    }
+
+    /**
+     * Mark this locator as dirty.
+     */
+    protected void markDirty()
+    {
+        setDirty(true);
+    }
+
+    /**
+     * Return the locator object.
+     *
+     * @param check If <em>true</em> a validation check is done, else simply the locator is returned.
+     * @return The locator object.
+     */
+    protected Object getLocator(boolean check)
+    {
+        if(check) checkActive();
+        return locator;
+    }
+
+    /**
+     * Returns <em>true</em> if the wrapped locator object is
+     * a ojb specific {@link Lob} implementation (and not a database specific
+     * locator object of a column entry). Else <em>false</em> is returned.
+     */
+    public boolean isTransient()
+    {
+        return isTransient;
+    }
+
+//    protected void setTransient(boolean aTransient)
+//    {
+//        isTransient = aTransient;
+//    }
+
+    protected void txFail()
+    {
+        this.active = false;
+        if(!isTransient()) this.locator = null;
+    }
+
+    protected void txSuccess()
+    {
+        this.active = false;
+        this.isTransient = false;
+        this.dirty = false;
+        this.locator = null;
+    }
+
+    /**
+     * Called to decouple this LOB object from
+     * a associated {@link org.apache.ojb.broker.PersistenceBroker} instance.
+     */
+    protected void decouple()
+    {
+        this.active = false;
+        if(!isTransient())
+        {
+            this.dirty = false;
+            this.locator = null;
+        }
+    }
+
+    /**
+     * Returns <em>true</em> if this LOB object is associated
+     * with a {@link org.apache.ojb.broker.PersistenceBroker} instance.
+     */
+    protected boolean isCoupled()
+    {
+        return this.active;
+    }
+
+    public void checkActive()
+    {
+        if(!(isTransient() || isCoupled())) throw new InactiveLobException(
+                "Current LOB is not valid for access (no active PB-tx or PB-tx changed), "
+                        + "refresh the persistent object LOB content after PB-tx starts");
+    }
+
+    public boolean isActive()
+    {
+        return isTransient() || isCoupled();
+    }
+
+
+    //===================================================================
+    // Listener methods
+    //===================================================================
+    public void beforeClose(PBStateEvent event)
+    {
+        decouple();
+    }
+
+    public void beforeRollback(PBStateEvent event)
+    {
+        txFail();
+    }
+
+    public void afterCommit(PBStateEvent event)
+    {
+        txSuccess();
+    }
+
+    public void afterBegin(PBStateEvent event)
+    {
+        if(isTransient()) this.active = true;
+    }
+
+    public void afterOpen(PBStateEvent event)
+    {
+    }
+
+    public void beforeBegin(PBStateEvent event)
+    {
+    }
+
+    public void beforeCommit(PBStateEvent event)
+    {
+    }
+
+    public void afterRollback(PBStateEvent event)
+    {
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelper.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelper.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelper.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelper.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,202 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Blob;
+import java.sql.Clob;
+
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+
+/**
+ * Helper class support handling of LOB-locator-object
+ * fields ({@link java.sql.Blob} and {@link java.sql.Clob} fields)
+ * in persistence capable objects.
+ *
+ * @version $Id: $
+ */
+public interface LobHelper
+{
+    /**
+     * Returns a new {@link java.sql.Blob} instance.
+     *
+     * @param in The data source stream.
+     * @return The new {@link java.sql.Blob} instance.
+     */
+    public Blob newBlob(InputStream in);
+
+    /**
+     * Returns a new {@link java.sql.Blob} instance.
+     *
+     * @param value The byte array data.
+     * @return The new {@link java.sql.Blob} instance.
+     */
+    public Blob newBlob(byte[] value);
+
+    /**
+     * Returns a new <em>empty</em> {@link java.sql.Blob} instance.
+     *
+     * @return The new {@link java.sql.Blob} instance.
+     */
+    public Blob newBlob();
+
+    /**
+     * Returns a new {@link java.sql.Clob} instance.
+     *
+     * @param reader The data source reader.
+     * @return The new {@link java.sql.Clob} instance.
+     */
+    public Clob newClob(Reader reader);
+
+    /**
+     * Returns a new {@link java.sql.Clob} instance.
+     *
+     * @param value The data source as {@link String}.
+     * @return The new {@link java.sql.Clob} instance.
+     */
+    public Clob newClob(String value);
+
+    /**
+     * Returns a new <em>empty</em> {@link java.sql.Clob} instance.
+     *
+     * @return The new {@link java.sql.Clob} instance.
+     */
+    public Clob newClob();
+
+    /**
+     * Returns <em>true</em> if automatic refresh of LOB-locator
+     * fields is enabled.
+     *
+     * @see #setLobAutoRefresh(boolean)
+     */
+    public boolean isLobAutoRefresh();
+
+    /**
+     * @param autoRefresh If <em>true</em> automatic refresh for LOB-locator
+     * objects will be enabled.
+     */
+    public void setLobAutoRefresh(boolean autoRefresh);
+
+    /**
+     * INTERNAL USED METHOD!
+     * This method was internally called when automatic refresh of
+     * LOB-locator-object field is enabled - see {@link #setLobAutoRefresh(boolean)}.
+     */
+    public void internalAutoRefresh(Object target, ClassDescriptor cld);
+
+    /**
+     * See method {@link #refreshLob(Object, org.apache.ojb.broker.metadata.ClassDescriptor)}.
+     *
+     * @param target The target object with the LOB-fields to refresh.
+     */
+    public void refreshLob(Object target);
+
+    /**
+     * Refresh all LOB-locator instances of the specified persistence capable object
+     * if the following conditions are <em>true</em> for the target object:
+     * <ul>
+     * <li>active {@link org.apache.ojb.broker.PersistenceBroker}-tx is running</li>
+     * <li>contains LOB fields</li>
+     * <li>LOB fields wrapped by OJB's LOB wrapping classes (normally
+     * all LOB fields of persistence capable objects are automatically wrapped
+     * internal with OJB specific wrapper classes</li>
+     * <li>one or more fields are inactive/invalid (there is no active
+     * {@link org.apache.ojb.broker.PersistenceBroker} instance associated with detected LOB-fields)</li>
+     * </ul>
+     * In all other cases the method will return immediately.
+     * On each LOB-fields refresh, OJB query a new LOB-locator instance from the database.
+     *
+     * @param target The target object with the LOB-fields to refresh.
+     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of the target object.
+     */
+    public void refreshLob(Object target, ClassDescriptor cld);
+
+    /**
+     * Internal used method!
+     * <br/>
+     * Wrap the specified LOB value ({@link java.sql.Blob} and {@link java.sql.Clob}
+     * instances returned by the database) with OJB specific LOB-wrapper class.
+     *
+     * @param fld The field of the specified value.
+     * @param value The LOB content value of the field.
+     * @return The wrapped LOB content.
+     */
+    public Object wrapLobField(FieldDescriptor fld, Object value);
+
+//    /**
+//     * Internal used method!
+//     * <br/>
+//     * Refresh the specified LOB-locator instance field of the persistence capable object.
+//     * For each refresh OJB query a new Locator instance from the database.
+//     * The refresh of LOB-fields is only possible within an active
+//     * {@link org.apache.ojb.broker.PersistenceBroker}-tx, else the method will return immediately.
+//     *
+//     * @param lobField The LOB field to refresh.
+//     * @param target The target object with the field to refresh.
+//     * @param pkFields The promary key values of the target object.
+//     */
+//    public void refreshLob(FieldDescriptor lobField, Object target, FieldDescriptor[] pkFields);
+
+//    /**
+//     * Internal used method!
+//     * <br/>
+//     * Wraps the target object LOB instances ({@link java.sql.Blob} and {@link java.sql.Clob}
+//     * instances returned by the database) with OJB specific LOB-wrapper classes.
+//     *
+//     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of the target object.
+//     * @param target The target object.
+//     */
+//    public void wrapLobFields(ClassDescriptor cld, Object target);
+
+//    /**
+//     * Returns <em>true</em> if the specified persistence capable object
+//     * fulfill the conditions below:
+//     * <ul>
+//     * <li>contains LOB fields</li>
+//     * <li>LOB fields wrapped by OJB's LOB wrapping classes (normally
+//     * all LOB fields of persistence capable objects are automatically wrapped
+//     * with OJB specific wrapper classes by internal calls to
+//     * {@link #wrapLobFields(org.apache.ojb.broker.metadata.ClassDescriptor, Object)})</li>
+//     * <li>one or more fields are inactive/invalid</li>
+//     * </ul>
+//     * In all other cases <em>false</em> will be returned.
+//     *
+//     * @param source The persistence capable object.
+//     * @return <em>True</em> if source object has inactive/invalid LOB-fields.
+//     */
+//    public boolean needsRefresh(Object source);
+//
+//    /**
+//     * Returns <em>true</em> if the specified persistence capable object
+//     * fulfill the conditions below:
+//     * <ul>
+//     * <li>contains LOB fields</li>
+//     * <li>LOB fields wrapped by OJB's LOB wrapping classes (normally
+//     * all LOB fields of persistence capable objects are automatically wrapped
+//     * with OJB specific wrapper classes by internal calls to
+//     * {@link #wrapLobFields(org.apache.ojb.broker.metadata.ClassDescriptor, Object)})</li>
+//     * <li>one or more fields are inactive/invalid</li>
+//     * </ul>
+//     * In all other cases <em>false</em> will be returned.
+//     *
+//     * @param source The persistence capable object.
+//     * @param cld The associated {@link org.apache.ojb.broker.metadata.ClassDescriptor}.
+//     * @return <em>True</em> if source object has inactive/invalid LOB-fields.
+//     */
+//    public boolean needsRefresh(Object source, ClassDescriptor cld);
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java?rev=422223&view=auto
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java Sat Jul 15 07:06:37 2006
@@ -0,0 +1,258 @@
+package org.apache.ojb.broker.lob;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.util.Iterator;
+
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.FieldTypes;
+import org.apache.ojb.broker.query.Criteria;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.broker.query.QueryFactory;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
+/**
+ * Helper class for LOB object creation.
+ *
+ * @version $Id: $
+ */
+public class LobHelperImpl implements LobHelper
+{
+    private Logger log = LoggerFactory.getLogger(LobHelperImpl.class);
+
+    private PersistenceBrokerInternal broker;
+    private boolean lobAutoRefresh;
+
+    public LobHelperImpl(PersistenceBrokerInternal broker)
+    {
+        this.broker = broker;
+    }
+
+    public Blob newBlob(InputStream in)
+    {
+        BlobImpl result = new BlobImpl(in);
+        return new BlobHandle(broker, result);
+    }
+
+    public Blob newBlob(byte[] value)
+    {
+        BlobImpl result = new BlobImpl(value);
+        return new BlobHandle(broker, result);
+    }
+
+    public Blob newBlob()
+    {
+        return newBlob((byte[]) null);
+    }
+
+    public Clob newClob(Reader reader)
+    {
+        ClobImpl result = new ClobImpl(reader);
+        return new ClobHandle(broker, result);
+    }
+
+    public Clob newClob(String value)
+    {
+        ClobImpl result = new ClobImpl(value);
+        return new ClobHandle(broker, result);
+    }
+
+    public Clob newClob()
+    {
+        return newClob((String) null);
+    }
+
+    public boolean isLobAutoRefresh()
+    {
+        return this.lobAutoRefresh;
+    }
+
+    public void setLobAutoRefresh(boolean autoRefresh)
+    {
+        this.lobAutoRefresh = autoRefresh;
+    }
+
+    public void internalAutoRefresh(Object target, ClassDescriptor cld)
+    {
+        if(lobAutoRefresh)
+        {
+            refreshLob(target, cld);
+        }
+    }
+
+    public void refreshLob(Object target)
+    {
+        ClassDescriptor cld = broker.getClassDescriptor(target.getClass());
+        refreshLob(target, cld);
+    }
+
+    public void refreshLob(Object target, ClassDescriptor cld)
+    {
+        if(cld.hasLobField())
+        {
+            if(broker.isInTransaction())
+            {
+                FieldDescriptor[] pkFields = cld.getPkFields();
+                FieldDescriptor[] fields = cld.getFieldDescriptor(true);
+                for(int i = 0; i < fields.length; i++)
+                {
+                    FieldDescriptor field = fields[i];
+                    if(needsRefresh(field, target))
+                    {
+                        performRefreshLob(field, target, pkFields);
+                    }
+                }
+            }
+            else
+            {
+                if(log.isDebugEnabled())
+                {
+                    log.debug("No active transaction, can't refresh LOB-content for object " + target);
+                }
+            }
+        }
+    }
+
+    /**
+     * Refresh the specified LOB type field by querying a new LOB-locator object via ReportQuery
+     * and replace the LOB-object in source object.
+     */
+    protected void performRefreshLob(FieldDescriptor lobField, Object source, FieldDescriptor[] pkFields)
+    {
+        if(source == null)
+        {
+            throw new NullPointerException("Persistence capable object instance is 'null'");
+        }
+        if(lobField.isLobFieldType())
+        {
+            Object result = null;
+            FieldDescriptor fld;
+            Criteria crit = new Criteria();
+            for(int i = 0; i < pkFields.length; i++)
+            {
+                fld = pkFields[i];
+                crit.addEqualTo(fld.getAttributeName(), fld.getPersistentField().get(source));
+            }
+            Query query = QueryFactory.newReportQuery(
+                    source.getClass(), new String[]{lobField.getAttributeName()}, crit, false);
+            Iterator iter = broker.getReportQueryIteratorByQuery(query);
+            while(iter.hasNext())
+            {
+                Object[] arr = (Object[]) iter.next();
+                if(arr.length > 0)
+                {
+                    result = arr[0];
+                    break;
+                }
+            }
+            if(result != null)
+            {
+                if(log.isDebugEnabled())
+                {
+                    log.debug("Refresh LOB field for " + lobField.getClassDescriptor().getClassNameOfObject()
+                            + "." + lobField.getAttributeName());
+                }
+                if(isBlobField(lobField))
+                {
+                    result = new BlobHandle(broker, (Blob) result);
+                }
+                else
+                {
+                    result = new ClobHandle(broker, (Clob) result);
+                }
+            }
+            lobField.getPersistentField().set(source, result);
+        }
+        else
+        {
+            throw new LobException("Specified field isn't of type LOB (Blob or Clob): " + lobField);
+        }
+    }
+
+    /**
+     * Returns <em>true</em> if the specified field is of type LOB (Blob or Clob type)
+     * and wrapped by OJB's LOB wrapper and the LOB wrapper isn't active.
+     */
+    protected boolean needsRefresh(FieldDescriptor field, Object source)
+    {
+        boolean result = field.isLobFieldType();
+        if(result)
+        {
+            Object lob = field.getPersistentField().get(source);
+            if(lob instanceof LobHandle && ((LobHandle) lob).isCoupled())
+            {
+                // used LOB value doesn't need refresh, it's already bound to a PB instance
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    protected boolean isBlobField(FieldDescriptor fld)
+    {
+        return FieldTypes.BlobFieldType.class.isAssignableFrom(fld.getJdbcType().getFieldType().getClass());
+    }
+
+//    public void wrapLobFields(ClassDescriptor cld, Object target)
+//    {
+//        if(cld.hasLobField())
+//        {
+//            FieldDescriptor[] fields = cld.getFieldDescriptor(true);
+//            for(int i = 0; i < fields.length; i++)
+//            {
+//                FieldDescriptor field = fields[i];
+//                if(field.isLobFieldType())
+//                {
+//                    Object lob = field.getPersistentField().get(target);
+//                    if(lob != null && !(lob instanceof LobHandle))
+//                    {
+//                        if(isBlobField(field))
+//                        {
+//                            field.getPersistentField().set(target, new BlobHandle(broker, (Blob) lob));
+//                        }
+//                        else
+//                        {
+//                            field.getPersistentField().set(target, new ClobHandle(broker, (Clob) lob));
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//    }
+
+    public Object wrapLobField(FieldDescriptor fld, Object value)
+    {
+        if(value != null && !(value instanceof LobHandle))
+        {
+            if(isBlobField(fld))
+            {
+                return new BlobHandle(broker, (Blob) value);
+            }
+            else
+            {
+                return new ClobHandle(broker, (Clob) value);
+            }
+        }
+        return value;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org