You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2009/12/04 18:25:03 UTC
svn commit: r887279 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
ItemImpl.java SessionImpl.java state/SessionItemStateManager.java
Author: stefan
Date: Fri Dec 4 17:24:44 2009
New Revision: 887279
URL: http://svn.apache.org/viewvc?rev=887279&view=rev
Log:
JCR-2425: Session.save() and Session.refresh(boolean) rely on accessibility of the root node
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=887279&r1=887278&r2=887279&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Fri Dec 4 17:24:44 2009
@@ -979,7 +979,7 @@
*/
Collection<ItemState> removed = getRemovedStates();
- // All affected item states. They keys are used to look up whether
+ // All affected item states. The keys are used to look up whether
// an item is affected, and the values are iterated through below
Map<ItemId, ItemState> affected =
new HashMap<ItemId, ItemState>(dirty.size() + removed.size());
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=887279&r1=887278&r2=887279&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Fri Dec 4 17:24:44 2009
@@ -914,7 +914,13 @@
// check sanity of this session
sanityCheck();
- getItemManager().getRootNode().save();
+ // /JCR-2425: check whether session is allowed to read root node
+ if (hasPermission("/", ACTION_READ)) {
+ getItemManager().getRootNode().save();
+ } else {
+ NodeId id = getItemStateManager().getIdOfRootTransientNodeState();
+ getItemManager().getItem(id).save();
+ }
}
/**
@@ -936,11 +942,12 @@
}
if (!keepChanges) {
- // optimization
itemStateMgr.disposeAllTransientItemStates();
- return;
+ } else {
+ /** todo FIXME should reset Item#status field to STATUS_NORMAL
+ * of all non-transient instances; maybe also
+ * have to reset stale ItemState instances */
}
- getItemManager().getRootNode().refresh(keepChanges);
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=887279&r1=887278&r2=887279&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java Fri Dec 4 17:24:44 2009
@@ -22,12 +22,12 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.LinkedList;
import javax.jcr.InvalidItemStateException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.ReferentialIntegrityException;
import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
import org.apache.commons.collections.iterators.IteratorChain;
import org.apache.jackrabbit.core.CachingHierarchyManager;
@@ -38,10 +38,12 @@
import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
-import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.QNodeDefinition;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PathFactory;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -391,7 +393,7 @@
* Returns an iterator over those transient item state instances that are
* direct or indirect descendants of the item state with the given
* <code>parentId</code>. The transient item state instance with the given
- * <code>parentId</code> itself (if there is such) not be included.
+ * <code>parentId</code> itself (if there is such) will not be included.
* <p/>
* The instances are returned in depth-first tree traversal order.
*
@@ -417,9 +419,7 @@
List[] la = new List[10];
try {
HierarchyManager atticAware = getAtticAwareHierarchyMgr();
- Iterator iter = transientStore.values().iterator();
- while (iter.hasNext()) {
- ItemState state = (ItemState) iter.next();
+ for (ItemState state : transientStore.values()) {
// determine relative depth: > 0 means it's a descendant
int depth;
try {
@@ -562,6 +562,104 @@
}
/**
+ * Returns the id of the root of the minimal subtree including all
+ * transient states.
+ *
+ * @return id of nearest common ancestor of all transient states or null
+ * if there's no transient state.
+ * @throws RepositoryException if an error occurs
+ */
+ public NodeId getIdOfRootTransientNodeState() throws RepositoryException {
+ if (transientStore.isEmpty()) {
+ return null;
+ }
+
+ // short cut
+ if (transientStore.contains(hierMgr.getRootNodeId())) {
+ return hierMgr.getRootNodeId();
+ }
+
+ // the nearest common ancestor of all transient states
+ // must be either
+ // a) a node state with STATUS_EXISTING_MODIFIED, or
+ // b) the parent node of a property state with STATUS_EXISTING_MODIFIED
+
+ // collect all candidates based on above criteria
+ Collection<NodeId> candidateIds = new LinkedList<NodeId>();
+ try {
+ HierarchyManager hierMgr = getHierarchyMgr();
+ for (ItemState state : transientStore.values()) {
+ if (state.getStatus() == ItemState.STATUS_EXISTING_MODIFIED) {
+ NodeId nodeId;
+ if (state.isNode()) {
+ nodeId = (NodeId) state.getId();
+ } else {
+ nodeId = state.getParentId();
+ }
+ // remove any descendant candidates
+ boolean skip = false;
+ for (NodeId id : candidateIds) {
+ if (nodeId.equals(id) || hierMgr.isAncestor(id, nodeId)) {
+ // already a candidate or a descendant thereof
+ // => skip
+ skip = true;
+ break;
+ }
+ if (hierMgr.isAncestor(nodeId, id)) {
+ // candidate is a descendant => remove
+ candidateIds.remove(id);
+ }
+ }
+ if (!skip) {
+ // add to candidates
+ candidateIds.add(nodeId);
+ }
+ }
+ }
+
+ if (candidateIds.size() == 1) {
+ return candidateIds.iterator().next();
+ }
+
+ // pick (any) candidate with shortest path to start with
+ NodeId candidateId = null;
+ for (NodeId id : candidateIds) {
+ if (candidateId == null) {
+ candidateId = id;
+ } else {
+ if (hierMgr.getDepth(id) < hierMgr.getDepth(candidateId)) {
+ candidateId = id;
+ }
+ }
+ }
+
+ // starting with this candidate closest to root, find first parent
+ // which is an ancestor of all candidates
+ NodeState state = (NodeState) getItemState(candidateId);
+ NodeId parentId = state.getParentId();
+ boolean continueWithParent = false;
+ while (parentId != null) {
+ for (NodeId id : candidateIds) {
+ if (hierMgr.getRelativeDepth(parentId, id) == -1) {
+ continueWithParent = true;
+ break;
+ }
+ }
+ if (continueWithParent) {
+ state = (NodeState) getItemState(candidateId);
+ parentId = state.getParentId();
+ continueWithParent = false;
+ } else {
+ break;
+ }
+ }
+ return parentId;
+ } catch (ItemStateException e) {
+ throw new RepositoryException("failed to determine common root of transient changes", e);
+ }
+ }
+
+ /**
* Return a flag indicating whether the specified item is in the transient
* item state manager's attic space.
*