Index: src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (revision 899132)
+++ src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (working copy)
@@ -572,6 +572,8 @@
checkReferentialIntegrity();
}
+ checkAddedChildNodes();
+
/**
* prepare the events. this needs to be after the referential
* integrity check, since another transaction could have modified
@@ -957,6 +959,40 @@
}
/**
+ * Verify the added child nodes of the added or modified states exist.
+ * If they don't exist, most likely the problem is that the same session
+ * is used concurrently.
+ */
+ private void checkAddedChildNodes() throws ItemStateException {
+ for (Iterator iter = local.addedStates(); iter.hasNext();) {
+ checkAddedChildNode((ItemState) iter.next());
+ }
+ for (Iterator iter = local.modifiedStates(); iter.hasNext();) {
+ checkAddedChildNode((ItemState) iter.next());
+ }
+ }
+
+ private void checkAddedChildNode(ItemState state) throws ItemStateException {
+ if (state.isNode()) {
+ NodeState node = (NodeState) state;
+
+ for (Iterator iter = node.getAddedChildNodeEntries().iterator();
+ iter.hasNext();) {
+ ChildNodeEntry cne =
+ (ChildNodeEntry) iter.next();
+ NodeId id = cne.getId();
+ if (local.get(id) == null) {
+ if (!cache.isCached(id) && !persistMgr.exists(id)) {
+ String msg = "Trying to add a non-existing child node: " + id;
+ log.debug(msg);
+ throw new ItemStateException(msg);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Verifies that
*
* - no referenceable nodes are deleted if they are still being referenced
Index: src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java (revision 899132)
+++ src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java (working copy)
@@ -364,6 +364,11 @@
NodeId parentId = n.getParentId();
// the parent of an added item is always modified or new
NodeState parent = (NodeState) changes.get(parentId);
+ if (parent == null) {
+ String msg = "Parent " + parentId + " must be changed as well.";
+ log.error(msg);
+ throw new ItemStateException(msg);
+ }
NodeTypeImpl nodeType = getNodeType(parent, session);
Set mixins = parent.getMixinTypeNames();
Path path = getPath(n.getNodeId(), hmgr);
@@ -377,6 +382,11 @@
} else {
// property created / set
NodeState n = (NodeState) changes.get(state.getParentId());
+ if (n == null) {
+ String msg = "Node " + state.getParentId() + " must be changed as well.";
+ log.error(msg);
+ throw new ItemStateException(msg);
+ }
NodeTypeImpl nodeType = getNodeType(n, session);
Set mixins = n.getMixinTypeNames();
Path path = getPath(state.getId(), hmgr);
@@ -474,7 +484,12 @@
} catch (Exception e) {
// also catch eventual runtime exceptions here
// should never happen actually
- String msg = "Item " + node.getNodeId() + " has unknown node type: " + node.getNodeTypeName();
+ String msg;
+ if (node == null) {
+ msg = "Node state is null";
+ } else {
+ msg = "Item " + node.getNodeId() + " has unknown node type: " + node.getNodeTypeName();
+ }
log.error(msg);
throw new ItemStateException(msg, e);
}
Index: src/main/java/org/apache/jackrabbit/core/ItemImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/ItemImpl.java (revision 899132)
+++ src/main/java/org/apache/jackrabbit/core/ItemImpl.java (working copy)
@@ -68,6 +68,7 @@
import javax.jcr.version.VersionException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -926,7 +927,16 @@
* build list of transient (i.e. new & modified) states that
* should be persisted
*/
- Collection dirty = getTransientStates();
+ Collection dirty;
+ try {
+ dirty = getTransientStates();
+ } catch (ConcurrentModificationException e) {
+ String msg = "Concurrent modification; session is closed";
+ log.error(msg, e);
+ session.logout();
+ throw e;
+ }
+
if (dirty.size() == 0) {
// no transient items, nothing to do here
return;