jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1502527 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/
Date Fri, 12 Jul 2013 12:20:38 GMT
Author: mduerig
Date: Fri Jul 12 12:20:37 2013
New Revision: 1502527

URL: http://svn.apache.org/r1502527
Log:
OAK-144 Implement observation
Base EventGeneratingNodeStateDiff on ImmutableTree instead of raw node states in order to
track hierarchy information

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFilter.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java?rev=1502527&r1=1502526&r2=1502527&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
Fri Jul 12 12:20:37 2013
@@ -21,7 +21,6 @@ package org.apache.jackrabbit.oak.plugin
 import static com.google.common.base.Objects.toStringHelper;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.jackrabbit.oak.plugins.observation.ObservationConstants.OAK_UNKNOWN;
-import static org.apache.jackrabbit.oak.spi.state.NodeStateUtils.getNode;
 
 import java.util.Queue;
 import java.util.Set;
@@ -31,16 +30,10 @@ import javax.annotation.Nonnull;
 
 import com.google.common.collect.Queues;
 import com.google.common.collect.Sets;
-import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.spi.commit.PostCommitHook;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.apache.jackrabbit.oak.spi.state.RecursingNodeStateDiff;
 import org.apache.jackrabbit.oak.util.TODO;
 
 /**
@@ -254,58 +247,19 @@ public class ChangeDispatcher {
         public abstract long getDate();
 
         /**
-         * Get the id of the node at the given path as it was before this change set.
-         * @param path  path to determine the id for
-         * @return  id for the item at {@code path} or {@code path} if the item doesn't exit.
+         * State before the change
+         * @return  before state
          */
-        @Nonnull
-        public String getBeforeId(String path) {
-            return getId(before, path);
+        public NodeState getBeforeState() {
+            return before;
         }
 
         /**
-         * Get the id of the node at the given path as it is after this change set.
-         * @param path  path to determine the id for
-         * @return  id for the item at {@code path} or {@code path} if the item doesn't exit.
+         * State after the change
+         * @return  after state
          */
-        @Nonnull
-        public String getAfterId(String path) {
-            return getId(after, path);
-        }
-
-        private static String getId(NodeState nodeState, String path) {
-            StringBuilder id = new StringBuilder();
-
-            id.append(getIdOrName(nodeState, ""));
-            for (String name : PathUtils.elements(path)) {
-                nodeState = nodeState.getChildNode(name);
-                id.append('/').append(getIdOrName(nodeState, name));
-            }
-
-            if (id.length() == 0) {
-                return "/";
-            } else {
-                return id.toString();
-            }
-        }
-
-        private static String getIdOrName(NodeState nodeState, String name) {
-            PropertyState uuid = nodeState.getProperty(JcrConstants.JCR_UUID);
-            if (uuid == null) {
-                return name;
-            } else {
-                return uuid.getValue(Type.STRING);
-            }
-        }
-
-        /**
-         * {@link NodeStateDiff} of the changes
-         * @param diff  node state diff instance for traversing the changes.
-         * @param path  path where diffing should start
-         */
-        public void diff(RecursingNodeStateDiff diff, String path) {
-            NodeStateDiff secureDiff = SecureNodeStateDiff.wrap(diff);
-            getNode(after, path).compareAgainstBaseState(getNode(before, path), secureDiff);
+        public NodeState getAfterState() {
+            return after;
         }
 
         @Override

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java?rev=1502527&r1=1502526&r2=1502527&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java
Fri Jul 12 12:20:37 2013
@@ -20,6 +20,15 @@ package org.apache.jackrabbit.oak.jcr.ob
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterators.emptyIterator;
+import static com.google.common.collect.Iterators.singletonIterator;
+import static com.google.common.collect.Iterators.transform;
+import static javax.jcr.observation.Event.NODE_ADDED;
+import static javax.jcr.observation.Event.NODE_REMOVED;
+import static javax.jcr.observation.Event.PROPERTY_ADDED;
+import static javax.jcr.observation.Event.PROPERTY_REMOVED;
+import static org.apache.jackrabbit.oak.core.IdentifierManager.getIdentifier;
+import static org.apache.jackrabbit.oak.spi.state.NodeStateUtils.getNode;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -31,24 +40,24 @@ import javax.jcr.observation.Event;
 import javax.jcr.observation.EventListener;
 
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 import com.google.common.collect.Iterators;
-import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.jmx.EventListenerMBean;
 import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
 import org.apache.jackrabbit.commons.observation.ListenerTracker;
 import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ImmutableRoot;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.ChangeSet;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.Listener;
 import org.apache.jackrabbit.oak.plugins.observation.Observable;
-import org.apache.jackrabbit.oak.spi.state.RecursingNodeStateDiff;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.observation.SecureNodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.RecursingNodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.VisibleDiff;
 import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
@@ -185,9 +194,13 @@ class ChangeProcessor implements Runnabl
             while (!stopping && changes != null) {
                 EventFilter filter = filterRef.get();
                 if (!(filter.excludeLocal() && changes.isLocal(contentSession)))
{
+                    NodeState beforeState = changes.getBeforeState();
+                    NodeState afterState = changes.getAfterState();
                     String path = namePathMapper.getOakPath(filter.getPath());
-                    EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(changes,
path);
-                    changes.diff(VisibleDiff.wrap(diff), path);
+                    EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(
+                            changes, new ImmutableRoot(beforeState), new ImmutableRoot(afterState),
path);
+                    NodeStateDiff secureDiff = SecureNodeStateDiff.wrap(VisibleDiff.wrap(diff));
+                    getNode(afterState, path).compareAgainstBaseState(getNode(beforeState,
path), secureDiff);
                     if (!stopping) {
                         diff.sendEvents();
                     }
@@ -208,30 +221,24 @@ class ChangeProcessor implements Runnabl
     //------------------------------------------------------------< private >---
 
     private class EventGeneratingNodeStateDiff extends RecursingNodeStateDiff {
-        public static final int PURGE_LIMIT = 8192;
+        public static final int EVENT_LIMIT = 8192;
 
         private final ChangeSet changes;
-        private final String path;
-        private final NodeState beforeParentNode;
-        private final NodeState afterParentNode;
-        private final String name;
+        private final Tree beforeTree;
+        private final Tree afterTree;
 
         private List<Iterator<Event>> events;
-        private int childNodeCount;
-
-        EventGeneratingNodeStateDiff(ChangeSet changes, String path, List<Iterator<Event>>
events,
-                NodeState beforeParentNode, NodeState afterParentNode, String name) {
+        private int eventCount;
 
+        EventGeneratingNodeStateDiff(ChangeSet changes, Tree beforeTree, Tree afterTree,
List<Iterator<Event>> events) {
             this.changes = changes;
-            this.path = path;
+            this.beforeTree = beforeTree;
+            this.afterTree = afterTree;
             this.events = events;
-            this.beforeParentNode = beforeParentNode;
-            this.afterParentNode = afterParentNode;
-            this.name = name;
         }
 
-        public EventGeneratingNodeStateDiff(ChangeSet changes, String path) {
-            this(changes, path, new ArrayList<Iterator<Event>>(PURGE_LIMIT),
null, null, "");
+        public EventGeneratingNodeStateDiff(ChangeSet changes, Root beforeRoot, Root afterRoot,
String path) {
+            this(changes, beforeRoot.getTree(path), afterRoot.getTree(path), new ArrayList<Iterator<Event>>(EVENT_LIMIT));
         }
 
         public void sendEvents() {
@@ -248,44 +255,44 @@ class ChangeProcessor implements Runnabl
                 catch (Exception e) {
                     log.warn("Unhandled exception in observation listener: " + listener,
e);
                 }
-                events = new ArrayList<Iterator<Event>>(PURGE_LIMIT);
+                events = new ArrayList<Iterator<Event>>(EVENT_LIMIT);
             }
         }
 
         @Override
         public boolean propertyAdded(PropertyState after) {
-            if (filterRef.get().include(Event.PROPERTY_ADDED, path, afterParentNode)) {
-                Event event = generatePropertyEvent(Event.PROPERTY_ADDED, path, after, changes.getAfterId(path));
-                events.add(Iterators.singletonIterator(event));
+            if (filterRef.get().include(PROPERTY_ADDED, afterTree)) {
+                Event event = generatePropertyEvent(PROPERTY_ADDED, afterTree, after);
+                events.add(singletonIterator(event));
             }
             return !stopping;
         }
 
         @Override
         public boolean propertyChanged(PropertyState before, PropertyState after) {
-            if (filterRef.get().include(Event.PROPERTY_CHANGED, path, afterParentNode)) {
-                Event event = generatePropertyEvent(Event.PROPERTY_CHANGED, path, after,
changes.getAfterId(path));
-                events.add(Iterators.singletonIterator(event));
+            if (filterRef.get().include(Event.PROPERTY_CHANGED, afterTree)) {
+                Event event = generatePropertyEvent(Event.PROPERTY_CHANGED, afterTree, after);
+                events.add(singletonIterator(event));
             }
             return !stopping;
         }
 
         @Override
         public boolean propertyDeleted(PropertyState before) {
-            if (filterRef.get().include(Event.PROPERTY_REMOVED, path, afterParentNode)) {
-                Event event = generatePropertyEvent(Event.PROPERTY_REMOVED, path, before,
changes.getBeforeId(path));
-                events.add(Iterators.singletonIterator(event));
+            if (filterRef.get().include(PROPERTY_REMOVED, afterTree)) {
+                Event event = generatePropertyEvent(PROPERTY_REMOVED, beforeTree, before);
+                events.add(singletonIterator(event));
             }
             return !stopping;
         }
 
         @Override
         public boolean childNodeAdded(String name, NodeState after) {
-            if (filterRef.get().includeChildren(path)) {
-                Iterator<Event> events = generateNodeEvents(Event.NODE_ADDED, path,
name,
-                        after, afterParentNode, changes.getAfterId(PathUtils.concat(path,
name)));
+            if (filterRef.get().includeChildren(afterTree.getPath())) {
+                Iterator<Event> events = generateNodeEvents(
+                        NODE_ADDED, afterTree.getChild(name));
                 this.events.add(events);
-                if (++childNodeCount > PURGE_LIMIT) {
+                if (++eventCount > EVENT_LIMIT) {
                     sendEvents();
                 }
             }
@@ -294,9 +301,9 @@ class ChangeProcessor implements Runnabl
 
         @Override
         public boolean childNodeDeleted(String name, NodeState before) {
-            if (filterRef.get().includeChildren(path)) {
-                Iterator<Event> events = generateNodeEvents(Event.NODE_REMOVED, path,
name,
-                        before, beforeParentNode, changes.getBeforeId(PathUtils.concat(path,
name)));
+            if (filterRef.get().includeChildren(beforeTree.getPath())) {
+                Iterator<Event> events = generateNodeEvents(
+                        NODE_REMOVED, beforeTree.getChild(name));
                 this.events.add(events);
             }
             return !stopping;
@@ -310,9 +317,9 @@ class ChangeProcessor implements Runnabl
         @Nonnull
         @Override
         public RecursingNodeStateDiff createChildDiff(String name, NodeState before, NodeState
after) {
-            if (filterRef.get().includeChildren(path)) {
+            if (filterRef.get().includeChildren(afterTree.getPath())) {
                 EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(
-                        changes, PathUtils.concat(path, name), events, before, after, name);
+                        changes, beforeTree.getChild(name), afterTree.getChild(name), events);
                 return VisibleDiff.wrap(diff);
             } else {
                 return RecursingNodeStateDiff.EMPTY;
@@ -327,81 +334,53 @@ class ChangeProcessor implements Runnabl
                     changes.isExternal());
         }
 
-        private Event generatePropertyEvent(int eventType, String parentPath, PropertyState
property, String id) {
-            String path = PathUtils.concat(parentPath, property.getName());
-            return createEvent(eventType, path, id);
+        private Event generatePropertyEvent(int eventType, Tree parent, PropertyState property)
{
+            String path = PathUtils.concat(parent.getPath(), property.getName());
+            return createEvent(eventType, path, getIdentifier(parent));
         }
 
-        private Iterator<Event> generateNodeEvents(int eventType, String parentPath,
String childName,
-                NodeState node, NodeState parentNode, final String id) {
+        private Iterator<Event> generateNodeEvents(int eventType, final Tree tree)
{
             EventFilter filter = filterRef.get();
-            final String path = PathUtils.concat(parentPath, childName);
             Iterator<Event> nodeEvent;
-            if (filter.include(eventType, parentPath, parentNode)) {
-                Event event = createEvent(eventType, path, id);
-                nodeEvent = Iterators.singletonIterator(event);
+            if (filter.include(eventType, tree.isRoot() ? null : tree.getParent())) {
+                Event event = createEvent(eventType, tree.getPath(), getIdentifier(tree));
+                nodeEvent = singletonIterator(event);
             } else {
-                nodeEvent = Iterators.emptyIterator();
+                nodeEvent = emptyIterator();
             }
 
-            final int propertyEventType = eventType == Event.NODE_ADDED
-                    ? Event.PROPERTY_ADDED
-                    : Event.PROPERTY_REMOVED;
+            final int propertyEventType = eventType == NODE_ADDED
+                    ? PROPERTY_ADDED
+                    : PROPERTY_REMOVED;
 
             Iterator<Event> propertyEvents;
-            if (filter.include(propertyEventType, path, parentNode)) {
-                propertyEvents = Iterators.transform(
-                        Iterators.filter(
-                                node.getProperties().iterator(),
-                                new Predicate<PropertyState>() {
-                                    @Override
-                                    public boolean apply(PropertyState propertyState) {
-                                        return !NodeStateUtils.isHidden(propertyState.getName());
-                                    }
-                                }),
+            if (filter.include(propertyEventType, tree)) {
+                propertyEvents = transform(
+                        tree.getProperties().iterator(),
                         new Function<PropertyState, Event>() {
                             @Override
                             public Event apply(PropertyState property) {
-                                return generatePropertyEvent(propertyEventType, path, property,
id);
+                                return generatePropertyEvent(propertyEventType, tree, property);
                             }
                         });
             } else {
-                propertyEvents = Iterators.emptyIterator();
+                propertyEvents = emptyIterator();
             }
 
-            Iterator<Event> childNodeEvents = filter.includeChildren(path)
-                    ? Iterators.concat(generateChildEvents(eventType, path, node, id))
+            Iterator<Event> childNodeEvents = filter.includeChildren(tree.getPath())
+                    ? Iterators.concat(generateChildEvents(eventType, tree))
                     : Iterators.<Event>emptyIterator();
 
             return Iterators.concat(nodeEvent, propertyEvents, childNodeEvents);
         }
 
-        private Iterator<Iterator<Event>> generateChildEvents(final int eventType,
final String parentPath,
-                final NodeState parentNode, final String parentId) {
-            return Iterators.transform(
-                    Iterators.filter(parentNode.getChildNodeEntries().iterator(),
-                            new Predicate<ChildNodeEntry>() {
-                                @Override
-                                public boolean apply(ChildNodeEntry entry) {
-                                    return !NodeStateUtils.isHidden(entry.getName());
-                                }
-                            }),
-                    new Function<ChildNodeEntry, Iterator<Event>>() {
+        private Iterator<Iterator<Event>> generateChildEvents(final int eventType,
final Tree tree) {
+            return transform(
+                    tree.getChildren().iterator(),
+                    new Function<Tree, Iterator<Event>>() {
                         @Override
-                        public Iterator<Event> apply(ChildNodeEntry entry) {
-                            NodeState node = entry.getNodeState();
-                            String name = entry.getName();
-                            return generateNodeEvents(eventType, parentPath, name,
-                                    node, parentNode, getId(parentId, node, name));
-                        }
-
-                        private String getId(String parentId, NodeState node, String name)
{
-                            PropertyState uuid = node.getProperty(JcrConstants.JCR_UUID);
-                            if (uuid == null) {
-                                return parentId + '/' + namePathMapper.getJcrName(name);
-                            } else {
-                                return uuid.getValue(Type.STRING);
-                            }
+                        public Iterator<Event> apply(Tree child) {
+                            return generateNodeEvents(eventType, child);
                         }
                     });
         }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFilter.java?rev=1502527&r1=1502526&r2=1502527&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFilter.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFilter.java
Fri Jul 12 12:20:37 2013
@@ -20,7 +20,7 @@ package org.apache.jackrabbit.oak.jcr.ob
 
 import static com.google.common.base.Objects.toStringHelper;
 
-import javax.annotation.Nullable;
+import javax.annotation.CheckForNull;
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 
@@ -29,9 +29,7 @@ import org.apache.jackrabbit.oak.api.Pro
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 /**
  * Filter for filtering observation events according to a certain criterion.
@@ -74,15 +72,15 @@ class EventFilter {
     /**
      * Match an event against this filter.
      * @param eventType  type of the event
-     * @param path       path of the event
-     * @param associatedParentNode  associated parent node of the event
+     * @param associatedParent  associated parent node of the event
      * @return  {@code true} if the filter matches this event. {@code false} otherwise.
      */
-    public boolean include(int eventType, String path, @Nullable NodeState associatedParentNode)
{
-        return include(eventType)
-                && include(path)
-                && (associatedParentNode == null || includeByType(new ImmutableTree(associatedParentNode)))
-                && (associatedParentNode == null || includeByUuid(associatedParentNode));
+    public boolean include(int eventType, @CheckForNull Tree associatedParent) {
+        return includeByEvent(eventType)
+            && associatedParent != null
+            && includeByPath(associatedParent.getPath())
+            && includeByType(associatedParent)
+            && includeByUuid(associatedParent);
     }
 
     /**
@@ -124,11 +122,11 @@ class EventFilter {
 
     //-----------------------------< internal >---------------------------------
 
-    private boolean include(int eventType) {
+    private boolean includeByEvent(int eventType) {
         return (this.eventTypes & eventType) != 0;
     }
 
-    private boolean include(String path) {
+    private boolean includeByPath(String path) {
         boolean equalPaths = this.path.equals(path);
         if (!deep && !equalPaths) {
             return false;
@@ -144,16 +142,16 @@ class EventFilter {
      * Checks whether to include an event based on the type of the associated
      * parent node and the node type filter.
      *
-     * @param associatedParentNode the associated parent node of the event.
+     * @param associatedParent the associated parent node of the event.
      * @return whether to include the event based on the type of the associated
      *         parent node.
      */
-    private boolean includeByType(Tree associatedParentNode) {
+    private boolean includeByType(Tree associatedParent) {
         if (nodeTypeOakName == null) {
             return true;
         } else {
             for (String oakName : nodeTypeOakName) {
-                if (ntMgr.isNodeType(associatedParentNode, oakName)) {
+                if (ntMgr.isNodeType(associatedParent, oakName)) {
                     return true;
                 }
             }
@@ -162,7 +160,7 @@ class EventFilter {
         }
     }
 
-    private boolean includeByUuid(NodeState associatedParentNode) {
+    private boolean includeByUuid(Tree associatedParent) {
         if (uuids == null) {
             return true;
         }
@@ -170,7 +168,7 @@ class EventFilter {
             return false;
         }
 
-        PropertyState uuidProperty = associatedParentNode.getProperty(JcrConstants.JCR_UUID);
+        PropertyState uuidProperty = associatedParent.getProperty(JcrConstants.JCR_UUID);
         if (uuidProperty == null) {
             return false;
         }



Mime
View raw message