You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2006/01/11 15:24:32 UTC
svn commit: r368026 [1/3] - in /incubator/jackrabbit/trunk/jackrabbit/src:
main/java/org/apache/jackrabbit/core/
main/java/org/apache/jackrabbit/core/lock/
main/java/org/apache/jackrabbit/core/observation/
main/java/org/apache/jackrabbit/core/state/ ma...
Author: dpfister
Date: Wed Jan 11 06:22:57 2006
New Revision: 368026
URL: http://svn.apache.org/viewcvs?rev=368026&view=rev
Log:
Make versioning transactional
- Added specialized XAVersion and XAVersionHistory objects that refresh their internal state when needed
- Defined new observation interface in order to have VersionManagerImpl use standard event dispatching
instead of writing its own
- Added test cases verifying isolation of versioning operations in transactions
Added:
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersion.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionHistory.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersion.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionHistory.java (with props)
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java (with props)
Modified:
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/InternalXAResource.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/DelegatingObservationDispatcher.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalFreezeImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenVHImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionIteratorImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
incubator/jackrabbit/trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/XATest.java
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/InternalXAResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/InternalXAResource.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/InternalXAResource.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/InternalXAResource.java Wed Jan 11 06:22:57 2006
@@ -30,6 +30,13 @@
public void associate(TransactionContext tx);
/**
+ * Invoked before one of the {@link #prepare}, {@link #commit} or
+ * {@link #rollback} method is called.
+ * @param tx transaction context
+ */
+ public void beforeOperation(TransactionContext tx);
+
+ /**
* Prepare transaction. The transaction is identified by a transaction
* context.
* @param tx transaction context
@@ -52,4 +59,11 @@
* @param tx transaction context.
*/
public void rollback(TransactionContext tx) throws TransactionException;
+
+ /**
+ * Invoked after one of the {@link #prepare}, {@link #commit} or
+ * {@link #rollback} method has been called.
+ * @param tx transaction context
+ */
+ public void afterOperation(TransactionContext tx);
}
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java Wed Jan 11 06:22:57 2006
@@ -32,6 +32,8 @@
import org.apache.jackrabbit.core.version.InternalVersionHistory;
import org.apache.jackrabbit.core.version.VersionHistoryImpl;
import org.apache.jackrabbit.core.version.VersionImpl;
+import org.apache.jackrabbit.core.version.AbstractVersion;
+import org.apache.jackrabbit.core.version.AbstractVersionHistory;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.name.NoPrefixDeclaredException;
import org.apache.jackrabbit.name.Path;
@@ -81,7 +83,7 @@
private final NodeDefinition rootNodeDef;
private final NodeId rootNodeId;
- private final SessionImpl session;
+ protected final SessionImpl session;
private final ItemStateManager itemStateProvider;
private final HierarchyManager hierMgr;
@@ -100,9 +102,9 @@
* @param rootNodeDef the definition of the root node
* @param rootNodeUUID the UUID of the root node
*/
- ItemManager(ItemStateManager itemStateProvider, HierarchyManager hierMgr,
- SessionImpl session, NodeDefinition rootNodeDef,
- String rootNodeUUID) {
+ protected ItemManager(ItemStateManager itemStateProvider, HierarchyManager hierMgr,
+ SessionImpl session, NodeDefinition rootNodeDef,
+ String rootNodeUUID) {
this.itemStateProvider = itemStateProvider;
this.hierMgr = hierMgr;
this.session = session;
@@ -493,18 +495,17 @@
if (state.getNodeTypeName().equals(QName.NT_VERSION)) {
InternalVersion version =
session.getVersionManager().getVersion(state.getUUID());
- return new VersionImpl(this, session, id, state, def, listeners, version);
+ return createVersionInstance(id, state, def, listeners);
} else if (state.getNodeTypeName().equals(QName.NT_VERSIONHISTORY)) {
InternalVersionHistory history =
session.getVersionManager().getVersionHistory(state.getUUID());
- return new VersionHistoryImpl(this, session, id, state, def, listeners, history);
+ return createVersionHistoryInstance(id, state, def, listeners);
} else {
// create node object
return new NodeImpl(this, session, id, state, def, listeners);
}
-
}
NodeImpl createNodeInstance(NodeState state) throws RepositoryException {
@@ -531,6 +532,42 @@
PropertyDefinition def = getDefinition(state);
// 2. create instance
return createPropertyInstance(state, def);
+ }
+
+ /**
+ * Create a version instance.
+ * @param id node id
+ * @param state node state
+ * @param def node definition
+ * @param listeners listeners
+ * @return version instance
+ * @throws RepositoryException if an error occurs
+ */
+ protected AbstractVersion createVersionInstance(
+ NodeId id, NodeState state, NodeDefinition def,
+ ItemLifeCycleListener[] listeners) throws RepositoryException {
+
+ InternalVersion version =
+ session.getVersionManager().getVersion(id.getUUID());
+ return new VersionImpl(this, session, id, state, def, listeners, version);
+ }
+
+ /**
+ * Create a version history instance.
+ * @param id node id
+ * @param state node state
+ * @param def node definition
+ * @param listeners listeners
+ * @return version instance
+ * @throws RepositoryException if an error occurs
+ */
+ protected AbstractVersionHistory createVersionHistoryInstance(
+ NodeId id, NodeState state, NodeDefinition def,
+ ItemLifeCycleListener[] listeners) throws RepositoryException {
+
+ InternalVersionHistory history =
+ session.getVersionManager().getVersionHistory(id.getUUID());
+ return new VersionHistoryImpl(this, session, id, state, def, listeners, history);
}
//---------------------------------------------------< item cache methods >
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Wed Jan 11 06:22:57 2006
@@ -38,10 +38,8 @@
import org.apache.jackrabbit.core.version.InternalFreeze;
import org.apache.jackrabbit.core.version.InternalFrozenNode;
import org.apache.jackrabbit.core.version.InternalFrozenVersionHistory;
-import org.apache.jackrabbit.core.version.InternalVersion;
-import org.apache.jackrabbit.core.version.VersionHistoryImpl;
-import org.apache.jackrabbit.core.version.VersionImpl;
import org.apache.jackrabbit.core.version.VersionSelector;
+import org.apache.jackrabbit.core.version.AbstractVersion;
import org.apache.jackrabbit.core.lock.LockManager;
import org.apache.jackrabbit.name.IllegalNameException;
import org.apache.jackrabbit.name.MalformedPathException;
@@ -2869,7 +2867,7 @@
NodeImpl node;
try {
// check if versionable node exists
- InternalFrozenNode fn = ((VersionImpl) version).getFrozenNode();
+ InternalFrozenNode fn = ((AbstractVersion) version).getFrozenNode();
node = (NodeImpl) session.getNodeByUUID(fn.getFrozenUUID());
if (removeExisting) {
try {
@@ -2888,7 +2886,7 @@
}
} catch (ItemNotFoundException e) {
// not found, create new one
- node = addNode(relPath, ((VersionImpl) version).getFrozenNode());
+ node = addNode(relPath, ((AbstractVersion) version).getFrozenNode());
}
// recreate node from frozen state
@@ -3075,14 +3073,14 @@
return null;
}
// test versions
- InternalVersion v = ((VersionImpl) getBaseVersion()).getInternalVersion();
- InternalVersion vp = ((VersionImpl) srcNode.getBaseVersion()).getInternalVersion();
+ AbstractVersion v = (AbstractVersion) getBaseVersion();
+ AbstractVersion vp = (AbstractVersion) srcNode.getBaseVersion();
if (vp.isMoreRecent(v) && !isCheckedOut()) {
// I f V' is a successor (to any degree) of V, then the merge result for
// N is update. This case can be thought of as the case where N' is
// "newer" than N and therefore N should be updated to reflect N'.
return srcNode;
- } else if (v.equals(vp) || v.isMoreRecent(vp)) {
+ } else if (v.isSame(vp) || v.isMoreRecent(vp)) {
// If V' is a predecessor (to any degree) of V or if V and V' are
// identical (i.e., are actually the same version), then the merge
// result for N is leave. This case can be thought of as the case where
@@ -3488,7 +3486,7 @@
throws UnsupportedRepositoryOperationException, RepositoryException {
try {
- internalRestore(((VersionImpl) version).getInternalVersion(), vsel, removeExisting);
+ internalRestore((AbstractVersion) version, vsel, removeExisting);
} catch (RepositoryException e) {
// revert session
try {
@@ -3511,8 +3509,8 @@
* @param removeExisting
* @throws RepositoryException
*/
- protected InternalVersion[] internalRestore(InternalVersion version, VersionSelector vsel,
- boolean removeExisting)
+ protected Version[] internalRestore(AbstractVersion version, VersionSelector vsel,
+ boolean removeExisting)
throws RepositoryException {
// fail if root version
@@ -3531,7 +3529,8 @@
restored.add(version);
// 2. N's jcr:baseVersion property will be changed to point to V.
- internalSetProperty(QName.JCR_BASEVERSION, InternalValue.create(new UUID(version.getId())));
+ UUID uuid = new UUID(((NodeId) version.getId()).getUUID());
+ internalSetProperty(QName.JCR_BASEVERSION, InternalValue.create(uuid));
// 4. N's jcr:predecessor property is set to null
internalSetProperty(QName.JCR_PREDECESSORS, InternalValue.EMPTY_ARRAY, PropertyType.REFERENCE);
@@ -3542,7 +3541,7 @@
// 3. N's jcr:isCheckedOut property is set to false.
internalSetProperty(QName.JCR_ISCHECKEDOUT, InternalValue.create(false));
- return (InternalVersion[]) restored.toArray(new InternalVersion[restored.size()]);
+ return (Version[]) restored.toArray(new Version[restored.size()]);
}
/**
@@ -3654,7 +3653,7 @@
} else if (child instanceof InternalFrozenVersionHistory) {
InternalFrozenVersionHistory f = (InternalFrozenVersionHistory) child;
- VersionHistoryImpl history = (VersionHistoryImpl) session.getNodeByUUID(f.getVersionHistoryId());
+ VersionHistory history = (VersionHistory) session.getNodeByUUID(f.getVersionHistoryId());
String nodeId = history.getVersionableUUID();
// check if representing versionable already exists somewhere
@@ -3673,7 +3672,7 @@
}
} else {
// get desired version from version selector
- InternalVersion v = ((VersionImpl) vsel.select(history)).getInternalVersion();
+ AbstractVersion v = (AbstractVersion) vsel.select(history);
NodeImpl node = addNode(child.getName(), v.getFrozenNode());
node.internalRestore(v, vsel, removeExisting);
// add this version to set
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed Jan 11 06:22:57 2006
@@ -1397,7 +1397,7 @@
// create item state manager
try {
itemStateMgr =
- new SharedItemStateManager(persistMgr, rootNodeUUID, ntReg);
+ new SharedItemStateManager(persistMgr, rootNodeUUID, ntReg, true);
try {
itemStateMgr.addVirtualItemStateProvider(
vMgr.getVirtualItemStateProvider());
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/TransactionContext.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/TransactionContext.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/TransactionContext.java Wed Jan 11 06:22:57 2006
@@ -112,6 +112,7 @@
*/
public synchronized void prepare() throws XAException {
status = Status.STATUS_PREPARING;
+ beforeOperation();
TransactionException txe = null;
for (int i = 0; i < resources.length; i++) {
@@ -130,6 +131,7 @@
}
}
}
+ afterOperation();
status = Status.STATUS_PREPARED;
Thread rollbackThread = new Thread(this, "RollbackThread");
@@ -154,6 +156,7 @@
throw new XAException(XAException.XA_RBTIMEOUT);
}
status = Status.STATUS_COMMITTING;
+ beforeOperation();
TransactionException txe = null;
for (int i = 0; i < resources.length; i++) {
@@ -172,6 +175,7 @@
}
}
}
+ afterOperation();
status = Status.STATUS_COMMITTED;
if (txe != null) {
@@ -191,6 +195,7 @@
throw new XAException(XAException.XA_RBTIMEOUT);
}
status = Status.STATUS_ROLLING_BACK;
+ beforeOperation();
int errors = 0;
for (int i = 0; i < resources.length; i++) {
@@ -202,7 +207,9 @@
errors++;
}
}
+ afterOperation();
status = Status.STATUS_ROLLEDBACK;
+
if (errors != 0) {
throw new XAException(XAException.XA_RBOTHER);
}
@@ -231,6 +238,26 @@
}
log.warn("Transaction rolled back because timeout expired.");
}
+ }
+ }
+
+ /**
+ * Invoke all of the registered resources' {@link InternalXAResource#beforeOperation}
+ * methods.
+ */
+ private void beforeOperation() {
+ for (int i = 0; i < resources.length; i++) {
+ resources[i].beforeOperation(this);
+ }
+ }
+
+ /**
+ * Invoke all of the registered resources' {@link InternalXAResource#afterOperation}
+ * methods.
+ */
+ private void afterOperation() {
+ for (int i = 0; i < resources.length; i++) {
+ resources[i].afterOperation(this);
}
}
}
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Wed Jan 11 06:22:57 2006
@@ -20,13 +20,14 @@
import org.apache.jackrabbit.core.lock.LockManager;
import org.apache.jackrabbit.core.observation.ObservationManagerFactory;
import org.apache.jackrabbit.core.observation.ObservationManagerImpl;
+import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
+import org.apache.jackrabbit.core.observation.EventStateCollection;
import org.apache.jackrabbit.core.query.QueryManagerImpl;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
import org.apache.jackrabbit.core.state.LocalItemStateManager;
import org.apache.jackrabbit.core.version.GenericVersionSelector;
-import org.apache.jackrabbit.core.version.InternalVersion;
-import org.apache.jackrabbit.core.version.VersionImpl;
import org.apache.jackrabbit.core.version.VersionSelector;
+import org.apache.jackrabbit.core.version.AbstractVersion;
import org.apache.jackrabbit.core.xml.ImportHandler;
import org.apache.jackrabbit.core.xml.Importer;
import org.apache.jackrabbit.core.xml.WorkspaceImporter;
@@ -67,7 +68,7 @@
/**
* A <code>WorkspaceImpl</code> ...
*/
-public class WorkspaceImpl implements Workspace {
+public class WorkspaceImpl implements Workspace, EventStateCollectionFactory {
private static Logger log = Logger.getLogger(WorkspaceImpl.class);
@@ -123,9 +124,8 @@
* @param session The session
*/
protected WorkspaceImpl(WorkspaceConfig wspConfig,
- SharedItemStateManager stateMgr,
- RepositoryImpl rep,
- SessionImpl session) {
+ SharedItemStateManager stateMgr, RepositoryImpl rep,
+ SessionImpl session) {
this.wspConfig = wspConfig;
this.rep = rep;
this.stateMgr = createItemStateManager(stateMgr);
@@ -573,7 +573,7 @@
// add all versions to map of versions to restore
final HashMap toRestore = new HashMap();
for (int i = 0; i < versions.length; i++) {
- VersionImpl v = (VersionImpl) versions[i];
+ AbstractVersion v = (AbstractVersion) versions[i];
VersionHistory vh = v.getContainingHistory();
// check for collision
if (toRestore.containsKey(vh.getUUID())) {
@@ -606,16 +606,16 @@
// now restore all versions that have a node in the ws
int numRestored = 0;
while (toRestore.size() > 0) {
- InternalVersion[] restored = null;
+ Version[] restored = null;
Iterator iter = toRestore.values().iterator();
while (iter.hasNext()) {
- VersionImpl v = (VersionImpl) iter.next();
+ AbstractVersion v = (AbstractVersion) iter.next();
try {
NodeImpl node = (NodeImpl) session.getNodeByUUID(v.getFrozenNode().getFrozenUUID());
- restored = node.internalRestore(v.getInternalVersion(), vsel, removeExisting);
+ restored = node.internalRestore(v, vsel, removeExisting);
// remove restored versions from set
for (int i = 0; i < restored.length; i++) {
- toRestore.remove(restored[i].getVersionHistory().getId());
+ toRestore.remove(restored[i].getContainingHistory().getUUID());
}
numRestored += restored.length;
break;
@@ -728,6 +728,20 @@
*/
protected LocalItemStateManager createItemStateManager(SharedItemStateManager shared) {
return new LocalItemStateManager(shared, this);
+ }
+
+ //------------------------------------------< EventStateCollectionFactory >
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Implemented in this object and forwarded rather than {@link #obsMgr}
+ * since creation of the latter is lazy.
+ */
+ public EventStateCollection createEventStateCollection()
+ throws RepositoryException {
+
+ return ((ObservationManagerImpl) getObservationManager()).createEventStateCollection();
}
}
Added: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java?rev=368026&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java (added)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java Wed Jan 11 06:22:57 2006
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.version.InternalVersion;
+import org.apache.jackrabbit.core.version.AbstractVersion;
+import org.apache.jackrabbit.core.version.XAVersion;
+import org.apache.jackrabbit.core.version.AbstractVersionHistory;
+import org.apache.jackrabbit.core.version.InternalVersionHistory;
+import org.apache.jackrabbit.core.version.XAVersionHistory;
+import org.apache.jackrabbit.core.version.XAVersionManager;
+import org.apache.log4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.nodetype.NodeDefinition;
+
+/**
+ * Extended <code>ItemManager</code> that works in an XA environment.
+ */
+public class XAItemManager extends ItemManager {
+
+ /**
+ * Logger instance.
+ */
+ private static Logger log = Logger.getLogger(XAItemManager.class);
+
+ /**
+ * Create a new instance of this class.
+ * @param itemStateProvider the item state provider associated with
+ * the new instance
+ * @param session the session associated with the new instance
+ * @param rootNodeDef the definition of the root node
+ * @param rootNodeUUID the UUID of the root node
+ */
+ protected XAItemManager(ItemStateManager itemStateProvider, HierarchyManager hierMgr,
+ SessionImpl session, NodeDefinition rootNodeDef,
+ String rootNodeUUID) {
+
+ super(itemStateProvider, hierMgr, session, rootNodeDef, rootNodeUUID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected AbstractVersion createVersionInstance(
+ NodeId id, NodeState state, NodeDefinition def,
+ ItemLifeCycleListener[] listeners) throws RepositoryException {
+
+ InternalVersion version =
+ session.getVersionManager().getVersion(id.getUUID());
+ return new XAVersion(this, session, id, state, def, listeners, version);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected AbstractVersionHistory createVersionHistoryInstance(
+ NodeId id, NodeState state, NodeDefinition def,
+ ItemLifeCycleListener[] listeners) throws RepositoryException {
+
+ InternalVersionHistory history =
+ session.getVersionManager().getVersionHistory(id.getUUID());
+ return new XAVersionHistory(this, session, id, state, def, listeners, history);
+ }
+}
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAItemManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Wed Jan 11 06:22:57 2006
@@ -22,8 +22,11 @@
import org.apache.jackrabbit.core.lock.XALockManager;
import org.apache.jackrabbit.core.lock.LockManagerImpl;
import org.apache.jackrabbit.core.state.XAItemStateManager;
-import org.apache.jackrabbit.core.state.SessionItemStateManager;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
+import org.apache.jackrabbit.core.state.SessionItemStateManager;
+import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.VersionManagerImpl;
+import org.apache.jackrabbit.core.version.XAVersionManager;
import org.apache.log4j.Logger;
import javax.jcr.AccessDeniedException;
@@ -93,10 +96,7 @@
super(rep, loginContext, wspConfig);
- txResources = new InternalXAResource[] {
- (XAItemStateManager) wsp.getItemStateManager(),
- (XALockManager) getLockManager()
- };
+ init();
}
/**
@@ -115,10 +115,21 @@
super(rep, subject, wspConfig);
+ init();
+ }
+
+ /**
+ * Initialize this object.
+ */
+ private void init() throws RepositoryException {
+ XAItemStateManager stateMgr = (XAItemStateManager) wsp.getItemStateManager();
+ XALockManager lockMgr = (XALockManager) getLockManager();
+ XAVersionManager versionMgr = (XAVersionManager) getVersionManager();
+
txResources = new InternalXAResource[] {
- (XAItemStateManager) wsp.getItemStateManager(),
- (XALockManager) getLockManager()
+ stateMgr, lockMgr, versionMgr
};
+ stateMgr.setVirtualProvider(versionMgr);
}
/**
@@ -129,6 +140,25 @@
RepositoryImpl rep,
SessionImpl session) {
return new XAWorkspace(wspConfig, stateMgr, rep, session);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected VersionManager createVersionManager(RepositoryImpl rep)
+ throws RepositoryException {
+
+ VersionManagerImpl vMgr = (VersionManagerImpl) rep.getVersionManager();
+ return new XAVersionManager(vMgr, rep.getNodeTypeRegistry(), wsp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected ItemManager createItemManager(SessionItemStateManager itemStateMgr,
+ HierarchyManager hierMgr) {
+ return new XAItemManager(itemStateMgr, hierMgr, this,
+ ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
}
/**
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java Wed Jan 11 06:22:57 2006
@@ -215,6 +215,12 @@
/**
* {@inheritDoc}
*/
+ public void beforeOperation(TransactionContext tx) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void prepare(TransactionContext tx) throws TransactionException {
XAEnvironment xaEnv = (XAEnvironment) tx.getAttribute(XA_ENV_ATTRIBUTE_NAME);
if (xaEnv != null) {
@@ -244,6 +250,12 @@
if (xaEnv != null) {
xaEnv.rollback();
}
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterOperation(TransactionContext tx) {
}
/**
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/DelegatingObservationDispatcher.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/DelegatingObservationDispatcher.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/DelegatingObservationDispatcher.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/DelegatingObservationDispatcher.java Wed Jan 11 06:22:57 2006
@@ -17,8 +17,8 @@
package org.apache.jackrabbit.core.observation;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.state.ChangeLog;
-import javax.jcr.RepositoryException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -27,7 +27,7 @@
* This Class implements an observation dispatcher, that delegates events to
* a set of underlying dispatchers.
*/
-public class DelegatingObservationDispatcher {
+public class DelegatingObservationDispatcher extends EventDispatcher {
/**
* the set of dispatchers
@@ -53,15 +53,48 @@
}
/**
+ * Creates an <code>EventStateCollection</code> tied to the session
+ * given as argument.
+ *
+ * @param session event source
+ * @return new <code>EventStateCollection</code> instance
+ */
+ public EventStateCollection createEventStateCollection(SessionImpl session) {
+ return new EventStateCollection(this, session);
+ }
+
+ //------------------------------------------------------< EventDispatcher >
+
+ /**
+ * {@inheritDoc}
+ */
+ void prepareEvents(EventStateCollection events) {
+ // events will get prepared on dispatch
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void prepareDeleted(EventStateCollection events, ChangeLog changes) {
+ // events will get prepared on dispatch
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void dispatchEvents(EventStateCollection events) {
+ dispatch(events.getEvents(), events.getSession());
+ }
+
+ /**
* Dispatchers a list of events to all registered dispatchers. A new
* {@link EventStateCollection} is created for every dispatcher, fille with
* the given event list and then dispatched.
*
* @param eventList
* @param session
- * @throws RepositoryException
*/
- public void dispatch(List eventList, SessionImpl session) throws RepositoryException {
+ public void dispatch(List eventList, SessionImpl session) {
Iterator iter = dispatchers.iterator();
while (iter.hasNext()) {
ObservationManagerFactory fac = (ObservationManagerFactory) iter.next();
Added: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java?rev=368026&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java (added)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java Wed Jan 11 06:22:57 2006
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.observation;
+
+import org.apache.jackrabbit.core.state.ChangeLog;
+
+/**
+ * Defines an object that prepares and dispatches events. Made into an abstract
+ * class rather than an interface in order not to exhibit internal methods
+ * that should not be visible to everybody.
+ */
+abstract class EventDispatcher {
+
+ /**
+ * Gives this dispatcher the oportunity to prepare the events for
+ * dispatching.
+ *
+ * @param events the {@link EventState}s to prepare.
+ */
+ abstract void prepareEvents(EventStateCollection events);
+
+ /**
+ * Prepares changes that involve deleted item states.
+ *
+ * @param events the event state collection.
+ * @param changes the changes.
+ */
+ abstract void prepareDeleted(EventStateCollection events, ChangeLog changes);
+
+ /**
+ * Dispatches the {@link EventStateCollection events}.
+ *
+ * @param events the {@link EventState}s to dispatch.
+ */
+ abstract void dispatchEvents(EventStateCollection events);
+}
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventDispatcher.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java Wed Jan 11 06:22:57 2006
@@ -41,6 +41,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.Collections;
/**
* The <code>EventStateCollection</code> class implements how {@link EventState}
@@ -70,9 +71,9 @@
private final List events = new ArrayList();
/**
- * The <code>ObservationManagerFactory</code> that notifies the EventListeners.
+ * Event dispatcher.
*/
- private final ObservationManagerFactory dispatcher;
+ private final EventDispatcher dispatcher;
/**
* The session that created these events
@@ -82,9 +83,10 @@
/**
* Creates a new empty <code>EventStateCollection</code>.
*
+ * @param dispatcher event dispatcher
* @param session the session that created these events.
*/
- EventStateCollection(ObservationManagerFactory dispatcher,
+ EventStateCollection(EventDispatcher dispatcher,
SessionImpl session) {
this.dispatcher = dispatcher;
this.session = session;
@@ -420,6 +422,22 @@
*/
Iterator iterator() {
return events.iterator();
+ }
+
+ /**
+ * Return the list of events.
+ * @return list of events
+ */
+ List getEvents() {
+ return Collections.unmodifiableList(events);
+ }
+
+ /**
+ * Return the session who is the origin of this events.
+ * @return event source
+ */
+ SessionImpl getSession() {
+ return session;
}
/**
Added: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java?rev=368026&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java (added)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java Wed Jan 11 06:22:57 2006
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.observation;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Defines methods to create an {@link EventStateCollection}
+ */
+public interface EventStateCollectionFactory {
+
+ /**
+ * Creates an <code>EventStateCollection</code>.
+ *
+ * @return a new <code>EventStateCollection</code>
+ * @throws RepositoryException if creation fails for some reason
+ */
+ public EventStateCollection createEventStateCollection() throws RepositoryException;
+}
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollectionFactory.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java Wed Jan 11 06:22:57 2006
@@ -35,7 +35,8 @@
* creates new {@link EventStateCollection}s that can be dispatched
* to registered {@link javax.jcr.observation.EventListener}s.
*/
-public final class ObservationManagerFactory implements Runnable {
+public final class ObservationManagerFactory extends EventDispatcher
+ implements Runnable {
/**
* Logger instance for this class
@@ -171,10 +172,10 @@
}
/**
+ * {@inheritDoc}
+ * <p/>
* Gives this observation manager the oportunity to
* prepare the events for dispatching.
- *
- * @param events the {@link EventState}s to prepare.
*/
void prepareEvents(EventStateCollection events) {
Set consumers = new HashSet();
@@ -187,10 +188,7 @@
}
/**
- * Prepares changes that involve deleted item states.
- *
- * @param events the event state collection.
- * @param changes the changes.
+ * {@inheritDoc}
*/
void prepareDeleted(EventStateCollection events, ChangeLog changes) {
Set consumers = new HashSet();
@@ -203,10 +201,10 @@
}
/**
+ * {@inheritDoc}
+ * <p/>
* Dispatches the {@link EventStateCollection events} to all
* registered {@link javax.jcr.observation.EventListener}s.
- *
- * @param events the {@link EventState}s to dispatch.
*/
void dispatchEvents(EventStateCollection events) {
// notify synchronous listeners
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/observation/ObservationManagerImpl.java Wed Jan 11 06:22:57 2006
@@ -31,7 +31,7 @@
* instance. The class <code>SessionLocalObservationManager</code> implements
* this behaviour.
*/
-public class ObservationManagerImpl implements ObservationManager {
+public class ObservationManagerImpl implements ObservationManager, EventStateCollectionFactory {
/**
* The logger instance of this class
@@ -153,16 +153,6 @@
}
/**
- * Creates an <code>EventStateCollection</code> tied to the session
- * which is attached this <code>ObservationManager</code> instance.
- *
- * @return a new <code>EventStateCollection</code>.
- */
- public EventStateCollection createEventStateCollection() {
- return new EventStateCollection(obsMgrFactory, session);
- }
-
- /**
* Unregisters all EventListeners.
*/
public void dispose() {
@@ -179,4 +169,15 @@
}
+ //------------------------------------------< EventStateCollectionFactory >
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Creates an <code>EventStateCollection</code> tied to the session
+ * which is attached to this <code>ObservationManager</code> instance.
+ */
+ public EventStateCollection createEventStateCollection() {
+ return new EventStateCollection(obsMgrFactory, session);
+ }
}
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Wed Jan 11 06:22:57 2006
@@ -19,13 +19,11 @@
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.WorkspaceImpl;
-import org.apache.jackrabbit.core.observation.ObservationManagerImpl;
+import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
import org.apache.jackrabbit.name.QName;
import org.apache.log4j.Logger;
import javax.jcr.ReferentialIntegrityException;
-import javax.jcr.RepositoryException;
import java.util.Iterator;
/**
@@ -52,9 +50,9 @@
protected final SharedItemStateManager sharedStateMgr;
/**
- * Local WorkspaceImpl instance.
+ * Event state collection factory.
*/
- protected final WorkspaceImpl wspImpl;
+ protected final EventStateCollectionFactory factory;
/**
* Flag indicating whether this item state manager is in edit mode
@@ -68,20 +66,14 @@
/**
* Creates a new <code>LocalItemStateManager</code> instance.
- * todo LocalItemStateManager without a wspImpl will not generate observation events!
- *
* @param sharedStateMgr shared state manager
- * @param wspImpl the workspace instance where this item state manager
- * belongs to, or <code>null</code> if this item state manager is not
- * associated with a workspace. This is the case for the version item state
- * manager. Version item states are not associated with a specific workspace
- * instance.
+ * @param factory event state collection factory
*/
public LocalItemStateManager(SharedItemStateManager sharedStateMgr,
- WorkspaceImpl wspImpl) {
+ EventStateCollectionFactory factory) {
cache = new ItemStateReferenceCache();
this.sharedStateMgr = sharedStateMgr;
- this.wspImpl = wspImpl;
+ this.factory = factory;
}
/**
@@ -325,23 +317,9 @@
* @throws ItemStateException if an error occurs
*/
protected void update(ChangeLog changeLog)
- throws ReferentialIntegrityException, StaleItemStateException,
- ItemStateException {
-
- ObservationManagerImpl obsMgr = null;
-
- try {
- if (wspImpl != null) {
- obsMgr = (ObservationManagerImpl) wspImpl.getObservationManager();
- }
- } catch (RepositoryException e) {
- // should never get here
- String msg = "ObservationManager unavailable";
- log.error(msg);
- throw new ItemStateException(msg, e);
- }
+ throws ReferentialIntegrityException, StaleItemStateException, ItemStateException {
- sharedStateMgr.store(changeLog, obsMgr);
+ sharedStateMgr.update(changeLog, factory);
changeLog.persisted();
}
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Wed Jan 11 06:22:57 2006
@@ -27,7 +27,7 @@
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.nodetype.PropDef;
import org.apache.jackrabbit.core.observation.EventStateCollection;
-import org.apache.jackrabbit.core.observation.ObservationManagerImpl;
+import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
@@ -36,6 +36,7 @@
import javax.jcr.PropertyType;
import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import java.io.PrintStream;
@@ -130,6 +131,12 @@
private final NodeTypeRegistry ntReg;
/**
+ * Flag indicating whether this item state manager uses node references to
+ * verify integrity of its reference properties.
+ */
+ private final boolean usesReferences;
+
+ /**
* uuid of root node
*/
private final String rootNodeUUID;
@@ -164,11 +171,13 @@
*/
public SharedItemStateManager(PersistenceManager persistMgr,
String rootNodeUUID,
- NodeTypeRegistry ntReg)
+ NodeTypeRegistry ntReg,
+ boolean usesReferences)
throws ItemStateException {
cache = new ItemStateReferenceCache();
this.persistMgr = persistMgr;
this.ntReg = ntReg;
+ this.usesReferences = usesReferences;
this.rootNodeUUID = rootNodeUUID;
// create root node state if it doesn't yet exist
if (!hasNonVirtualItemState(new NodeId(rootNodeUUID))) {
@@ -378,69 +387,89 @@
}
/**
- * Store modifications registered in a <code>ChangeLog</code>. The items
- * contained in the <tt>ChangeLog</tt> are not states returned by this
- * item state manager but rather must be reconnected to items provided
- * by this state manager.<p/>
- * After successfully storing the states the observation manager is informed
- * about the changes, if an observation manager is passed to this method.<p/>
- * NOTE: This method is not synchronized, because all methods it invokes
- * on instance members (such as {@link PersistenceManager#store} are
- * considered to be thread-safe. Should this ever change, the
- * synchronization status has to be re-examined.
- *
- * @param local change log containing local items
- * @param obsMgr the observation manager to inform, or <code>null</code> if
- * no observation manager should be informed.
- * @throws ReferentialIntegrityException if a new or modified REFERENCE
- * property refers to a non-existent
- * target or if a removed node is still
- * being referenced
- * @throws StaleItemStateException if at least one of the affected item
- * states has become stale
- * @throws ItemStateException if another error occurs
+ * Object representing a single update operation.
*/
- public void store(ChangeLog local, ObservationManagerImpl obsMgr)
- throws ReferentialIntegrityException, StaleItemStateException,
- ItemStateException {
+ class Update {
+
+ /**
+ * Local change log.
+ */
+ private final ChangeLog local;
+
+ /**
+ * Event state collection factory.
+ */
+ private final EventStateCollectionFactory factory;
+
+ /**
+ * Virtual provider containing references to be left out when updating
+ * references.
+ */
+ private final VirtualItemStateProvider virtualProvider;
+
+ /**
+ * Shared change log.
+ */
+ private ChangeLog shared;
- ChangeLog shared = new ChangeLog();
+ /**
+ * Virtual node references.
+ */
+ private List[] virtualNodeReferences;
/**
- * array of lists of dirty virtual node references per virtual provider.
- * since NV-type references must be persisted via the respective VISP
- * and not by the SISM, they are filtered out below.
- *
- * todo: FIXME handling of virtual node references is erm... messy
- * VISP are eventually replaced by a more general 'mounting'
- * mechanism, probably on the API level and not on the item state
- * layer.
+ * Events to dispatch.
*/
- List[] virtualNodeReferences = new List[virtualProviders.length];
+ private EventStateCollection events;
- EventStateCollection events = null;
- if (obsMgr != null) {
- events = obsMgr.createEventStateCollection();
- events.prepareDeleted(local);
+ /**
+ * Create a new instance of this class.
+ */
+ public Update(ChangeLog local, EventStateCollectionFactory factory,
+ VirtualItemStateProvider virtualProvider) {
+ this.local = local;
+ this.factory = factory;
+ this.virtualProvider = virtualProvider;
}
- acquireWriteLock();
- boolean holdingWriteLock = true;
+ /**
+ * Begin update operation. Prepares everything upto the point where
+ * the persistence manager's <code>store</code> method may be invoked.
+ * If this method succeeds, a write lock will have been acquired on the
+ * item state manager and either {@link #end()} or {@link #cancel()} has
+ * to be called in order to release it.
+ */
+ public void begin() throws ItemStateException, ReferentialIntegrityException {
+ shared = new ChangeLog();
- try {
- /**
- * Update node references based on modifications in change log
- * (added/modified/removed REFERENCE properties)
- */
- updateReferences(local);
- /**
- * Check whether reference targets exist/were not removed
- */
- checkReferentialIntegrity(local);
+ virtualNodeReferences = new List[virtualProviders.length];
+
+ try {
+ events = factory.createEventStateCollection();
+ } catch (RepositoryException e) {
+ String msg = "Unable to create event state collection.";
+ log.error(msg);
+ throw new ItemStateException(msg, e);
+ }
+
+ acquireWriteLock();
boolean succeeded = false;
try {
+ if (usesReferences) {
+ /**
+ * Update node references based on modifications in change log
+ * (added/modified/removed REFERENCE properties)
+ */
+ updateReferences(local, virtualProvider);
+ }
+
+ /**
+ * Check whether reference targets exist/were not removed
+ */
+ checkReferentialIntegrity(local);
+
/**
* Reconnect all items contained in the change log to their
* respective shared item and add the shared items to a
@@ -502,13 +531,32 @@
}
/* create event states */
- if (events != null) {
- events.createEventStates(rootNodeUUID, local, this);
- }
+ events.createEventStates(rootNodeUUID, local,
+ SharedItemStateManager.this);
/* Push all changes from the local items to the shared items */
local.push();
+ succeeded = true;
+
+ } finally {
+ if (!succeeded) {
+ cancel();
+ }
+ }
+ }
+
+ /**
+ * End update operation. This will store the changes to the associated
+ * <code>PersistenceManager</code>. At the end of this operation, an
+ * eventual read or write lock on the item state manager will have
+ * been released.
+ * @throws ItemStateException if some error occurs
+ */
+ public void end() throws ItemStateException {
+ boolean succeeded = false;
+
+ try {
/* Store items in the underlying persistence manager */
long t0 = System.currentTimeMillis();
persistMgr.store(shared);
@@ -517,73 +565,121 @@
if (log.isDebugEnabled()) {
log.debug("persisting change log " + shared + " took " + (t1 - t0) + "ms");
}
-
} finally {
-
- /**
- * If some store operation was unsuccessful, we have to reload
- * the state of modified and deleted items from persistent
- * storage.
- */
if (!succeeded) {
- local.disconnect();
+ cancel();
+ }
+ }
- for (Iterator iter = shared.modifiedStates(); iter.hasNext();) {
- ItemState state = (ItemState) iter.next();
- try {
- state.copy(loadItemState(state.getId()));
- } catch (ItemStateException e) {
- state.discard();
- }
- }
- for (Iterator iter = shared.deletedStates(); iter.hasNext();) {
- ItemState state = (ItemState) iter.next();
- try {
- state.copy(loadItemState(state.getId()));
- } catch (ItemStateException e) {
- state.discard();
+ boolean holdingWriteLock = true;
+
+ try {
+ /* Let the shared item listeners know about the change */
+ shared.persisted();
+
+ /* notify virtual providers about node references */
+ for (int i = 0; i < virtualNodeReferences.length; i++) {
+ List virtualRefs = virtualNodeReferences[i];
+ if (virtualRefs != null) {
+ for (Iterator iter = virtualRefs.iterator(); iter.hasNext();) {
+ NodeReferences refs = (NodeReferences) iter.next();
+ virtualProviders[i].setNodeReferences(refs);
}
}
- for (Iterator iter = shared.addedStates(); iter.hasNext();) {
- ItemState state = (ItemState) iter.next();
- state.discard();
- }
}
- }
- /* Let the shared item listeners know about the change */
- shared.persisted();
+ // downgrade to read lock
+ acquireReadLock();
+ rwLock.writeLock().release();
+ holdingWriteLock = false;
- /* notify virtual providers about node references */
- for (int i = 0; i < virtualNodeReferences.length; i++) {
- List virtualRefs = virtualNodeReferences[i];
- if (virtualRefs != null) {
- for (Iterator iter = virtualRefs.iterator(); iter.hasNext();) {
- NodeReferences refs = (NodeReferences) iter.next();
- virtualProviders[i].setNodeReferences(refs);
- }
+ /* dispatch the events */
+ events.dispatch();
+
+ } finally {
+ if (holdingWriteLock) {
+ // exception occured before downgrading lock
+ rwLock.writeLock().release();
+ } else {
+ rwLock.readLock().release();
}
}
+ }
- // downgrade to read lock
- acquireReadLock();
- rwLock.writeLock().release();
- holdingWriteLock = false;
+ /**
+ * Cancel update operation. At the end of this operation, the write lock
+ * on the item state manager will have been released.
+ */
+ public void cancel() {
+ local.disconnect();
- /* dispatch the events */
- if (events != null) {
- events.dispatch();
+ for (Iterator iter = shared.modifiedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ try {
+ state.copy(loadItemState(state.getId()));
+ } catch (ItemStateException e) {
+ state.discard();
+ }
}
- } finally {
- if (holdingWriteLock) {
- // exception occured before downgrading lock
- rwLock.writeLock().release();
- } else {
- rwLock.readLock().release();
+ for (Iterator iter = shared.deletedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ try {
+ state.copy(loadItemState(state.getId()));
+ } catch (ItemStateException e) {
+ state.discard();
+ }
}
+ for (Iterator iter = shared.addedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ state.discard();
+ }
+ rwLock.writeLock().release();
}
}
+ /**
+ * Begin update operation. This will return an object that can itself be
+ * ended/cancelled.
+ */
+ public Update beginUpdate(ChangeLog local, EventStateCollectionFactory factory,
+ VirtualItemStateProvider virtualProvider)
+ throws ReferentialIntegrityException, StaleItemStateException,
+ ItemStateException {
+
+ Update update = new Update(local, factory, virtualProvider);
+ update.begin();
+ return update;
+ }
+
+ /**
+ * Store modifications registered in a <code>ChangeLog</code>. The items
+ * contained in the <tt>ChangeLog</tt> are not states returned by this
+ * item state manager but rather must be reconnected to items provided
+ * by this state manager.<p/>
+ * After successfully storing the states the observation manager is informed
+ * about the changes, if an observation manager is passed to this method.<p/>
+ * NOTE: This method is not synchronized, because all methods it invokes
+ * on instance members (such as {@link PersistenceManager#store} are
+ * considered to be thread-safe. Should this ever change, the
+ * synchronization status has to be re-examined.
+ *
+ * @param local change log containing local items
+ * @param factory event state collection factory
+ * @throws ReferentialIntegrityException if a new or modified REFERENCE
+ * property refers to a non-existent
+ * target or if a removed node is still
+ * being referenced
+ * @throws StaleItemStateException if at least one of the affected item
+ * states has become stale
+ * @throws ItemStateException if another error occurs
+ */
+ public void update(ChangeLog local, EventStateCollectionFactory factory)
+ throws ReferentialIntegrityException, StaleItemStateException,
+ ItemStateException {
+
+ beginUpdate(local, factory, null).end();
+ }
+
//-------------------------------------------------------< implementation >
/**
* Create a new node state instance
@@ -801,9 +897,13 @@
* anymore afterwards.
*
* @param changes change log
+ * @param virtualProvider virtual provider that may already contain a
+ * node references object
* @throws ItemStateException if an error occurs
*/
- protected void updateReferences(ChangeLog changes) throws ItemStateException {
+ protected void updateReferences(ChangeLog changes,
+ VirtualItemStateProvider virtualProvider)
+ throws ItemStateException {
// process added REFERENCE properties
for (Iterator iter = changes.addedStates(); iter.hasNext();) {
@@ -817,6 +917,10 @@
for (int i = 0; vals != null && i < vals.length; i++) {
String uuid = vals[i].toString();
NodeReferencesId refsId = new NodeReferencesId(uuid);
+ if (virtualProvider != null &&
+ virtualProvider.hasNodeReferences(refsId)) {
+ continue;
+ }
NodeReferences refs =
getOrCreateNodeReferences(refsId, changes);
// add reference
@@ -843,6 +947,10 @@
for (int i = 0; vals != null && i < vals.length; i++) {
String uuid = vals[i].toString();
NodeReferencesId refsId = new NodeReferencesId(uuid);
+ if (virtualProvider != null &&
+ virtualProvider.hasNodeReferences(refsId)) {
+ continue;
+ }
// either get node references from change log or load from
// persistence manager
NodeReferences refs = changes.get(refsId);
@@ -863,6 +971,10 @@
for (int i = 0; vals != null && i < vals.length; i++) {
String uuid = vals[i].toString();
NodeReferencesId refsId = new NodeReferencesId(uuid);
+ if (virtualProvider != null &&
+ virtualProvider.hasNodeReferences(refsId)) {
+ continue;
+ }
NodeReferences refs =
getOrCreateNodeReferences(refsId, changes);
// add reference
@@ -886,6 +998,10 @@
for (int i = 0; vals != null && i < vals.length; i++) {
String uuid = vals[i].toString();
NodeReferencesId refsId = new NodeReferencesId(uuid);
+ if (virtualProvider != null &&
+ virtualProvider.hasNodeReferences(refsId)) {
+ continue;
+ }
// either get node references from change log or
// load from persistence manager
NodeReferences refs = changes.get(refsId);
Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java?rev=368026&r1=368025&r2=368026&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java Wed Jan 11 06:22:57 2006
@@ -17,13 +17,19 @@
package org.apache.jackrabbit.core.state;
import org.apache.jackrabbit.core.ItemId;
-import org.apache.jackrabbit.core.WorkspaceImpl;
import org.apache.jackrabbit.core.TransactionException;
import org.apache.jackrabbit.core.TransactionContext;
import org.apache.jackrabbit.core.InternalXAResource;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
import org.apache.log4j.Logger;
import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.PropertyType;
+import java.util.Iterator;
/**
* Extension to <code>LocalItemStateManager</code> that remembers changes on
@@ -59,34 +65,54 @@
private transient ChangeLog txLog;
/**
+ * Current update operation.
+ */
+ private transient SharedItemStateManager.Update update;
+
+ /**
* Change log attribute name.
*/
private final String attributeName;
/**
+ * Optional virtual item state provider.
+ */
+ private VirtualItemStateProvider virtualProvider;
+
+ /**
* Creates a new instance of this class.
+ *
* @param sharedStateMgr shared state manager
- * @param wspImpl workspace
+ * @param factory event state collection factory
*/
public XAItemStateManager(SharedItemStateManager sharedStateMgr,
- WorkspaceImpl wspImpl) {
- this(sharedStateMgr, wspImpl, DEFAULT_ATTRIBUTE_NAME);
+ EventStateCollectionFactory factory) {
+ this(sharedStateMgr, factory, DEFAULT_ATTRIBUTE_NAME);
}
/**
* Creates a new instance of this class with a custom attribute name.
+ *
* @param sharedStateMgr shared state manager
- * @param wspImpl workspace
- * @param attributeName attribute name
+ * @param factory event state collection factory
+ * @param attributeName attribute name
*/
public XAItemStateManager(SharedItemStateManager sharedStateMgr,
- WorkspaceImpl wspImpl, String attributeName) {
- super(sharedStateMgr, wspImpl);
+ EventStateCollectionFactory factory,
+ String attributeName) {
+ super(sharedStateMgr, factory);
this.attributeName = attributeName;
}
/**
+ * Set optional virtual item state provider.
+ */
+ public void setVirtualProvider(VirtualItemStateProvider virtualProvider) {
+ this.virtualProvider = virtualProvider;
+ }
+
+ /**
* {@inheritDoc}
*/
public void associate(TransactionContext tx) {
@@ -104,12 +130,24 @@
/**
* {@inheritDoc}
*/
+ public void beforeOperation(TransactionContext tx) {
+ ChangeLog txLog = (ChangeLog) tx.getAttribute(attributeName);
+ if (txLog != null) {
+ ((CommitLog) commitLog.get()).setChanges(txLog);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void prepare(TransactionContext tx) throws TransactionException {
ChangeLog txLog = (ChangeLog) tx.getAttribute(attributeName);
if (txLog != null) {
try {
- ((CommitLog) commitLog.get()).setChanges(txLog);
- sharedStateMgr.checkReferentialIntegrity(txLog);
+ if (virtualProvider != null) {
+ updateVirtualReferences(txLog);
+ }
+ update = sharedStateMgr.beginUpdate(txLog, factory, virtualProvider);
} catch (ReferentialIntegrityException rie) {
log.error(rie);
txLog.undo(sharedStateMgr);
@@ -118,8 +156,6 @@
log.error(ise);
txLog.undo(sharedStateMgr);
throw new TransactionException("Unable to prepare transaction.", ise);
- } finally {
- ((CommitLog) commitLog.get()).setChanges(null);
}
}
}
@@ -131,18 +167,11 @@
ChangeLog txLog = (ChangeLog) tx.getAttribute(attributeName);
if (txLog != null) {
try {
- ((CommitLog) commitLog.get()).setChanges(txLog);
- super.update(txLog);
- } catch (ReferentialIntegrityException rie) {
- log.error(rie);
- txLog.undo(sharedStateMgr);
- throw new TransactionException("Unable to commit transaction.", rie);
+ update.end();
} catch (ItemStateException ise) {
log.error(ise);
txLog.undo(sharedStateMgr);
throw new TransactionException("Unable to commit transaction.", ise);
- } finally {
- ((CommitLog) commitLog.get()).setChanges(null);
}
txLog.reset();
}
@@ -154,16 +183,21 @@
public void rollback(TransactionContext tx) {
ChangeLog txLog = (ChangeLog) tx.getAttribute(attributeName);
if (txLog != null) {
- try {
- ((CommitLog) commitLog.get()).setChanges(txLog);
- txLog.undo(sharedStateMgr);
- } finally {
- ((CommitLog) commitLog.get()).setChanges(null);
+ if (update != null) {
+ update.cancel();
}
+ txLog.undo(sharedStateMgr);
}
}
/**
+ * {@inheritDoc}
+ */
+ public void afterOperation(TransactionContext tx) {
+ ((CommitLog) commitLog.get()).setChanges(null);
+ }
+
+ /**
* Returns the current change log. First tries thread-local change log,
* then instance-local change log. Returns <code>null</code> if no
* change log was found.
@@ -188,6 +222,9 @@
public ItemState getItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
+ if (virtualProvider != null && virtualProvider.hasItemState(id)) {
+ return virtualProvider.getItemState(id);
+ }
ChangeLog changeLog = getChangeLog();
if (changeLog != null) {
ItemState state = changeLog.get(id);
@@ -207,6 +244,9 @@
* class.
*/
public boolean hasItemState(ItemId id) {
+ if (virtualProvider != null && virtualProvider.hasItemState(id)) {
+ return true;
+ }
ChangeLog changeLog = getChangeLog();
if (changeLog != null) {
try {
@@ -232,6 +272,9 @@
public NodeReferences getNodeReferences(NodeReferencesId id)
throws NoSuchItemStateException, ItemStateException {
+ if (virtualProvider != null && virtualProvider.hasNodeReferences(id)) {
+ return virtualProvider.getNodeReferences(id);
+ }
ChangeLog changeLog = getChangeLog();
if (changeLog != null) {
NodeReferences refs = changeLog.get(id);
@@ -251,6 +294,9 @@
* the base class.
*/
public boolean hasNodeReferences(NodeReferencesId id) {
+ if (virtualProvider != null && virtualProvider.hasNodeReferences(id)) {
+ return true;
+ }
ChangeLog changeLog = getChangeLog();
if (changeLog != null) {
if (changeLog.get(id) != null) {
@@ -274,6 +320,111 @@
txLog.merge(changeLog);
} else {
super.update(changeLog);
+ }
+ }
+
+ //-------------------------------------------------------< implementation >
+
+ /**
+ * Determine all node references whose targets only exist in the view of
+ * this transaction and store the modified view back to the virtual provider.
+ * @param changes change log
+ * @throws ItemStateException if an error occurs
+ */
+ private void updateVirtualReferences(ChangeLog changes) throws ItemStateException {
+ for (Iterator iter = changes.addedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ if (!state.isNode()) {
+ PropertyState prop = (PropertyState) state;
+ if (prop.getType() == PropertyType.REFERENCE) {
+ InternalValue[] vals = prop.getValues();
+ for (int i = 0; vals != null && i < vals.length; i++) {
+ String uuid = vals[i].toString();
+ NodeReferencesId refsId = new NodeReferencesId(uuid);
+ addVirtualReference((PropertyId) prop.getId(), refsId);
+ }
+ }
+ }
+ }
+ for (Iterator iter = changes.modifiedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ if (!state.isNode()) {
+ PropertyState newProp = (PropertyState) state;
+ PropertyState oldProp =
+ (PropertyState) getItemState(state.getId());
+ if (oldProp.getType() == PropertyType.REFERENCE) {
+ InternalValue[] vals = oldProp.getValues();
+ for (int i = 0; vals != null && i < vals.length; i++) {
+ String uuid = vals[i].toString();
+ NodeReferencesId refsId = new NodeReferencesId(uuid);
+ removeVirtualReference((PropertyId) oldProp.getId(), refsId);
+ }
+ }
+ if (newProp.getType() == PropertyType.REFERENCE) {
+ InternalValue[] vals = newProp.getValues();
+ for (int i = 0; vals != null && i < vals.length; i++) {
+ String uuid = vals[i].toString();
+ NodeReferencesId refsId = new NodeReferencesId(uuid);
+ addVirtualReference((PropertyId) newProp.getId(), refsId);
+ }
+ }
+ }
+ }
+ for (Iterator iter = changes.deletedStates(); iter.hasNext();) {
+ ItemState state = (ItemState) iter.next();
+ if (!state.isNode()) {
+ PropertyState prop = (PropertyState) state;
+ if (prop.getType() == PropertyType.REFERENCE) {
+ InternalValue[] vals = prop.getValues();
+ for (int i = 0; vals != null && i < vals.length; i++) {
+ String uuid = vals[i].toString();
+ NodeReferencesId refsId = new NodeReferencesId(uuid);
+ removeVirtualReference((PropertyId) prop.getId(), refsId);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a virtual reference from some reference property to a virtual node.
+ * Ignored if <code>targetId</code> does not actually point to a virtual
+ * node.
+ * @param sourceId property id
+ * @param targetId node references id
+ */
+ private void addVirtualReference(PropertyId sourceId,
+ NodeReferencesId targetId)
+ throws NoSuchItemStateException, ItemStateException {
+
+ NodeReferences refs = virtualProvider.getNodeReferences(targetId);
+ if (refs == null && virtualProvider.hasItemState(new NodeId(targetId.getUUID()))) {
+ refs = new NodeReferences(targetId);
+ }
+ if (refs != null) {
+ refs.addReference(sourceId);
+ virtualProvider.setNodeReferences(refs);
+ }
+ }
+
+ /**
+ * Remove a virtual reference from some reference property to a virtual node.
+ * Ignored if <code>targetId</code> does not actually point to a virtual
+ * node.
+ * @param sourceId property id
+ * @param targetId node references id
+ */
+ private void removeVirtualReference(PropertyId sourceId,
+ NodeReferencesId targetId)
+ throws NoSuchItemStateException, ItemStateException {
+
+ NodeReferences refs = virtualProvider.getNodeReferences(targetId);
+ if (refs == null && virtualProvider.hasItemState(new NodeId(targetId.getUUID()))) {
+ refs = new NodeReferences(targetId);
+ }
+ if (refs != null) {
+ refs.removeReference(sourceId);
+ virtualProvider.setNodeReferences(refs);
}
}