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/03/26 15:01:06 UTC

svn commit: r1461135 - in /jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr: SessionImpl.java delegate/SessionDelegate.java

Author: mduerig
Date: Tue Mar 26 14:01:05 2013
New Revision: 1461135

URL: http://svn.apache.org/r1461135
Log:
OAK-672: Avoid JCR APIs calling other JCR APIs
OAK-662: Reduce boilerplate code in JCR impl methods
 refactor session related methods to use common base class of SessionOperation, which takes care of establishing session preconditions.

Modified:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java?rev=1461135&r1=1461134&r2=1461135&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java Tue Mar 26 14:01:05 2013
@@ -25,6 +25,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
@@ -54,7 +55,6 @@ import org.apache.jackrabbit.commons.xml
 import org.apache.jackrabbit.commons.xml.ParsingContentHandler;
 import org.apache.jackrabbit.commons.xml.SystemViewExporter;
 import org.apache.jackrabbit.commons.xml.ToXmlContentHandler;
-import org.apache.jackrabbit.oak.api.TreeLocation;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
 import org.apache.jackrabbit.oak.jcr.delegate.PropertyDelegate;
@@ -62,7 +62,6 @@ import org.apache.jackrabbit.oak.jcr.del
 import org.apache.jackrabbit.oak.jcr.delegate.SessionOperation;
 import org.apache.jackrabbit.oak.jcr.xml.ImportHandler;
 import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
-import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.util.TODO;
 import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.util.XMLChar;
@@ -75,14 +74,10 @@ import org.xml.sax.SAXException;
  * TODO document
  */
 public class SessionImpl implements JackrabbitSession {
-
-    /**
-     * logger instance
-     */
     private static final Logger log = LoggerFactory.getLogger(SessionImpl.class);
 
     private final SessionContext sessionContext;
-    private final SessionDelegate dlg;
+    private final SessionDelegate sd;
 
     /**
      * Local namespace remappings. Prefixes as keys and namespace URIs as values.
@@ -94,7 +89,7 @@ public class SessionImpl implements Jack
 
     SessionImpl(SessionContext sessionContext, Map<String, String> namespaces) {
         this.sessionContext = sessionContext;
-        this.dlg = sessionContext.getSessionDelegate();
+        this.sd = sessionContext.getSessionDelegate();
         this.namespaces = namespaces;
     }
 
@@ -105,6 +100,108 @@ public class SessionImpl implements Jack
         }
     }
 
+    private abstract class CheckedSessionOperation<T> extends SessionOperation<T> {
+        @Override
+        protected void checkPreconditions() throws RepositoryException {
+            sd.checkAlive();
+        }
+    }
+
+    @CheckForNull
+    private <T> T perform(@Nonnull CheckedSessionOperation<T> op) throws RepositoryException {
+        return sd.perform(op);
+    }
+
+    @Nonnull
+    private String getOakPathOrThrow(String absPath) throws RepositoryException {
+        return sessionContext.getOakPathOrThrow(absPath);
+    }
+
+    @Nonnull
+    private String getOakPathOrThrowNotFound(String absPath) throws PathNotFoundException {
+        return sessionContext.getOakPathOrThrowNotFound(absPath);
+    }
+
+    private NodeImpl<?> createNodeOrNull(NodeDelegate nd) {
+        return nd == null ? null : new NodeImpl<NodeDelegate>(nd, sessionContext);
+    }
+
+    private PropertyImpl createPropertyOrNull(PropertyDelegate pd) {
+        return pd == null ? null : new PropertyImpl(pd, sessionContext);
+    }
+
+    @CheckForNull
+    private ItemImpl<?> getItemInternal(@Nonnull String oakPath) {
+        NodeDelegate nd = sd.getNode(oakPath);
+        if (nd != null) {
+            return createNodeOrNull(nd);
+        }
+        PropertyDelegate pd = sd.getProperty(oakPath);
+        if (pd != null) {
+            return createPropertyOrNull(pd);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the node at the specified absolute path in the workspace or
+     * {@code null} if no such node exists.
+     *
+     * @param absPath An absolute path.
+     * @return the specified {@code Node} or {@code null}.
+     * @throws RepositoryException   If another error occurs.
+     */
+    @CheckForNull
+    public Node getNodeOrNull(final String absPath) throws RepositoryException {
+        return perform(new CheckedSessionOperation<Node>() {
+            @Override
+            public Node perform() throws RepositoryException {
+                return createNodeOrNull(sd.getNode(getOakPathOrThrow(absPath)));
+            }
+        });
+    }
+
+    /**
+     * Returns the property at the specified absolute path in the workspace or
+     * {@code null} if no such node exists.
+     *
+     * @param absPath An absolute path.
+     * @return the specified {@code Property} or {@code null}.
+     * @throws RepositoryException   if another error occurs.
+     */
+    @CheckForNull
+    public Property getPropertyOrNull(final String absPath) throws RepositoryException {
+        if (absPath.equals("/")) {
+            return null;
+        } else {
+            return perform(new CheckedSessionOperation<Property>() {
+                @Override
+                public Property perform() throws RepositoryException {
+                    return createPropertyOrNull(sd.getProperty(getOakPathOrThrow(absPath)));
+                }
+            });
+        }
+    }
+
+    /**
+     * Returns the node at the specified absolute path in the workspace. If no
+     * such node exists, then it returns the property at the specified path.
+     * If no such property exists, then it return {@code null}.
+     *
+     * @param absPath An absolute path.
+     * @return the specified {@code Item} or {@code null}.
+     * @throws RepositoryException   if another error occurs.
+     */
+    @CheckForNull
+    public Item getItemOrNull(final String absPath) throws RepositoryException {
+        return perform(new CheckedSessionOperation<Item>() {
+            @Override
+            public Item perform() throws RepositoryException {
+                return getItemInternal(getOakPathOrThrow(absPath));
+            }
+        });
+    }
+
     //------------------------------------------------------------< Session >---
 
     @Override
@@ -115,17 +212,17 @@ public class SessionImpl implements Jack
 
     @Override
     public String getUserID() {
-        return dlg.getAuthInfo().getUserID();
+        return sd.getAuthInfo().getUserID();
     }
 
     @Override
     public String[] getAttributeNames() {
-        return dlg.getAuthInfo().getAttributeNames();
+        return sd.getAuthInfo().getAttributeNames();
     }
 
     @Override
     public Object getAttribute(String name) {
-        return dlg.getAuthInfo().getAttribute(name);
+        return sd.getAuthInfo().getAttribute(name);
     }
 
     @Override
@@ -137,166 +234,108 @@ public class SessionImpl implements Jack
     @Override
     @Nonnull
     public Session impersonate(Credentials credentials) throws RepositoryException {
-        dlg.checkAlive();
+        sd.checkAlive();
 
-        ImpersonationCredentials impCreds = new ImpersonationCredentials(credentials, dlg.getAuthInfo());
-        return getRepository().login(impCreds, dlg.getWorkspaceName());
+        ImpersonationCredentials impCreds = new ImpersonationCredentials(credentials, sd.getAuthInfo());
+        return getRepository().login(impCreds, sd.getWorkspaceName());
     }
 
     @Override
     @Nonnull
     public ValueFactory getValueFactory() throws RepositoryException {
-        dlg.checkAlive();
+        sd.checkAlive();
         return sessionContext.getValueFactory();
     }
 
     @Override
     @Nonnull
     public Node getRootNode() throws RepositoryException {
-        return dlg.perform(new SessionOperation<NodeImpl<?>>() {
+        return perform(new CheckedSessionOperation<Node>() {
             @Override
-            protected void checkPreconditions() throws RepositoryException {
-                dlg.checkAlive();
-            }
-
-            @Override
-            public NodeImpl<?> perform() throws AccessDeniedException {
-                NodeDelegate nd = dlg.getRootNode();
+            protected Node perform() throws AccessDeniedException {
+                NodeDelegate nd = sd.getRootNode();
                 if (nd == null) {
                     throw new AccessDeniedException("Root node is not accessible.");
-                } else {
-                    return new NodeImpl<NodeDelegate>(nd, sessionContext);
                 }
+                return createNodeOrNull(nd);
             }
         });
     }
 
     @Override
-    @Nonnull
-    public Node getNodeByUUID(String uuid) throws RepositoryException {
-        return getNodeByIdentifier(uuid);
+    public Node getNode(String absPath) throws RepositoryException {
+        Node node = getNodeOrNull(absPath);
+        if (node == null) {
+            throw new PathNotFoundException("Node with path " + absPath + " does not exist.");
+        }
+        return node;
     }
 
     @Override
-    @Nonnull
-    public Node getNodeByIdentifier(final String id) throws RepositoryException {
-        return dlg.perform(new SessionOperation<NodeImpl<?>>() {
-            @Override
-            protected void checkPreconditions() throws RepositoryException {
-                dlg.checkAlive();
-            }
+    public boolean nodeExists(String absPath) throws RepositoryException {
+        return getNodeOrNull(absPath) != null;
+    }
 
+    @Nonnull
+    private Node getNodeById(final String id) throws RepositoryException {
+        return perform(new CheckedSessionOperation<Node>() {
             @Override
-            public NodeImpl<?> perform() throws RepositoryException {
-                NodeDelegate d = dlg.getNodeByIdentifier(id);
-                if (d == null) {
+            public Node perform() throws ItemNotFoundException {
+                NodeDelegate nd = sd.getNodeByIdentifier(id);
+                if (nd == null) {
                     throw new ItemNotFoundException("Node with id " + id + " does not exist.");
                 }
-                return new NodeImpl<NodeDelegate>(d, sessionContext);
+                return createNodeOrNull(nd);
             }
         });
     }
 
     @Override
-    public Item getItem(String absPath) throws RepositoryException {
-        if (nodeExists(absPath)) {
-            return getNode(absPath);
-        } else {
-            return getProperty(absPath);
-        }
+    @Nonnull
+    public Node getNodeByUUID(String uuid) throws RepositoryException {
+        return getNodeById(uuid);
     }
 
     @Override
-    public boolean itemExists(String absPath) throws RepositoryException {
-        return nodeExists(absPath) || propertyExists(absPath);
-    }
-
-    private String getOakPath(String absPath) throws RepositoryException {
-        return sessionContext.getOakPathOrThrow(absPath);
+    @Nonnull
+    public Node getNodeByIdentifier(String id) throws RepositoryException {
+        return getNodeById(id);
     }
 
     @Override
-    public Node getNode(final String absPath) throws RepositoryException {
-        return dlg.perform(new SessionOperation<NodeImpl<?>>() {
-            @Override
-            protected void checkPreconditions() throws RepositoryException {
-                dlg.checkAlive();
-            }
-
-            @Override
-            public NodeImpl<?> perform() throws RepositoryException {
-                String oakPath = getOakPath(absPath);
-                NodeDelegate d = dlg.getNode(oakPath);
-                if (d == null) {
-                    throw new PathNotFoundException("Node with path " + absPath + " does not exist.");
-                }
-                return new NodeImpl<NodeDelegate>(d, sessionContext);
-            }
-        });
+    public Property getProperty(String absPath) throws RepositoryException {
+        Property property = getPropertyOrNull(absPath);
+        if (property == null) {
+            throw new PathNotFoundException(absPath);
+        }
+        return property;
     }
 
     @Override
-    public boolean nodeExists(final String absPath) throws RepositoryException {
-        return dlg.perform(new SessionOperation<Boolean>() {
-            @Override
-            protected void checkPreconditions() throws RepositoryException {
-                dlg.checkAlive();
-            }
-
-            @Override
-            public Boolean perform() throws RepositoryException {
-                String oakPath = getOakPath(absPath);
-                return dlg.getNode(oakPath) != null;
-            }
-        });
+    public boolean propertyExists(String absPath) throws RepositoryException {
+        return getPropertyOrNull(absPath) != null;
     }
 
     @Override
-    public Property getProperty(final String absPath) throws RepositoryException {
-        if (absPath.equals("/")) {
-            throw new RepositoryException("The root node is not a property");
-        } else {
-            return dlg.perform(new SessionOperation<PropertyImpl>() {
-                @Override
-                public PropertyImpl perform() throws RepositoryException {
-                    String oakPath = getOakPathOrThrowNotFound(absPath);
-                    TreeLocation loc = dlg.getLocation(oakPath);
-                    if (loc.getProperty() == null) {
-                        throw new PathNotFoundException(absPath);
-                    } else {
-                        return new PropertyImpl(new PropertyDelegate(dlg, loc), sessionContext);
-                    }
-                }
-            });
+    public Item getItem(String absPath) throws RepositoryException {
+        Item item = getItemOrNull(absPath);
+        if (item == null) {
+            throw new PathNotFoundException(absPath);
         }
-    }
-
-    private String getOakPathOrThrowNotFound(String absPath) throws PathNotFoundException {
-        return sessionContext.getOakPathOrThrowNotFound(absPath);
+        return item;
     }
 
     @Override
-    public boolean propertyExists(final String absPath) throws RepositoryException {
-        if (absPath.equals("/")) {
-            throw new RepositoryException("The root node is not a property");
-        } else {
-            return dlg.perform(new SessionOperation<Boolean>() {
-                @Override
-                public Boolean perform() throws RepositoryException {
-                    String oakPath = getOakPathOrThrowNotFound(absPath);
-                    TreeLocation loc = dlg.getLocation(oakPath);
-                    return loc.getProperty() != null;
-                }
-            });
-        }
+    public boolean itemExists(String absPath) throws RepositoryException {
+        return getItemOrNull(absPath) != null;
     }
 
     @Override
     public void move(final String srcAbsPath, final String destAbsPath) throws RepositoryException {
-        dlg.perform(new SessionOperation<Void>() {
+        sd.perform(new CheckedSessionOperation<Void>() {
             @Override
             protected void checkPreconditions() throws RepositoryException {
-                dlg.checkAlive();
+                super.checkPreconditions();
                 checkProtectedNodes(SessionImpl.this,
                         Text.getRelativeParent(srcAbsPath, 1), Text.getRelativeParent(destAbsPath, 1));
             }
@@ -309,49 +348,64 @@ public class SessionImpl implements Jack
                     throw new RepositoryException("Cannot create a new node using a name including an index");
                 }
 
-                dlg.move(getOakPathOrThrowNotFound(srcAbsPath), oakDestPath, true);
+                sd.move(getOakPathOrThrowNotFound(srcAbsPath), oakDestPath, true);
                 return null;
             }
         });
     }
 
     @Override
-    public void removeItem(String absPath) throws RepositoryException {
-        getItem(absPath).remove();
+    public void removeItem(final String absPath) throws RepositoryException {
+        perform(new CheckedSessionOperation<Void>() {
+            @Override
+            protected Void perform() throws RepositoryException {
+                String oakPath = getOakPathOrThrowNotFound(absPath);
+                ItemImpl<?> item = getItemInternal(oakPath);
+                if (item == null) {
+                    throw new PathNotFoundException(absPath);
+                }
+
+                item.checkProtected();
+                item.remove();
+                return null;
+            }
+        });
     }
 
     @Override
     public void save() throws RepositoryException {
-        dlg.checkAlive();
-        dlg.save();
+        sd.checkAlive();
+        sd.save();
         sessionContext.refresh();
     }
 
     @Override
     public void refresh(boolean keepChanges) throws RepositoryException {
-        dlg.checkAlive();
-        dlg.refresh(keepChanges);
+        sd.checkAlive();
+        sd.refresh(keepChanges);
         sessionContext.refresh();
     }
 
     @Override
     public boolean hasPendingChanges() throws RepositoryException {
-        dlg.checkAlive();
-        return dlg.hasPendingChanges();
+        sd.checkAlive();
+        return sd.hasPendingChanges();
     }
 
     @Override
     public boolean isLive() {
-        return dlg.isAlive();
+        return sd.isAlive();
     }
 
 
     @Override
     public void logout() {
-        sessionContext.dispose();
-        dlg.logout();
-        synchronized (namespaces) {
-            namespaces.clear();
+        if (sd.isAlive()) {
+            sessionContext.dispose();
+            sd.logout();
+            synchronized (namespaces) {
+                namespaces.clear();
+            }
         }
     }
 
@@ -414,7 +468,7 @@ public class SessionImpl implements Jack
             throws IOException, RepositoryException {
         try {
             ContentHandler handler = new ToXmlContentHandler(out);
-            exportSystemView(absPath, handler, skipBinary, noRecurse);
+            export(absPath, new SystemViewExporter(this, handler, !noRecurse, !skipBinary));
         } catch (SAXException e) {
             Exception exception = e.getException();
             if (exception instanceof RepositoryException) {
@@ -438,7 +492,7 @@ public class SessionImpl implements Jack
             throws IOException, RepositoryException {
         try {
             ContentHandler handler = new ToXmlContentHandler(out);
-            exportDocumentView(absPath, handler, skipBinary, noRecurse);
+            export(absPath, new DocumentViewExporter(this, handler, !noRecurse, !skipBinary));
         } catch (SAXException e) {
             Exception exception = e.getException();
             if (exception instanceof RepositoryException) {
@@ -495,16 +549,14 @@ public class SessionImpl implements Jack
     }
 
     @Override
-    public boolean hasPermission(String absPath, String actions) throws RepositoryException {
-        dlg.checkAlive();
-
-        String oakPath = sessionContext.getOakPathKeepIndex(absPath);
-        if (oakPath == null) {
-            throw new RepositoryException("Invalid JCR path: " + absPath);
-        }
-
-        PermissionProvider permissionProvider = sessionContext.getPermissionProvider();
-        return permissionProvider.isGranted(absPath, actions);
+    public boolean hasPermission(final String absPath, final String actions) throws RepositoryException {
+        return perform(new CheckedSessionOperation<Boolean>() {
+            @Override
+            protected Boolean perform() throws RepositoryException {
+                String oakPath = getOakPathOrThrow(absPath);
+                return sessionContext.getPermissionProvider().isGranted(oakPath, actions);
+            }
+        });
     }
 
     @Override
@@ -516,7 +568,7 @@ public class SessionImpl implements Jack
 
     @Override
     public boolean hasCapability(String methodName, Object target, Object[] arguments) throws RepositoryException {
-        dlg.checkAlive();
+        sd.checkAlive();
 
         // TODO
         return TODO.unimplemented().returnValue(false);

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java?rev=1461135&r1=1461134&r2=1461135&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java Tue Mar 26 14:01:05 2013
@@ -58,6 +58,11 @@ public class SessionDelegate {
         this.idManager = new IdentifierManager(root);
     }
 
+    /**
+     * Called by {@link #perform(SessionOperation)} when the session needs to be
+     * refreshed before the actual {@link SessionOperation} is executed.
+     * This default implementation is empty.
+     */
     protected void refresh() {
     }
 
@@ -74,24 +79,19 @@ public class SessionDelegate {
      */
     public synchronized <T> T perform(SessionOperation<T> sessionOperation) throws RepositoryException {
         // Synchronize to avoid conflicting refreshes from concurrent JCR API calls
+        if (sessionOpCount == 0) {
+            // Refresh and checks only for non re-entrant session operations
+            refresh();
+            sessionOperation.checkPreconditions();
+        }
         try {
-            if (sessionOpCount == 0) {
-                // Refresh only for non re-entrant session operations
-                refresh();
-            }
             sessionOpCount++;
-            sessionOperation.checkPreconditions();
             return sessionOperation.perform();
         } finally {
             sessionOpCount--;
         }
     }
 
-    @Nonnull  // FIXME this should be package private
-    public Root getRoot() {
-        return root;
-    }
-
     @Nonnull
     public ContentSession getContentSession() {
         return contentSession;
@@ -143,11 +143,6 @@ public class SessionDelegate {
         return idManager;
     }
 
-    @Nonnull
-    public TreeLocation getLocation(String path) {
-        return root.getLocation(path);
-    }
-
     @CheckForNull
     public NodeDelegate getRootNode() {
         return getNode("/");
@@ -297,6 +292,16 @@ public class SessionDelegate {
 
     //-----------------------------------------------------------< internal >---
 
+    @Nonnull  // FIXME this should be package private
+    public Root getRoot() {
+        return root;
+    }
+
+    @Nonnull
+    TreeLocation getLocation(String path) {
+        return root.getLocation(path);
+    }
+
     /**
      * Revision of this session. The revision is incremented each time a session is refreshed or saved.
      * This allows items to determine whether they need to re-resolve their underlying state when the