You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2006/10/26 11:11:20 UTC
svn commit: r467925 [1/6] - in /jackrabbit/trunk/jackrabbit:
applications/test/ applications/test/workspaces/default/
applications/test/workspaces/test/ src/main/config/
src/main/java/org/apache/jackrabbit/core/
src/main/java/org/apache/jackrabbit/core...
Author: tripod
Date: Thu Oct 26 02:11:18 2006
New Revision: 467925
URL: http://svn.apache.org/viewvc?view=rev&rev=467925
Log:
JCR-595 Refactoring of the Persistence Managers (+changing some eol-styles)
Added:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/JNDIDatabasePersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/OraclePersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/SimpleDbPersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/daffodil.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/db2.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/default.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/derby.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/mssql.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/mysql.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/oracle.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/package.html (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/postgresql.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/mem/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemPersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/obj/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/obj/ObjectPersistenceManager.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/util/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/util/BLOBStore.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/util/FileSystemBLOBStore.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/util/ResourceBasedBLOBStore.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/util/Serializer.java (with props)
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/xml/
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/xml/XMLPersistenceManager.java (with props)
Removed:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/daffodil.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/db2.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/default.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/derby.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/mssql.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/mysql.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/oracle.ddl
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/package.html
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/postgresql.ddl
Modified:
jackrabbit/trunk/jackrabbit/applications/test/repository.xml
jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml (contents, props changed)
jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml (contents, props changed)
jackrabbit/trunk/jackrabbit/src/main/config/repository.xml
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/repository.xml
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/AbstractPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/PMContext.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/PersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/DatabasePersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/DerbyPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/JNDIDatabasePersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/OraclePersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/db/SimpleDbPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/util/BLOBStore.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/util/FileSystemBLOBStore.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/util/ResourceBasedBLOBStore.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/util/Serializer.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/test-repository.xml
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
jackrabbit/trunk/jackrabbit/src/site/xdoc/doc/config.xml
jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java
jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java
jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/config/repository.xml (contents, props changed)
jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/config/workspace.xml
Modified: jackrabbit/trunk/jackrabbit/applications/test/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/applications/test/repository.xml?view=diff&rev=467925&r1=467924&r2=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/applications/test/repository.xml (original)
+++ jackrabbit/trunk/jackrabbit/applications/test/repository.xml Thu Oct 26 02:11:18 2006
@@ -193,7 +193,7 @@
persistence manager of the workspace:
class: FQN of class implementing the PersistenceManager interface
-->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
<param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
<param name="schemaObjectPrefix" value="${wsp.name}_"/>
</PersistenceManager>
@@ -224,7 +224,7 @@
a 'normal' persistence manager, but this could change in future
implementations.
-->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
<param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>
<param name="schemaObjectPrefix" value="version_"/>
</PersistenceManager>
Modified: jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml?view=diff&rev=467925&r1=467924&r2=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml (original)
+++ jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml Thu Oct 26 02:11:18 2006
@@ -1,46 +1,46 @@
-<?xml version="1.0"?>
-<!--
- 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.
- -->
-<Workspace name="default">
- <!--
- virtual file system of the workspace:
- class: FQN of class implementing FileSystem interface
- -->
- <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
- <param name="path" value="${wsp.home}" />
- </FileSystem>
- <!--
- persistence of the workspace:
- class: FQN of class implementing PersistenceManager interface
- -->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
- <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
- <param name="schemaObjectPrefix" value="${wsp.name}_"/>
- </PersistenceManager>
- <!--
- Search index and the file system it uses.
- -->
- <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
- <param name="path" value="${wsp.home}/index" />
- <!--
- Set to zero for test purpose. This is *not* recommended at all for a
- real system!
- -->
- <param name="idleTime" value="0"/>
- </SearchIndex>
-</Workspace>
-
+<?xml version="1.0"?>
+<!--
+ 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.
+ -->
+<Workspace name="default">
+ <!--
+ virtual file system of the workspace:
+ class: FQN of class implementing FileSystem interface
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${wsp.home}" />
+ </FileSystem>
+ <!--
+ persistence of the workspace:
+ class: FQN of class implementing PersistenceManager interface
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
+ <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
+ <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+ </PersistenceManager>
+ <!--
+ Search index and the file system it uses.
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${wsp.home}/index" />
+ <!--
+ Set to zero for test purpose. This is *not* recommended at all for a
+ real system!
+ -->
+ <param name="idleTime" value="0"/>
+ </SearchIndex>
+</Workspace>
+
Propchange: jackrabbit/trunk/jackrabbit/applications/test/workspaces/default/workspace.xml
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml?view=diff&rev=467925&r1=467924&r2=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml (original)
+++ jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml Thu Oct 26 02:11:18 2006
@@ -1,41 +1,41 @@
-<?xml version="1.0"?>
-<!--
- 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.
- -->
-<Workspace name="test">
- <!--
- virtual file system of the workspace:
- class: FQN of class implementing FileSystem interface
- -->
- <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
- <param name="path" value="${wsp.home}" />
- </FileSystem>
- <!--
- persistence of the workspace:
- class: FQN of class implementing PersistenceManager interface
- -->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
- <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
- <param name="schemaObjectPrefix" value="${wsp.name}_"/>
- </PersistenceManager>
- <!--
- Search index and the file system it uses.
- -->
- <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
- <param name="path" value="${wsp.home}/index" />
- </SearchIndex>
-</Workspace>
-
+<?xml version="1.0"?>
+<!--
+ 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.
+ -->
+<Workspace name="test">
+ <!--
+ virtual file system of the workspace:
+ class: FQN of class implementing FileSystem interface
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${wsp.home}" />
+ </FileSystem>
+ <!--
+ persistence of the workspace:
+ class: FQN of class implementing PersistenceManager interface
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
+ <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
+ <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+ </PersistenceManager>
+ <!--
+ Search index and the file system it uses.
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${wsp.home}/index" />
+ </SearchIndex>
+</Workspace>
+
Propchange: jackrabbit/trunk/jackrabbit/applications/test/workspaces/test/workspace.xml
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit/src/main/config/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/config/repository.xml?view=diff&rev=467925&r1=467924&r2=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/config/repository.xml (original)
+++ jackrabbit/trunk/jackrabbit/src/main/config/repository.xml Thu Oct 26 02:11:18 2006
@@ -203,7 +203,7 @@
persistence manager of the workspace:
class: FQN of class implementing the PersistenceManager interface
-->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
<param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
<param name="schemaObjectPrefix" value="${wsp.name}_"/>
</PersistenceManager>
@@ -282,7 +282,7 @@
a 'normal' persistence manager, but this could change in future
implementations.
-->
- <PersistenceManager class="org.apache.jackrabbit.core.state.db.DerbyPersistenceManager">
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
<param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>
<param name="schemaObjectPrefix" value="version_"/>
</PersistenceManager>
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&rev=467925&r1=467924&r2=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Thu Oct 26 02:11:18 2006
@@ -42,8 +42,8 @@
import org.apache.jackrabbit.core.observation.ObservationDispatcher;
import org.apache.jackrabbit.core.security.AuthContext;
import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.PMContext;
-import org.apache.jackrabbit.core.state.PersistenceManager;
+import org.apache.jackrabbit.core.persistence.PMContext;
+import org.apache.jackrabbit.core.persistence.PersistenceManager;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.version.VersionManagerImpl;
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java?view=auto&rev=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java Thu Oct 26 02:11:18 2006
@@ -0,0 +1,148 @@
+/*
+ * 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.persistence;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+
+import java.util.Iterator;
+
+/**
+ * Implementation <code>PersistenceManager</code> that handles some
+ * concepts.
+ */
+public abstract class AbstractPersistenceManager implements PersistenceManager {
+
+ /**
+ * {@inheritDoc}
+ */
+ public NodeState createNew(NodeId id) {
+ return new NodeState(id, null, null, NodeState.STATUS_NEW, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PropertyState createNew(PropertyId id) {
+ return new PropertyState(id, PropertyState.STATUS_NEW, false);
+ }
+
+ /**
+ * Right now, this iterates over all items in the changelog and
+ * calls the individual methods that handle single item states
+ * or node references objects. Properly implemented, this method
+ * should ensure that changes are either written completely to
+ * the underlying persistence layer, or not at all.
+ *
+ * {@inheritDoc}
+ */
+ public synchronized void store(ChangeLog changeLog) throws ItemStateException {
+ Iterator iter = changeLog.deletedStates();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ if (state.isNode()) {
+ destroy((NodeState) state);
+ } else {
+ destroy((PropertyState) state);
+ }
+ }
+ iter = changeLog.addedStates();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ if (state.isNode()) {
+ store((NodeState) state);
+ } else {
+ store((PropertyState) state);
+ }
+ }
+ iter = changeLog.modifiedStates();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ if (state.isNode()) {
+ store((NodeState) state);
+ } else {
+ store((PropertyState) state);
+ }
+ }
+ iter = changeLog.modifiedRefs();
+ while (iter.hasNext()) {
+ NodeReferences refs = (NodeReferences) iter.next();
+ if (refs.hasReferences()) {
+ store(refs);
+ } else {
+ if (exists(refs.getId())) {
+ destroy(refs);
+ }
+ }
+ }
+ }
+
+ /**
+ * Store a node state. Subclass responsibility.
+ *
+ * @param state node state to store
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void store(NodeState state) throws ItemStateException;
+
+ /**
+ * Store a property state. Subclass responsibility.
+ *
+ * @param state property state to store
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void store(PropertyState state) throws ItemStateException;
+
+ /**
+ * Store a references object. Subclass responsibility.
+ *
+ * @param refs references object to store
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void store(NodeReferences refs) throws ItemStateException;
+
+ /**
+ * Destroy a node state. Subclass responsibility.
+ *
+ * @param state node state to destroy
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void destroy(NodeState state) throws ItemStateException;
+
+ /**
+ * Destroy a property state. Subclass responsibility.
+ *
+ * @param state property state to destroy
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void destroy(PropertyState state) throws ItemStateException;
+
+ /**
+ * Destroy a node references object. Subclass responsibility.
+ *
+ * @param refs node references object to destroy
+ * @throws ItemStateException if an error occurs
+ */
+ protected abstract void destroy(NodeReferences refs)
+ throws ItemStateException;
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url rev
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java?view=auto&rev=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java Thu Oct 26 02:11:18 2006
@@ -0,0 +1,123 @@
+/*
+ * 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.persistence;
+
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.persistence.PersistenceManager;
+
+import javax.jcr.NamespaceRegistry;
+import java.io.File;
+
+/**
+ * A <code>PMContext</code> is used to provide context information for a
+ * <code>PersistenceManager</code>.
+ *
+ * @see PersistenceManager#init(PMContext)
+ */
+public class PMContext {
+
+ /**
+ * the physcial home dir
+ */
+ private final File physicalHomeDir;
+
+ /**
+ * the virtual jackrabbit filesystem
+ */
+ private final FileSystem fs;
+
+ /**
+ * namespace registry
+ */
+ private final NamespaceRegistry nsReg;
+
+ /**
+ * node type registry
+ */
+ private final NodeTypeRegistry ntReg;
+
+ /**
+ * uuid of the root node
+ */
+ private final NodeId rootNodeId;
+
+ /**
+ * Creates a new <code>PMContext</code>.
+ *
+ * @param homeDir the physical home directory
+ * @param fs the virtual jackrabbit filesystem
+ * @param rootNodeId id of the root node
+ * @param nsReg namespace registry
+ * @param ntReg node type registry
+ */
+ public PMContext(File homeDir,
+ FileSystem fs,
+ NodeId rootNodeId,
+ NamespaceRegistry nsReg,
+ NodeTypeRegistry ntReg) {
+ this.physicalHomeDir = homeDir;
+ this.fs = fs;
+ this.rootNodeId = rootNodeId;
+ this.nsReg = nsReg;
+ this.ntReg = ntReg;
+ }
+
+
+ /**
+ * Returns the physical home directory for this persistence manager
+ * @return the physical home directory for this persistence manager
+ */
+ public File getHomeDir() {
+ return physicalHomeDir;
+ }
+
+ /**
+ * Returns the virtual filesystem for this persistence manager
+ * @return the virtual filesystem for this persistence manager
+ */
+ public FileSystem getFileSystem() {
+ return fs;
+ }
+
+ /**
+ * Returns the id of the root node
+ * @return the id of the root node
+ */
+ public NodeId getRootNodeId() {
+ return rootNodeId;
+ }
+
+ /**
+ * Returns the namespace registry
+ *
+ * @return the namespace registry
+ */
+ public NamespaceRegistry getNamespaceRegistry() {
+ return nsReg;
+ }
+
+ /**
+ * Returns the node type registry
+ *
+ * @return the node type registry
+ */
+ public NodeTypeRegistry getNodeTypeRegistry() {
+ return ntReg;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url rev
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java?view=auto&rev=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java Thu Oct 26 02:11:18 2006
@@ -0,0 +1,183 @@
+/*
+ * 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.persistence;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.persistence.PMContext;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.core.state.ChangeLog;
+
+/**
+ * Persistence manager interface. Persistence managers are
+ * internal Jackrabbit components that handle the persistent
+ * storage of content nodes and properties. A persistence
+ * manager knows how to retrieve the persistent states of
+ * content items and how to atomically save a set of changes
+ * to the persistent state.
+ * <p>
+ * Each workspace of a Jackrabbit content repository uses separate
+ * persistence manager to store the content in that workspace. Also
+ * the Jackrabbit version handler uses a separate persistence manager.
+ * The persistence managers in use are configured in the Jackrabbit
+ * XML configuration files. The configured persistence managers are
+ * instantiated and initialized using the JavaBeans conventions.
+ *
+ * <h2>Persistence manager life cycle</h2>
+ * <p>
+ * The life cycle of a persistence manager instance contains four phases:
+ * <ol>
+ * <li>Instantiation, where the instance is created and possible
+ * configuration properties are set using the JavaBean conventions.
+ * During this phase the persistence manager should not attempt to
+ * reference any external resources.
+ * <li>Initialization, where the {@link #init(PMContext) init} method
+ * is invoked to bind the persistence manager with a given
+ * {@link PMContext context}.
+ * <li>Normal usage, where the various create, load, exists, and store
+ * methods of the persistence manager are used to manage the
+ * persistent content items.
+ * <li>Closing, where the {@link #close() close} method is invoked
+ * to close the persistence manager and release all acquired
+ * resources.
+ * </ol>
+ */
+public interface PersistenceManager {
+
+ /**
+ * Initializes the persistence manager. The persistence manager is
+ * permanently bound to the given context, and any required external
+ * resources are acquired.
+ * <p>
+ * An appropriate exception is thrown if the persistence manager
+ * initialization fails for whatever reason. In this case the
+ * state of the persistence manager is undefined and the instance
+ * should be discarded.
+ *
+ * @param context persistence manager context
+ * @throws Exception if the persistence manager intialization failed
+ */
+ void init(PMContext context) throws Exception;
+
+ /**
+ * Closes the persistence manager. The consistency of the persistent
+ * storage is guaranteed and all acquired resources are released.
+ * It is an error to invoke any methods on a closed persistence manager,
+ * and implementations are free to enforce this constraint by throwing
+ * IllegalStateExceptions in such cases.
+ * <p>
+ * An appropriate exception is thrown if the persistence manager
+ * could not be closed properly. In this case the state of the
+ * persistence manager is undefined and the instance should be
+ * discarded.
+ *
+ * @throws Exception if the persistence manager failed to close properly
+ */
+ void close() throws Exception;
+
+ /**
+ * Creates a new node state instance with the given id.
+ *
+ * @param id node id
+ * @return node state instance
+ */
+ NodeState createNew(NodeId id);
+
+ /**
+ * Creates a new property state instance with the given id.
+ *
+ * @param id property id
+ * @return property state instance
+ */
+ PropertyState createNew(PropertyId id);
+
+ /**
+ * Load the persistent members of a node state.
+ *
+ * @param id node id
+ * @return loaded node state
+ * @throws NoSuchItemStateException if the node state does not exist
+ * @throws ItemStateException if another error occurs
+ */
+ NodeState load(NodeId id)
+ throws NoSuchItemStateException, ItemStateException;
+
+ /**
+ * Load the persistent members of a property state.
+ *
+ * @param id property id
+ * @return loaded property state
+ * @throws NoSuchItemStateException if the property state does not exist
+ * @throws ItemStateException if another error occurs
+ */
+ PropertyState load(PropertyId id)
+ throws NoSuchItemStateException, ItemStateException;
+
+ /**
+ * Load the persistent members of a node references object.
+ *
+ * @param id reference target node id
+ * @throws NoSuchItemStateException if the target node does not exist
+ * @throws ItemStateException if another error occurs
+ */
+ NodeReferences load(NodeReferencesId id)
+ throws NoSuchItemStateException, ItemStateException;
+
+ /**
+ * Checks whether the identified node exists.
+ *
+ * @param id node id
+ * @return <code>true</code> if the node exists,
+ * <code>false</code> otherwise
+ * @throws ItemStateException on persistence manager errors
+ */
+ boolean exists(NodeId id) throws ItemStateException;
+
+ /**
+ * Checks whether the identified property exists.
+ *
+ * @param id property id
+ * @return <code>true</code> if the property exists,
+ * <code>false</code> otherwise
+ * @throws ItemStateException on persistence manager errors
+ */
+ boolean exists(PropertyId id) throws ItemStateException;
+
+ /**
+ * Checks whether references of the identified target node exist.
+ *
+ * @param targetId target node id
+ * @return <code>true</code> if the references exist,
+ * <code>false</code> otherwise
+ * @throws ItemStateException on persistence manager errors
+ */
+ boolean exists(NodeReferencesId targetId) throws ItemStateException;
+
+ /**
+ * Atomically saves the given set of changes.
+ *
+ * @param changeLog change log containing states that were changed
+ * @throws ItemStateException if the changes could not be saved
+ */
+ void store(ChangeLog changeLog) throws ItemStateException;
+
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url rev
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java?view=auto&rev=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java Thu Oct 26 02:11:18 2006
@@ -0,0 +1,1075 @@
+/*
+ * 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.persistence.db;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.persistence.PMContext;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.persistence.db.SimpleDbPersistenceManager;
+import org.apache.jackrabbit.core.persistence.util.BLOBStore;
+import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
+import org.apache.jackrabbit.core.persistence.util.Serializer;
+import org.apache.jackrabbit.core.value.BLOBFileValue;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.FilterInputStream;
+import java.io.ByteArrayInputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.DatabaseMetaData;
+
+/**
+ * Abstract base class for database persistence managers. This class
+ * contains common functionality for database persistence manager subclasses
+ * that normally differ only in the way the database connection is acquired.
+ * Subclasses should override the {@link #getConnection()} method to return
+ * the configured database connection.
+ * <p>
+ * See the {@link SimpleDbPersistenceManager} for a detailed description
+ * of the available configuration options and database behaviour.
+ */
+public abstract class DatabasePersistenceManager extends AbstractPersistenceManager {
+
+ /**
+ * Logger instance
+ */
+ private static Logger log = LoggerFactory.getLogger(DatabasePersistenceManager.class);
+
+ protected static final String SCHEMA_OBJECT_PREFIX_VARIABLE =
+ "${schemaObjectPrefix}";
+
+ protected boolean initialized;
+
+ protected String schema;
+ protected String schemaObjectPrefix;
+
+ protected boolean externalBLOBs;
+
+ // initial size of buffer used to serialize objects
+ protected static final int INITIAL_BUFFER_SIZE = 1024;
+
+ // jdbc connection
+ protected Connection con;
+
+ // shared prepared statements for NodeState management
+ protected PreparedStatement nodeStateInsert;
+ protected PreparedStatement nodeStateUpdate;
+ protected PreparedStatement nodeStateSelect;
+ protected PreparedStatement nodeStateSelectExist;
+ protected PreparedStatement nodeStateDelete;
+
+ // shared prepared statements for PropertyState management
+ protected PreparedStatement propertyStateInsert;
+ protected PreparedStatement propertyStateUpdate;
+ protected PreparedStatement propertyStateSelect;
+ protected PreparedStatement propertyStateSelectExist;
+ protected PreparedStatement propertyStateDelete;
+
+ // shared prepared statements for NodeReference management
+ protected PreparedStatement nodeReferenceInsert;
+ protected PreparedStatement nodeReferenceUpdate;
+ protected PreparedStatement nodeReferenceSelect;
+ protected PreparedStatement nodeReferenceSelectExist;
+ protected PreparedStatement nodeReferenceDelete;
+
+ // shared prepared statements for BLOB management
+ // (if <code>externalBLOBs==false</code>)
+ protected PreparedStatement blobInsert;
+ protected PreparedStatement blobUpdate;
+ protected PreparedStatement blobSelect;
+ protected PreparedStatement blobSelectExist;
+ protected PreparedStatement blobDelete;
+
+ /**
+ * file system where BLOB data is stored
+ * (if <code>externalBLOBs==true</code>)
+ */
+ protected FileSystem blobFS;
+ /**
+ * BLOBStore that manages BLOB data in the file system
+ * (if <code>externalBLOBs==true</code>)
+ */
+ protected BLOBStore blobStore;
+
+ /**
+ * Creates a new <code>DatabasePersistenceManager</code> instance.
+ */
+ public DatabasePersistenceManager() {
+ schema = "default";
+ schemaObjectPrefix = "";
+ externalBLOBs = true;
+ initialized = false;
+ }
+
+ //----------------------------------------------------< setters & getters >
+
+ public String getSchemaObjectPrefix() {
+ return schemaObjectPrefix;
+ }
+
+ public void setSchemaObjectPrefix(String schemaObjectPrefix) {
+ // make sure prefix is all uppercase
+ this.schemaObjectPrefix = schemaObjectPrefix.toUpperCase();
+ }
+
+ public String getSchema() {
+ return schema;
+ }
+
+ public void setSchema(String schema) {
+ this.schema = schema;
+ }
+
+ public boolean isExternalBLOBs() {
+ return externalBLOBs;
+ }
+
+ public void setExternalBLOBs(boolean externalBLOBs) {
+ this.externalBLOBs = externalBLOBs;
+ }
+
+ public void setExternalBLOBs(String externalBLOBs) {
+ this.externalBLOBs = Boolean.valueOf(externalBLOBs).booleanValue();
+ }
+
+ //---------------------------------------------------< PersistenceManager >
+ /**
+ * {@inheritDoc}
+ */
+ public void init(PMContext context) throws Exception {
+ if (initialized) {
+ throw new IllegalStateException("already initialized");
+ }
+
+ // setup jdbc connection
+ initConnection();
+
+ // make sure schemaObjectPrefix consists of legal name characters only
+ prepareSchemaObjectPrefix();
+
+ // check if schema objects exist and create them if necessary
+ checkSchema();
+
+ // prepare statements
+ nodeStateInsert =
+ con.prepareStatement("insert into "
+ + schemaObjectPrefix + "NODE (NODE_DATA, NODE_ID) values (?, ?)");
+ nodeStateUpdate =
+ con.prepareStatement("update "
+ + schemaObjectPrefix + "NODE set NODE_DATA = ? where NODE_ID = ?");
+ nodeStateSelect =
+ con.prepareStatement("select NODE_DATA from "
+ + schemaObjectPrefix + "NODE where NODE_ID = ?");
+ nodeStateSelectExist =
+ con.prepareStatement("select 1 from "
+ + schemaObjectPrefix + "NODE where NODE_ID = ?");
+ nodeStateDelete =
+ con.prepareStatement("delete from "
+ + schemaObjectPrefix + "NODE where NODE_ID = ?");
+
+ propertyStateInsert =
+ con.prepareStatement("insert into "
+ + schemaObjectPrefix + "PROP (PROP_DATA, PROP_ID) values (?, ?)");
+ propertyStateUpdate =
+ con.prepareStatement("update "
+ + schemaObjectPrefix + "PROP set PROP_DATA = ? where PROP_ID = ?");
+ propertyStateSelect =
+ con.prepareStatement("select PROP_DATA from "
+ + schemaObjectPrefix + "PROP where PROP_ID = ?");
+ propertyStateSelectExist =
+ con.prepareStatement("select 1 from "
+ + schemaObjectPrefix + "PROP where PROP_ID = ?");
+ propertyStateDelete =
+ con.prepareStatement("delete from "
+ + schemaObjectPrefix + "PROP where PROP_ID = ?");
+
+ nodeReferenceInsert =
+ con.prepareStatement("insert into "
+ + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID) values (?, ?)");
+ nodeReferenceUpdate =
+ con.prepareStatement("update "
+ + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID = ?");
+ nodeReferenceSelect =
+ con.prepareStatement("select REFS_DATA from "
+ + schemaObjectPrefix + "REFS where NODE_ID = ?");
+ nodeReferenceSelectExist =
+ con.prepareStatement("select 1 from "
+ + schemaObjectPrefix + "REFS where NODE_ID = ?");
+ nodeReferenceDelete =
+ con.prepareStatement("delete from "
+ + schemaObjectPrefix + "REFS where NODE_ID = ?");
+
+ if (externalBLOBs) {
+ /**
+ * store BLOBs in local file system in a sub directory
+ * of the workspace home directory
+ */
+ LocalFileSystem blobFS = new LocalFileSystem();
+ blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
+ blobFS.init();
+ this.blobFS = blobFS;
+ blobStore = new FileSystemBLOBStore(blobFS);
+ } else {
+ /**
+ * store BLOBs in db
+ */
+ blobStore = new DbBLOBStore();
+
+ blobInsert =
+ con.prepareStatement("insert into "
+ + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)");
+ blobUpdate =
+ con.prepareStatement("update "
+ + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?");
+ blobSelect =
+ con.prepareStatement("select BINVAL_DATA from "
+ + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
+ blobSelectExist =
+ con.prepareStatement("select 1 from "
+ + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
+ blobDelete =
+ con.prepareStatement("delete from "
+ + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void close() throws Exception {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ try {
+ // close shared prepared statements
+ closeStatement(nodeStateInsert);
+ closeStatement(nodeStateUpdate);
+ closeStatement(nodeStateSelect);
+ closeStatement(nodeStateSelectExist);
+ closeStatement(nodeStateDelete);
+
+ closeStatement(propertyStateInsert);
+ closeStatement(propertyStateUpdate);
+ closeStatement(propertyStateSelect);
+ closeStatement(propertyStateSelectExist);
+ closeStatement(propertyStateDelete);
+
+ closeStatement(nodeReferenceInsert);
+ closeStatement(nodeReferenceUpdate);
+ closeStatement(nodeReferenceSelect);
+ closeStatement(nodeReferenceSelectExist);
+ closeStatement(nodeReferenceDelete);
+
+ if (!externalBLOBs) {
+ closeStatement(blobInsert);
+ closeStatement(blobUpdate);
+ closeStatement(blobSelect);
+ closeStatement(blobSelectExist);
+ closeStatement(blobDelete);
+ } else {
+ // close BLOB file system
+ blobFS.close();
+ blobFS = null;
+ }
+ blobStore = null;
+
+ // close jdbc connection
+ closeConnection(con);
+
+ } finally {
+ initialized = false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void store(ChangeLog changeLog)
+ throws ItemStateException {
+ ItemStateException ise = null;
+ try {
+ super.store(changeLog);
+ } catch (ItemStateException e) {
+ ise = e;
+ } finally {
+ if (ise == null) {
+ // storing the changes succeeded, now commit the changes
+ try {
+ con.commit();
+ } catch (SQLException e) {
+ String msg = "committing change log failed";
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ }
+ } else {
+ // storing the changes failed, rollback changes
+ try {
+ con.rollback();
+ } catch (SQLException e) {
+ String msg = "rollback of change log failed";
+ log.error(msg, e);
+ }
+ // re-throw original exception
+ throw ise;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NodeState load(NodeId id)
+ throws NoSuchItemStateException, ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeStateSelect;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ InputStream in = null;
+ try {
+ stmt.setString(1, id.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+ if (!rs.next()) {
+ throw new NoSuchItemStateException(id.toString());
+ }
+
+ in = rs.getBinaryStream(1);
+ NodeState state = createNew(id);
+ Serializer.deserialize(state, in);
+
+ return state;
+ } catch (Exception e) {
+ if (e instanceof NoSuchItemStateException) {
+ throw (NoSuchItemStateException) e;
+ }
+ String msg = "failed to read node state: " + id;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeStream(in);
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PropertyState load(PropertyId id)
+ throws NoSuchItemStateException, ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = propertyStateSelect;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ InputStream in = null;
+ try {
+ stmt.setString(1, id.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+ if (!rs.next()) {
+ throw new NoSuchItemStateException(id.toString());
+ }
+
+ in = rs.getBinaryStream(1);
+ PropertyState state = createNew(id);
+ Serializer.deserialize(state, in, blobStore);
+
+ return state;
+ } catch (Exception e) {
+ if (e instanceof NoSuchItemStateException) {
+ throw (NoSuchItemStateException) e;
+ }
+ String msg = "failed to read property state: " + id;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeStream(in);
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * This method uses shared <code>PreparedStatement</code>s which must
+ * be executed strictly sequentially. Because this method synchronizes on
+ * the persistence manager instance there is no need to synchronize on the
+ * shared statement. If the method would not be sychronized the shared
+ * statements would have to be synchronized.
+ */
+ 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(state.getId());
+ PreparedStatement stmt = (update) ? nodeStateUpdate : nodeStateInsert;
+
+ 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
+
+ stmt.setBytes(1, out.toByteArray());
+ stmt.setString(2, state.getNodeId().toString());
+ stmt.executeUpdate();
+
+ // there's no need to close a ByteArrayOutputStream
+ //out.close();
+ } catch (Exception e) {
+ String msg = "failed to write node state: " + state.getNodeId();
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * This method uses shared <code>PreparedStatement</code>s which must
+ * be executed strictly sequentially. Because this method synchronizes on
+ * the persistence manager instance there is no need to synchronize on the
+ * shared statement. If the method would not be sychronized the shared
+ * statements would have to be synchronized.
+ */
+ 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(state.getId());
+ PreparedStatement stmt = (update) ? propertyStateUpdate : propertyStateInsert;
+
+ 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
+
+ stmt.setBytes(1, out.toByteArray());
+ stmt.setString(2, state.getPropertyId().toString());
+ stmt.executeUpdate();
+
+ // there's no need to close a ByteArrayOutputStream
+ //out.close();
+ } catch (Exception e) {
+ String msg = "failed to write property state: " + state.getPropertyId();
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void destroy(NodeState state)
+ throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeStateDelete;
+ try {
+ stmt.setString(1, state.getNodeId().toString());
+ stmt.executeUpdate();
+ } catch (Exception e) {
+ String msg = "failed to delete node state: " + state.getNodeId();
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void destroy(PropertyState state)
+ throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ // make sure binary values (BLOBs) are properly removed
+ InternalValue[] values = state.getValues();
+ if (values != null) {
+ for (int i = 0; i < values.length; i++) {
+ InternalValue val = values[i];
+ if (val != null) {
+ if (val.getType() == PropertyType.BINARY) {
+ BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
+ // delete internal resource representation of BLOB value
+ blobVal.delete(true);
+ // also remove from BLOBStore
+ String blobId = blobStore.createId(state.getPropertyId(), i);
+ try {
+ blobStore.remove(blobId);
+ } catch (Exception e) {
+ log.warn("failed to remove from BLOBStore: " + blobId, e);
+ }
+ }
+ }
+ }
+ }
+
+ PreparedStatement stmt = propertyStateDelete;
+ try {
+ stmt.setString(1, state.getPropertyId().toString());
+ stmt.executeUpdate();
+ } catch (Exception e) {
+ String msg = "failed to delete property state: " + state.getPropertyId();
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NodeReferences load(NodeReferencesId targetId)
+ throws NoSuchItemStateException, ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeReferenceSelect;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ InputStream in = null;
+ try {
+ stmt.setString(1, targetId.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+ if (!rs.next()) {
+ throw new NoSuchItemStateException(targetId.toString());
+ }
+
+ in = rs.getBinaryStream(1);
+ NodeReferences refs = new NodeReferences(targetId);
+ Serializer.deserialize(refs, in);
+
+ return refs;
+ } catch (Exception e) {
+ if (e instanceof NoSuchItemStateException) {
+ throw (NoSuchItemStateException) e;
+ }
+ String msg = "failed to read node references: " + targetId;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeStream(in);
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * This method uses shared <code>PreparedStatement</code>s which must
+ * be executed strictly sequentially. Because this method synchronizes on
+ * the persistence manager instance there is no need to synchronize on the
+ * shared statement. If the method would not be sychronized the shared
+ * statements would have to be synchronized.
+ */
+ 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;
+
+ 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
+
+ stmt.setBytes(1, out.toByteArray());
+ 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);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void destroy(NodeReferences refs)
+ throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeReferenceDelete;
+ try {
+ stmt.setString(1, refs.getId().toString());
+ stmt.executeUpdate();
+ } catch (Exception e) {
+ String msg = "failed to delete node references: " + refs.getId();
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean exists(NodeId id) throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeStateSelectExist;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ try {
+ stmt.setString(1, id.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+
+ // a node state exists if the result has at least one entry
+ return rs.next();
+ } catch (Exception e) {
+ String msg = "failed to check existence of node state: " + id;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean exists(PropertyId id) throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = propertyStateSelectExist;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ try {
+ stmt.setString(1, id.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+
+ // a property state exists if the result has at least one entry
+ return rs.next();
+ } catch (Exception e) {
+ String msg = "failed to check existence of property state: " + id;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean exists(NodeReferencesId targetId) throws ItemStateException {
+ if (!initialized) {
+ throw new IllegalStateException("not initialized");
+ }
+
+ PreparedStatement stmt = nodeReferenceSelectExist;
+ synchronized (stmt) {
+ ResultSet rs = null;
+ try {
+ stmt.setString(1, targetId.toString());
+ stmt.execute();
+ rs = stmt.getResultSet();
+
+ // a reference exists if the result has at least one entry
+ return rs.next();
+ } catch (Exception e) {
+ String msg = "failed to check existence of node references: "
+ + targetId;
+ log.error(msg, e);
+ throw new ItemStateException(msg, e);
+ } finally {
+ closeResultSet(rs);
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ //----------------------------------< misc. helper methods & overridables >
+
+ /**
+ * Initializes the database connection used by this file system.
+ * <p>
+ * Subclasses should normally override the {@link #getConnection()}
+ * method instead of this one. The default implementation calls
+ * {@link #getConnection()} to get the database connection and disables
+ * the autocommit feature.
+ *
+ * @throws Exception if an error occurs
+ */
+ protected void initConnection() throws Exception {
+ con = getConnection();
+ con.setAutoCommit(false);
+ }
+
+ /**
+ * Abstract factory method for creating a new database connection. This
+ * method is called by {@link #init(PMContext)} when the persistence
+ * manager is started. The returned connection should come with the default
+ * JDBC settings, as the {@link #init(PMContext)} method will explicitly
+ * set the <code>autoCommit</code> and other properties as needed.
+ * <p>
+ * Note that the returned database connection is kept during the entire
+ * lifetime of the persistence manager, after which it is closed by
+ * {@link #close()} using the {@link #closeConnection(Connection)} method.
+ *
+ * @return new connection
+ * @throws Exception if an error occurs
+ */
+ protected Connection getConnection() throws Exception {
+ throw new UnsupportedOperationException("Override in a subclass!");
+ }
+
+ /**
+ * Closes the given database connection. This method is called by
+ * {@link #close()} to close the connection acquired using
+ * {@link #getConnection()} when the persistence manager was started.
+ * <p>
+ * The default implementation just calls the {@link Connection#close()}
+ * method of the given connection, but subclasses can override this
+ * method to provide more extensive database and connection cleanup.
+ *
+ * @param connection database connection
+ * @throws Exception if an error occurs
+ */
+ protected void closeConnection(Connection connection) throws Exception {
+ connection.close();
+ }
+
+ /**
+ * Resets the given <code>PreparedStatement</code> by clearing the parameters
+ * and warnings contained.
+ * <p/>
+ * NOTE: This method MUST be called in a synchronized context as neither
+ * this method nor the <code>PreparedStatement</code> instance on which it
+ * operates are thread safe.
+ *
+ * @param stmt The <code>PreparedStatement</code> to reset. If
+ * <code>null</code> this method does nothing.
+ */
+ protected void resetStatement(PreparedStatement stmt) {
+ if (stmt != null) {
+ try {
+ stmt.clearParameters();
+ stmt.clearWarnings();
+ } catch (SQLException se) {
+ logException("failed resetting PreparedStatement", se);
+ }
+ }
+ }
+
+ protected void closeResultSet(ResultSet rs) {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException se) {
+ logException("failed closing ResultSet", se);
+ }
+ }
+ }
+
+ protected void closeStream(InputStream in) {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
+ protected void closeStatement(Statement stmt) {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException se) {
+ logException("failed closing Statement", se);
+ }
+ }
+ }
+
+ protected void logException(String message, SQLException se) {
+ if (message != null) {
+ log.error(message);
+ }
+ log.error(" reason: " + se.getMessage());
+ log.error("state/code: " + se.getSQLState() + "/" + se.getErrorCode());
+ log.debug(" dump:", se);
+ }
+
+ /**
+ * Makes sure that <code>schemaObjectPrefix</code> does only consist of
+ * characters that are allowed in names on the target database. Illegal
+ * characters will be escaped as necessary.
+ *
+ * @throws Exception if an error occurs
+ */
+ protected void prepareSchemaObjectPrefix() throws Exception {
+ DatabaseMetaData metaData = con.getMetaData();
+ String legalChars = metaData.getExtraNameCharacters();
+ legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_";
+
+ String prefix = schemaObjectPrefix.toUpperCase();
+ StringBuffer escaped = new StringBuffer();
+ for (int i = 0; i < prefix.length(); i++) {
+ char c = prefix.charAt(i);
+ if (legalChars.indexOf(c) == -1) {
+ escaped.append("_x");
+ String hex = Integer.toHexString(c);
+ escaped.append("0000".toCharArray(), 0, 4 - hex.length());
+ escaped.append(hex);
+ escaped.append("_");
+ } else {
+ escaped.append(c);
+ }
+ }
+ schemaObjectPrefix = escaped.toString();
+ }
+
+ /**
+ * Checks if the required schema objects exist and creates them if they
+ * don't exist yet.
+ *
+ * @throws Exception if an error occurs
+ */
+ protected void checkSchema() throws Exception {
+ DatabaseMetaData metaData = con.getMetaData();
+ String tableName = schemaObjectPrefix + "NODE";
+ if (metaData.storesLowerCaseIdentifiers()) {
+ tableName = tableName.toLowerCase();
+ } else if (metaData.storesUpperCaseIdentifiers()) {
+ tableName = tableName.toUpperCase();
+ }
+
+ ResultSet rs = metaData.getTables(null, null, tableName, null);
+ boolean schemaExists;
+ try {
+ schemaExists = rs.next();
+ } finally {
+ rs.close();
+ }
+
+ if (!schemaExists) {
+ // read ddl from resources
+ InputStream in = getClass().getResourceAsStream(schema + ".ddl");
+ if (in == null) {
+ String msg = "Configuration error: unknown schema '" + schema + "'";
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ Statement stmt = con.createStatement();
+ try {
+ String sql = reader.readLine();
+ while (sql != null) {
+ // Skip comments and empty lines
+ if (!sql.startsWith("#") && sql.length() > 0) {
+ // replace prefix variable
+ sql = Text.replace(sql, SCHEMA_OBJECT_PREFIX_VARIABLE, schemaObjectPrefix);
+ // execute sql stmt
+ stmt.executeUpdate(sql);
+ }
+ // read next sql stmt
+ sql = reader.readLine();
+ }
+ // commit the changes
+ con.commit();
+ } finally {
+ closeStream(in);
+ closeStatement(stmt);
+ }
+ }
+ }
+
+ //--------------------------------------------------------< inner classes >
+ class DbBLOBStore implements BLOBStore {
+ /**
+ * {@inheritDoc}
+ */
+ public String createId(PropertyId id, int index) {
+ // the blobId is a simple string concatenation of id plus index
+ StringBuffer sb = new StringBuffer();
+ sb.append(id.toString());
+ sb.append('[');
+ sb.append(index);
+ sb.append(']');
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream get(String blobId) throws Exception {
+ PreparedStatement stmt = blobSelect;
+ synchronized (stmt) {
+ try {
+ stmt.setString(1, blobId);
+ stmt.execute();
+ final ResultSet rs = stmt.getResultSet();
+ if (!rs.next()) {
+ closeResultSet(rs);
+ throw new Exception("no such BLOB: " + blobId);
+ }
+ InputStream in = rs.getBinaryStream(1);
+ if (in == null) {
+ // some databases treat zero-length values as NULL;
+ // return empty InputStream in such a case
+ closeResultSet(rs);
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ /**
+ * return an InputStream wrapper in order to
+ * close the ResultSet when the stream is closed
+ */
+ return new FilterInputStream(in) {
+ public void close() throws IOException {
+ in.close();
+ // now it's safe to close ResultSet
+ closeResultSet(rs);
+ }
+ };
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void put(String blobId, InputStream in, long size)
+ throws Exception {
+ PreparedStatement stmt = blobSelectExist;
+ 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;
+ stmt.setBinaryStream(1, in, (int) size);
+ stmt.setString(2, blobId);
+ stmt.executeUpdate();
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized boolean remove(String blobId) throws Exception {
+ PreparedStatement stmt = blobDelete;
+ try {
+ stmt.setString(1, blobId);
+ return stmt.executeUpdate() == 1;
+ } finally {
+ resetStatement(stmt);
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url rev
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java?view=auto&rev=467925
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java Thu Oct 26 02:11:18 2006
@@ -0,0 +1,114 @@
+/*
+ * 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.persistence.db;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.persistence.db.DatabasePersistenceManager;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * <code>DerbyPersistenceManager</code> is a JDBC-based
+ * <code>PersistenceManager</code> for Jackrabbit that persists
+ * <code>ItemState</code> and <code>NodeReferences</code> objects in an
+ * embedded Derby 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>url</code>: the database url of the form
+ * <code>"jdbc:derby:[db];[attributes]"</code></li>
+ * <li><code>schemaObjectPrefix</code>: prefix to be prepended to schema objects</li>
+ * <li><code>driver</code>: the FQN name of the JDBC driver class
+ * (default: <code>"org.apache.derby.jdbc.EmbeddedDriver"</code>)</li>
+ * <li><code>schema</code>: type of schema to be used
+ * (default: <code>"derby"</code>)</li>
+ * <li><code>user</code>: the database user (default: <code>""</code>)</li>
+ * <li><code>password</code>: the user's password (default: <code>""</code>)</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>
+ * <PersistenceManager class="org.apache.jackrabbit.core.persistence.db.DerbyPersistenceManager">
+ * <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
+ * <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+ * <param name="externalBLOBs" value="false"/>
+ * </PersistenceManager>
+ * </pre>
+ */
+public class DerbyPersistenceManager extends SimpleDbPersistenceManager {
+
+ /**
+ * Logger instance
+ */
+ private static Logger log = LoggerFactory.getLogger(DerbyPersistenceManager.class);
+
+ /**
+ * Creates a new <code>SimpleDbPersistenceManager</code> instance.
+ */
+ public DerbyPersistenceManager() {
+ // preset some attributes to reasonable defaults
+ schema = "derby";
+ driver = "org.apache.derby.jdbc.EmbeddedDriver";
+ schemaObjectPrefix = "";
+ user = "";
+ password = "";
+ }
+
+ //------------------------------------------< DatabasePersistenceManager >
+
+ /**
+ * Closes the given connection by shutting down the embedded Derby
+ * database.
+ *
+ * @param connection database connection
+ * @throws SQLException if an error occurs
+ * @see DatabasePersistenceManager#closeConnection(Connection)
+ */
+ protected void closeConnection(Connection connection) throws SQLException {
+ // prepare connection url for issuing shutdown command
+ String url = connection.getMetaData().getURL();
+ int pos = url.lastIndexOf(';');
+ if (pos != -1) {
+ // strip any attributes from connection url
+ url = url.substring(0, pos);
+ }
+ url += ";shutdown=true";
+
+ // we have to reset the connection to 'autoCommit=true' before closing it;
+ // otherwise Derby would mysteriously complain about some pending uncommitted
+ // changes which can't possibly be true.
+ // @todo further investigate
+ connection.setAutoCommit(true);
+
+ // now it's safe to shutdown the embedded Derby database
+ try {
+ DriverManager.getConnection(url);
+ } catch (SQLException e) {
+ // a shutdown command always raises a SQLException
+ log.info(e.getMessage());
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/persistence/db/DerbyPersistenceManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url rev