jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r413685 - in /jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core: fs/db/ state/db/
Date Mon, 12 Jun 2006 15:45:51 GMT
Author: stefan
Date: Mon Jun 12 08:45:50 2006
New Revision: 413685

URL: http://svn.apache.org/viewvc?rev=413685&view=rev
Log:
adding oracle FileSystem and PersistenceManager 

Added:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
  (with props)
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl
  (with props)
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
  (with props)
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java?rev=413685&r1=413684&r2=413685&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java
Mon Jun 12 08:45:50 2006
@@ -85,7 +85,7 @@
  *       <param name="schemaObjectPrefix" value="rep_"/>
  *   </FileSystem>
  * </pre>
- * See also {@link DerbyFileSystem}, {@link DB2FileSystem}.
+ * See also {@link DerbyFileSystem}, {@link DB2FileSystem}, {@link OracleFileSystem}.
  */
 public class DbFileSystem extends DatabaseFileSystem {
 

Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java?rev=413685&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
(added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
Mon Jun 12 08:45:50 2006
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.jackrabbit.core.fs.db;
+
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.log4j.Logger;
+
+/**
+ * <code>OracleFileSystem</code> is a JDBC-based <code>FileSystem</code>
+ * implementation for Jackrabbit that persists file system entries in an
+ * Oracle database.
+ * <p/>
+ * It is configured through the following properties:
+ * <ul>
+ * <li><code>driver</code>: the FQN name of the JDBC driver class
+ * (default: <code>"oracle.jdbc.OracleDriver"</code>)</li>
+ * <li><code>schema</code>: type of schema to be used
+ * (default: <code>"oracle"</code>)</li>
+ * <li><code>url</code>: the database url (e.g.
+ * <code>"jdbc:oracle:thin:@[host]:[port]:[sid]"</code>)</li>
+ * <li><code>user</code>: the database user</li>
+ * <li><code>password</code>: the user's password</li>
+ * <li><code>schemaObjectPrefix</code>: prefix to be prepended to schema
objects</li>
+ * </ul>
+ * See also {@link DbFileSystem}.
+ * <p/>
+ * The following is a fragment from a sample configuration:
+ * <pre>
+ *   &lt;FileSystem class="org.apache.jackrabbit.core.fs.db.OracleFileSystem"&gt;
+ *       &lt;param name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/&gt;
+ *       &lt;param name="user" value="scott"/&gt;
+ *       &lt;param name="password" value="tiger"/&gt;
+ *       &lt;param name="schemaObjectPrefix" value="rep_"/&gt;
+ *  &lt;/FileSystem&gt;
+ * </pre>
+ */
+public class OracleFileSystem extends DbFileSystem {
+
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(OracleFileSystem.class);
+
+    /**
+     * Creates a new <code>OracleFileSystem</code> instance.
+     */
+    public OracleFileSystem() {
+        // preset some attributes to reasonable defaults
+        schema = "oracle";
+        driver = "oracle.jdbc.OracleDriver";
+        schemaObjectPrefix = "";
+        user = "";
+        password = "";
+        initialized = false;
+    }
+
+    //-----------------------------------------------< DbFileSystem overrides >
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Since Oracle treats emtpy strings and BLOBs as null values the SQL
+     * statements had to adapated accordingly. The following changes were
+     * necessary:
+     * <ul>
+     * <li>The distinction between file and folder entries is based on
+     * FSENTRY_LENGTH being null/not null rather than FSENTRY_DATA being
+     * null/not null because FSENTRY_DATA of a 0-length (i.e. empty) file is
+     * null in Oracle.</li>
+     * <li>Folder entries: Since the root folder has an empty name (which would
+     * be null in Oracle), an empty name is automatically converted and treated
+     * as " ".</li>
+     * </ul>
+     */
+    public void init() throws FileSystemException {
+        if (initialized) {
+            throw new IllegalStateException("already initialized");
+        }
+
+        try {
+            // setup jdbc connection
+            initConnection();
+
+            // check if schema objects exist and create them if necessary
+            checkSchema();
+
+            // prepare statements
+            insertFileStmt = con.prepareStatement("insert into "
+                    + schemaObjectPrefix + "FSENTRY "
+                    + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+                    + "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+                    + "values (?, ?, ?, ?, ?)");
+
+            insertFolderStmt = con.prepareStatement("insert into "
+                    + schemaObjectPrefix + "FSENTRY "
+                    + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+                    + "values (?, nvl(?, ' '), ?, null)");
+
+            updateDataStmt = con.prepareStatement("update "
+                    + schemaObjectPrefix + "FSENTRY "
+                    + "set FSENTRY_DATA = ?, FSENTRY_LASTMOD = ?, FSENTRY_LENGTH = ? "
+                    + "where FSENTRY_PATH = ? and FSENTRY_NAME = ? "
+                    + "and FSENTRY_LENGTH is not null");
+
+            updateLastModifiedStmt = con.prepareStatement("update "
+                    + schemaObjectPrefix + "FSENTRY set FSENTRY_LASTMOD = ? "
+                    + "where FSENTRY_PATH = ? and FSENTRY_NAME = ? "
+                    + "and FSENTRY_LENGTH is not null");
+
+            selectExistStmt = con.prepareStatement("select 1 from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = nvl(?, ' ')");
+
+            selectFileExistStmt = con.prepareStatement("select 1 from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = ? and FSENTRY_LENGTH is not null");
+
+            selectFolderExistStmt = con.prepareStatement("select 1 from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = nvl(?, ' ') and FSENTRY_LENGTH is null");
+
+            selectFileNamesStmt = con.prepareStatement("select FSENTRY_NAME from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_LENGTH is not null");
+
+            selectFolderNamesStmt = con.prepareStatement("select FSENTRY_NAME from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME != ' ' "
+                    + "and FSENTRY_LENGTH is null");
+
+            selectFileAndFolderNamesStmt = con.prepareStatement("select FSENTRY_NAME from
"
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME != ' '");
+
+            selectChildCountStmt = con.prepareStatement("select count(FSENTRY_NAME) from
"
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ?  "
+                    + "and FSENTRY_NAME != ' '");
+
+            selectDataStmt = con.prepareStatement("select nvl(FSENTRY_DATA, empty_blob())
from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = ? and FSENTRY_LENGTH is not null");
+
+            selectLastModifiedStmt = con.prepareStatement("select FSENTRY_LASTMOD from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = nvl(?, ' ')");
+
+            selectLengthStmt = con.prepareStatement("select nvl(FSENTRY_LENGTH, 0) from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = ? and FSENTRY_LENGTH is not null");
+
+            deleteFileStmt = con.prepareStatement("delete from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = ? and FSENTRY_LENGTH is not null");
+
+            deleteFolderStmt = con.prepareStatement("delete from "
+                    + schemaObjectPrefix + "FSENTRY where "
+                    + "(FSENTRY_PATH = ? and FSENTRY_NAME = nvl(?, ' ') and FSENTRY_LENGTH
is null) "
+                    + "or (FSENTRY_PATH = ?) "
+                    + "or (FSENTRY_PATH like ?) ");
+
+            copyFileStmt = con.prepareStatement("insert into "
+                    + schemaObjectPrefix + "FSENTRY "
+                    + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+                    + "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+                    + "select ?, ?, FSENTRY_DATA, "
+                    + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_NAME = ? and FSENTRY_LENGTH is not null");
+
+            copyFilesStmt = con.prepareStatement("insert into "
+                    + schemaObjectPrefix + "FSENTRY "
+                    + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+                    + "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+                    + "select ?, FSENTRY_NAME, FSENTRY_DATA, "
+                    + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
+                    + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+                    + "and FSENTRY_LENGTH is not null");
+
+            // finally verify that there's a file system root entry
+            verifyRootExists();
+
+            initialized = true;
+        } catch (Exception e) {
+            String msg = "failed to initialize file system";
+            log.error(msg, e);
+            throw new FileSystemException(msg, e);
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl?rev=413685&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl
(added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl
Mon Jun 12 08:45:50 2006
@@ -0,0 +1,2 @@
+create table ${schemaObjectPrefix}FSENTRY (FSENTRY_PATH varchar2(2048) not null, FSENTRY_NAME
varchar2(255) not null, FSENTRY_DATA blob null, FSENTRY_LASTMOD number(38,0) not null, FSENTRY_LENGTH
number(38,0) null)
+create unique index ${schemaObjectPrefix}FSENTRY_IDX on ${schemaObjectPrefix}FSENTRY (FSENTRY_PATH,
FSENTRY_NAME)

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/fs/db/oracle.ddl
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java?rev=413685&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
(added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
Mon Jun 12 08:45:50 2006
@@ -0,0 +1,348 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.jackrabbit.core.state.db;
+
+import org.apache.jackrabbit.core.state.PMContext;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.util.Serializer;
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+/**
+ * <code>OraclePersistenceManager</code> is a JDBC-based
+ * <code>PersistenceManager</code> for Jackrabbit that persists
+ * <code>ItemState</code> and <code>NodeReferences</code> objects
in Oracle
+ * database using a simple custom serialization format and a
+ * very basic non-normalized database schema (in essence tables with one 'key'
+ * and one 'data' column).
+ * <p/>
+ * It is configured through the following properties:
+ * <ul>
+ * <li><code>driver</code>: the FQN name of the JDBC driver class
+ * (default: <code>"oracle.jdbc.OracleDriver"</code>)</li>
+ * <li><code>schema</code>: type of schema to be used
+ * (default: <code>"oracle"</code>)</li>
+ * <li><code>url</code>: the database url (e.g.
+ * <code>"jdbc:oracle:thin:@[host]:[port]:[sid]"</code>)</li>
+ * <li><code>user</code>: the database user</li>
+ * <li><code>password</code>: the user's password</li>
+ * <li><code>schemaObjectPrefix</code>: prefix to be prepended to schema
objects</li>
+ * <li><code>externalBLOBs</code>: if <code>true</code> (the
default) BINARY
+ * values (BLOBs) are stored in the local file system;
+ * if <code>false</code> BLOBs are stored in the database</li>
+ * </ul>
+ * See also {@link SimpleDbPersistenceManager}.
+ * <p/>
+ * The following is a fragment from a sample configuration:
+ * <pre>
+ *   &lt;PersistenceManager class="org.apache.jackrabbit.core.state.db.OraclePersistenceManager"&gt;
+ *       &lt;param name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/&gt;
+ *       &lt;param name="user" value="scott"/&gt;
+ *       &lt;param name="password" value="tiger"/&gt;
+ *       &lt;param name="schemaObjectPrefix" value="${wsp.name}_"/&gt;
+ *       &lt;param name="externalBLOBs" value="false"/&gt;
+ *  &lt;/PersistenceManager&gt;
+ * </pre>
+ */
+public class OraclePersistenceManager extends SimpleDbPersistenceManager {
+
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(OraclePersistenceManager.class);
+
+    private Class blobClass;
+    private Integer DURATION_SESSION_CONSTANT;
+    private Integer MODE_READWRITE_CONSTANT;
+
+    /**
+     * Creates a new <code>OraclePersistenceManager</code> instance.
+     */
+    public OraclePersistenceManager() {
+        // preset some attributes to reasonable defaults
+        schema = "oracle";
+        driver = "oracle.jdbc.OracleDriver";
+        schemaObjectPrefix = "";
+        user = "";
+        password = "";
+        initialized = false;
+    }
+
+    //---------------------------------< SimpleDbPersistenceManager overrides >
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Retrieve the <code>oracle.sql.BLOB</code> class via reflection, and
+     * initialize the values for the <code>DURATION_SESSION</code> and
+     * <code>MODE_READWRITE</code> constants defined there.
+     * @see oracle.sql.BLOB#DURATION_SESSION
+     * @see oracle.sql.BLOB#MODE_READWRITE
+     */
+    public void init(PMContext context) throws Exception {
+        super.init(context);
+
+        if (!externalBLOBs) {
+            blobStore = new OracleBLOBStore();
+        }
+
+        // initialize oracle.sql.BLOB class & constants
+
+        // use the Connection object for using the exact same
+        // class loader that the Oracle driver was loaded with
+        blobClass = con.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
+        DURATION_SESSION_CONSTANT =
+                new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
+        MODE_READWRITE_CONSTANT =
+                new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void store(NodeState state) throws ItemStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+
+        // check if insert or update
+        boolean update = state.getStatus() != ItemState.STATUS_NEW;
+        //boolean update = exists((NodeId) state.getId());
+        PreparedStatement stmt = (update) ? nodeStateUpdate : nodeStateInsert;
+
+        Blob blob = null;
+        try {
+            ByteArrayOutputStream out =
+                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+            // serialize node state
+            Serializer.serialize(state, out);
+
+            // we are synchronized on this instance, therefore we do not
+            // not have to additionally synchronize on the preparedStatement
+
+            blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
+            stmt.setBlob(1, blob);
+            stmt.setString(2, state.getId().toString());
+            stmt.executeUpdate();
+
+            // there's no need to close a ByteArrayOutputStream
+            //out.close();
+        } catch (Exception e) {
+            String msg = "failed to write node state: " + state.getId();
+            log.error(msg, e);
+            throw new ItemStateException(msg, e);
+        } finally {
+            resetStatement(stmt);
+            if (blob != null) {
+                try {
+                    freeTemporaryBlob(blob);
+                } catch (Exception e1) {
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void store(PropertyState state) throws ItemStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+
+        // check if insert or update
+        boolean update = state.getStatus() != ItemState.STATUS_NEW;
+        //boolean update = exists((PropertyId) state.getId());
+        PreparedStatement stmt = (update) ? propertyStateUpdate : propertyStateInsert;
+
+        Blob blob = null;
+        try {
+            ByteArrayOutputStream out =
+                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+            // serialize property state
+            Serializer.serialize(state, out, blobStore);
+
+            // we are synchronized on this instance, therefore we do not
+            // not have to additionally synchronize on the preparedStatement
+
+            blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
+            stmt.setBlob(1, blob);
+            stmt.setString(2, state.getId().toString());
+            stmt.executeUpdate();
+
+            // there's no need to close a ByteArrayOutputStream
+            //out.close();
+        } catch (Exception e) {
+            String msg = "failed to write property state: " + state.getId();
+            log.error(msg, e);
+            throw new ItemStateException(msg, e);
+        } finally {
+            resetStatement(stmt);
+            if (blob != null) {
+                try {
+                    freeTemporaryBlob(blob);
+                } catch (Exception e1) {
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void store(NodeReferences refs) throws ItemStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+
+        // check if insert or update
+        boolean update = exists(refs.getId());
+        PreparedStatement stmt = (update) ? nodeReferenceUpdate : nodeReferenceInsert;
+
+        Blob blob = null;
+        try {
+            ByteArrayOutputStream out =
+                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+            // serialize references
+            Serializer.serialize(refs, out);
+
+            // we are synchronized on this instance, therefore we do not
+            // not have to additionally synchronize on the preparedStatement
+
+            blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
+            stmt.setBlob(1, blob);
+            stmt.setString(2, refs.getId().toString());
+            stmt.executeUpdate();
+
+            // there's no need to close a ByteArrayOutputStream
+            //out.close();
+        } catch (Exception e) {
+            String msg = "failed to write node references: " + refs.getId();
+            log.error(msg, e);
+            throw new ItemStateException(msg, e);
+        } finally {
+            resetStatement(stmt);
+            if (blob != null) {
+                try {
+                    freeTemporaryBlob(blob);
+                } catch (Exception e1) {
+                }
+            }
+        }
+    }
+
+    //----------------------------------------< oracle-specific blob handling >
+    /**
+     * Creates a temporary oracle.sql.BLOB instance via reflection and spools
+     * the contents of the specified stream.
+     */
+    protected Blob createTemporaryBlob(InputStream in) throws Exception {
+        /*
+        BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
+        blob.open(BLOB.MODE_READWRITE);
+        OutputStream out = blob.getBinaryOutputStream();
+        ...
+        out.flush();
+        out.close();
+        blob.close();
+        return blob;
+        */
+        Method createTemporary = blobClass.getMethod("createTemporary",
+                new Class[]{Connection.class, Boolean.TYPE, Integer.TYPE});
+        Object blob = createTemporary.invoke(null,
+                new Object[]{con, Boolean.FALSE, DURATION_SESSION_CONSTANT});
+        Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
+        open.invoke(blob, new Object[]{MODE_READWRITE_CONSTANT});
+        Method getBinaryOutputStream =
+                blobClass.getMethod("getBinaryOutputStream", new Class[0]);
+        OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob, null);
+        try {
+            int read;
+            byte[] buf = new byte[8192];
+            while ((read = in.read(buf, 0, buf.length)) > -1) {
+                out.write(buf, 0, read);
+            }
+        } finally {
+            try {
+                out.flush();
+            } catch (IOException ioe) {
+            }
+            out.close();
+        }
+        Method close = blobClass.getMethod("close", new Class[0]);
+        close.invoke(blob, null);
+        return (Blob) blob;
+    }
+
+    /**
+     * Frees a temporary oracle.sql.BLOB instance via reflection.
+     */
+    protected void freeTemporaryBlob(Object blob) throws Exception {
+        // blob.freeTemporary();
+        Method freeTemporary = blobClass.getMethod("freeTemporary", new Class[0]);
+        freeTemporary.invoke(blob, null);
+    }
+
+    //--------------------------------------------------------< inner classes >
+    class OracleBLOBStore extends DbBLOBStore {
+        /**
+         * {@inheritDoc}
+         */
+        public synchronized void put(String blobId, InputStream in, long size)
+                throws Exception {
+            PreparedStatement stmt = blobSelectExist;
+            Blob blob = null;
+            try {
+                stmt.setString(1, blobId);
+                stmt.execute();
+                ResultSet rs = stmt.getResultSet();
+                // a BLOB exists if the result has at least one entry
+                boolean exists = rs.next();
+                resetStatement(stmt);
+                closeResultSet(rs);
+
+                stmt = (exists) ? blobUpdate : blobInsert;
+
+                blob = createTemporaryBlob(in);
+                stmt.setBlob(1, blob);
+                stmt.setString(2, blobId);
+                stmt.executeUpdate();
+            } finally {
+                resetStatement(stmt);
+                if (blob != null) {
+                    try {
+                        freeTemporaryBlob(blob);
+                    } catch (Exception e1) {
+                    }
+                }
+            }
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java?rev=413685&r1=413684&r2=413685&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java
Mon Jun 12 08:45:50 2006
@@ -107,7 +107,7 @@
  *       &lt;param name="externalBLOBs" value="false"/&gt;
  *   &lt;/PersistenceManager&gt;
  * </pre>
- * See also {@link DerbyPersistenceManager}.
+ * See also {@link DerbyPersistenceManager}, {@link OraclePersistenceManager}.
  */
 public class SimpleDbPersistenceManager extends DatabasePersistenceManager {
 

Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl?rev=413685&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
(added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
Mon Jun 12 08:45:50 2006
@@ -0,0 +1,8 @@
+create table ${schemaObjectPrefix}NODE (NODE_ID char(36) not null, NODE_DATA blob not null)
+create unique index ${schemaObjectPrefix}NODE_IDX on ${schemaObjectPrefix}NODE (NODE_ID)
+create table ${schemaObjectPrefix}PROP (PROP_ID varchar2(1024) not null, PROP_DATA blob not
null)
+create unique index ${schemaObjectPrefix}PROP_IDX on ${schemaObjectPrefix}PROP (PROP_ID)
+create table ${schemaObjectPrefix}REFS (NODE_ID char(36) not null, REFS_DATA blob not null)
+create unique index ${schemaObjectPrefix}REFS_IDX on ${schemaObjectPrefix}REFS (NODE_ID)
+create table ${schemaObjectPrefix}BINVAL (BINVAL_ID varchar2(1024) not null, BINVAL_DATA
blob null)
+create unique index ${schemaObjectPrefix}BINVAL_IDX on ${schemaObjectPrefix}BINVAL (BINVAL_ID)

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message