You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2013/07/08 15:29:54 UTC
svn commit: r1500715 -
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java
Author: mduerig
Date: Mon Jul 8 13:29:53 2013
New Revision: 1500715
URL: http://svn.apache.org/r1500715
Log:
OAK-144 Implement observation
Javadoc
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java?rev=1500715&r1=1500714&r2=1500715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/SecurableNodeStateDiff.java Mon Jul 8 13:29:53 2013
@@ -28,45 +28,110 @@ import org.apache.jackrabbit.oak.spi.sta
/**
* Base class for {@code NodeStateDiff} implementations that can be secured.
- * That is its call back methods are only called when its receiver has sufficient
- * rights to access respective items.
+ * That is, its call back methods are only called when its receiver has sufficient
+ * rights to access the respective items.
+ * <p>
+ * Implementors must implement the {@link #create(SecurableNodeStateDiff, String, NodeState, NodeState)}
+ * factory method for creating {@code SecurableNodeStateDiff} instances for child nodes.
+ * Further implementors should override {@link #canRead(PropertyState, PropertyState)} and
+ * {@link #canRead(String, NodeState, NodeState)} and determine whether the passed states are
+ * accessible and the respective callbacks should thus be invoked. Finally implementors should override,
+ * {@link #secureBefore(String, NodeState)}, and {@link #secureAfter(String, NodeState)}} wrapping the
+ * passed node state into a node state that restricts access to accessible child nodes and properties.
*/
public abstract class SecurableNodeStateDiff implements NodeStateDiff {
+
+ /**
+ * Parent diff
+ */
private final SecurableNodeStateDiff parent;
+ /**
+ * Unsecured diff this secured diff delegates to after it has determined
+ * that the items pertaining to a call back are accessible.
+ */
private RecursingNodeStateDiff diff;
+
+ /**
+ * Deferred {@link #childNodeChanged(String, NodeState, NodeState)} calls.
+ * Such calls are deferred until an accessible change in the respective sub tree
+ * is detected, as otherwise we might leak information restricted by access control
+ * to the call back.
+ */
private Deferred deferred = Deferred.EMPTY;
private SecurableNodeStateDiff(SecurableNodeStateDiff parent, RecursingNodeStateDiff diff) {
- this.diff = diff;
this.parent = parent;
+ this.diff = diff;
}
+ /**
+ * Create a new child instance
+ * @param parent parent of this instance
+ */
protected SecurableNodeStateDiff(SecurableNodeStateDiff parent) {
this(parent, RecursingNodeStateDiff.EMPTY);
}
+ /**
+ * Create a new instance wrapping a unsecured diff.
+ * @param diff unsecured diff
+ */
protected SecurableNodeStateDiff(RecursingNodeStateDiff diff) {
this(null, diff);
}
+ /**
+ * Factory method for creating {@code SecurableNodeStateDiff} instances for child nodes.
+ * @param parent parent diff
+ * @param name name of the child node
+ * @param before before state of the child node
+ * @param after after state of the child node
+ * @return {@code SecurableNodeStateDiff} for the child node {@code name}.
+ */
@CheckForNull
protected abstract SecurableNodeStateDiff create(SecurableNodeStateDiff parent,
String name, NodeState before, NodeState after);
+ /**
+ * Determine whether a property is accessible
+ * @param before before state of the property
+ * @param after after state of the property
+ * @return {@code true} if accessible, {@code false} otherwise.
+ */
protected boolean canRead(PropertyState before, PropertyState after) {
return true;
}
+ /**
+ * Determine whether a node is accessible
+ * @param before before state of the node
+ * @param after after state of the node
+ * @return {@code true} if accessible, {@code false} otherwise.
+ */
protected boolean canRead(String name, NodeState before, NodeState after) {
return true;
}
+ /**
+ * Secure the before state of a child node such that it only provides
+ * accessible child nodes and properties.
+ * @param name name of the child node
+ * @param nodeState before state of the child node
+ * @return secured before state
+ */
@Nonnull
protected NodeState secureBefore(String name, NodeState nodeState) {
return nodeState;
}
+ /**
+ * Secure the after state of a child node such that it only provides
+ * accessible child nodes and properties.
+ * @param name name of the child node
+ * @param nodeState after state of the child node
+ * @return secured after state
+ */
@Nonnull
protected NodeState secureAfter(String name, NodeState nodeState) {
return nodeState;
@@ -119,6 +184,7 @@ public abstract class SecurableNodeState
return true;
}
+ // Defer call back until accessible changes in the subtree are found
deferred = new Deferred() {
@Override
boolean call() {
@@ -148,6 +214,9 @@ public abstract class SecurableNodeState
//------------------------------------------------------------< Deferred >---
+ /**
+ * A deferred method call implementing call by need semantics.
+ */
private abstract static class Deferred {
public static final Deferred EMPTY = new Deferred() {
@Override