### Eclipse Workspace Patch 1.0 #P oak Index: oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootImplFuzzIT.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootImplFuzzIT.java (revision 1506849) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootImplFuzzIT.java (working copy) @@ -32,6 +32,7 @@ import org.apache.jackrabbit.mk.api.MicroKernel; import org.apache.jackrabbit.mk.core.MicroKernelImpl; +import org.apache.jackrabbit.oak.api.ContentSession; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.commons.PathUtils; @@ -59,10 +60,10 @@ private static final Random random = new Random(SEED); private KernelNodeStore store1; - private RootImpl root1; + private AbstractMutableRoot root1; private KernelNodeStore store2; - private RootImpl root2; + private AbstractMutableRoot root2; private int counter; @@ -73,12 +74,12 @@ MicroKernel mk1 = new MicroKernelImpl("./target/mk1/" + random.nextInt()); store1 = new KernelNodeStore(mk1); mk1.commit("", "+\"/root\":{}", mk1.getHeadRevision(), ""); - root1 = new RootImpl(store1); + root1 = new SystemMutableRoot(store1); MicroKernel mk2 = new MicroKernelImpl("./target/mk2/" + random.nextInt()); store2 = new KernelNodeStore(mk2); mk2.commit("", "+\"/root\":{}", mk2.getHeadRevision(), ""); - root2 = new RootImpl(store2); + root2 = new SystemMutableRoot(store2); } @Test @@ -125,7 +126,7 @@ } abstract static class Operation { - abstract void apply(RootImpl root); + abstract void apply(AbstractMutableRoot root); static class AddNode extends Operation { private final String parentPath; @@ -137,7 +138,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.getTree(parentPath).addChild(name); } @@ -155,7 +156,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { String parentPath = PathUtils.getParentPath(path); String name = PathUtils.getName(path); root.getTree(parentPath).getChild(name).remove(); @@ -177,7 +178,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.move(source, destination); } @@ -197,7 +198,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.copy(source, destination); } @@ -219,7 +220,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.getTree(parentPath).setProperty(propertyName, propertyValue); } @@ -240,7 +241,7 @@ } @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.getTree(parentPath).removeProperty(name); } @@ -252,7 +253,7 @@ static class Save extends Operation { @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { // empty } @@ -264,7 +265,7 @@ static class Rebase extends Operation { @Override - void apply(RootImpl root) { + void apply(AbstractMutableRoot root) { root.rebase(); } @@ -439,5 +440,4 @@ checkEqual(child1, tree2.getChild(child1.getName())); } } - } Index: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/SolrBaseTest.java =================================================================== --- oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/SolrBaseTest.java (revision 1506849) +++ oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/SolrBaseTest.java (working copy) @@ -20,7 +20,8 @@ import org.apache.jackrabbit.mk.api.MicroKernel; import org.apache.jackrabbit.mk.core.MicroKernelImpl; -import org.apache.jackrabbit.oak.core.RootImpl; +import org.apache.jackrabbit.oak.api.ContentSession; +import org.apache.jackrabbit.oak.core.AbstractMutableRoot; import org.apache.jackrabbit.oak.kernel.KernelNodeStore; import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider; import org.apache.jackrabbit.oak.plugins.index.solr.index.SolrIndexEditorProvider; @@ -66,9 +67,17 @@ } } - protected RootImpl createRootImpl() { - return new RootImpl(store, hook, PostCommitHook.EMPTY, "solr-query-engine-it", new Subject(), - new OpenSecurityProvider(), new CompositeQueryIndexProvider()); + protected AbstractMutableRoot createRootImpl() { + return new AbstractMutableRoot(store, hook, PostCommitHook.EMPTY, "solr-query-engine-it", new Subject(), + new OpenSecurityProvider(), new CompositeQueryIndexProvider()){ + + @Override + public ContentSession getContentSession() { + // TODO Auto-generated method stub + return null; + } + + }; } protected NodeState createInitialState(MicroKernel microKernel) { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java (working copy) @@ -31,6 +31,7 @@ import java.util.Iterator; +import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import com.google.common.base.Function; @@ -95,6 +96,14 @@ */ @Nonnull protected abstract AbstractTree createChild(@Nonnull String name); + + /** + * Get a possibly non existing tree. + * @param path the path to the tree + * @return a {@link Tree} instance for the child at {@code path}. + */ + @CheckForNull + protected abstract AbstractTree getTree(@Nonnull String path); /** * @return {@code true} if this tree has orderable children; Index: oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerTheirsTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerTheirsTest.java (revision 1506849) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerTheirsTest.java (working copy) @@ -42,7 +42,7 @@ private static final String OUR_VALUE = "our value"; private static final String THEIR_VALUE = "their value"; - private RootImpl ourRoot; + private AbstractMutableRoot ourRoot; private Root theirRoot; @Before @@ -63,7 +63,7 @@ tree.addChild("z"); root.commit(); - ourRoot = (RootImpl) session.getLatestRoot(); + ourRoot = (AbstractMutableRoot) session.getLatestRoot(); theirRoot = session.getLatestRoot(); } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/SystemMutableRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/SystemMutableRoot.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/SystemMutableRoot.java (revision 0) @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.oak.core; + +import java.security.Principal; +import java.util.Set; + +import org.apache.jackrabbit.oak.Oak; +import org.apache.jackrabbit.oak.api.AuthInfo; +import org.apache.jackrabbit.oak.api.ContentSession; +import org.apache.jackrabbit.oak.api.Root; +import org.apache.jackrabbit.oak.security.authentication.SystemSubject; +import org.apache.jackrabbit.oak.spi.commit.CommitHook; +import org.apache.jackrabbit.oak.spi.commit.EmptyHook; +import org.apache.jackrabbit.oak.spi.commit.PostCommitHook; +import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; +import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; +import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider; +import org.apache.jackrabbit.oak.spi.security.SecurityProvider; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import static com.google.common.base.Preconditions.checkState; + +public class SystemMutableRoot extends AbstractMutableRoot { + + public SystemMutableRoot(NodeStore store, CommitHook hook, + String workspaceName, SecurityProvider securityProvider, + QueryIndexProvider indexProvider) { + super(store, hook, PostCommitHook.EMPTY, workspaceName, + SystemSubject.INSTANCE, securityProvider, indexProvider); + } + + // TODO: review if these constructors really make sense and cannot be replaced. + public SystemMutableRoot(NodeStore store) { + this(store, EmptyHook.INSTANCE); + } + + public SystemMutableRoot(NodeStore store, CommitHook hook) { + // FIXME: define proper default or pass workspace name with the constructor + //TODO: check the security provider + this(store, hook, Oak.DEFAULT_WORKSPACE_NAME, + new OpenSecurityProvider(), new CompositeQueryIndexProvider()); + } + + @Override + public ContentSession getContentSession() { + return new ContentSession() { + + private volatile boolean live = true; + + private void checkLive() { + checkState(live, "This session has been closed"); + } + + @Override + public void close() { + live = false; + } + + @Override + public String getWorkspaceName() { + return SystemMutableRoot.this.getWorkspaceName(); + } + + @Override + public Root getLatestRoot() { + checkLive(); + return SystemMutableRoot.this; + } + + @Override + public AuthInfo getAuthInfo() { + return new AuthInfo() { + + @Override + public String getUserID() { + return null; + } + + @Override + public Set getPrincipals() { + return SystemSubject.INSTANCE.getPrincipals(); + } + + @Override + public String[] getAttributeNames() { + return new String[] {}; + } + + @Override + public Object getAttribute(String attributeName) { + return null; + } + }; + } + }; + } + +} Index: oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerOursTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerOursTest.java (revision 1506849) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/core/DefaultConflictHandlerOursTest.java (working copy) @@ -42,7 +42,7 @@ private static final String OUR_VALUE = "our value"; private static final String THEIR_VALUE = "their value"; - private RootImpl ourRoot; + private AbstractMutableRoot ourRoot; private Root theirRoot; @Before @@ -63,7 +63,7 @@ tree.addChild("z"); root.commit(); - ourRoot = (RootImpl) session.getLatestRoot(); + ourRoot = (AbstractMutableRoot) session.getLatestRoot(); theirRoot = session.getLatestRoot(); } Index: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java =================================================================== --- oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java (revision 1506849) +++ oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrCommitHookIT.java (working copy) @@ -21,7 +21,6 @@ import javax.security.auth.Subject; import org.apache.jackrabbit.oak.api.Root; -import org.apache.jackrabbit.oak.core.RootImpl; import org.apache.jackrabbit.oak.plugins.index.solr.SolrBaseTest; import org.apache.jackrabbit.oak.spi.commit.PostCommitHook; import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractMutableRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractMutableRoot.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractMutableRoot.java (working copy) @@ -26,19 +26,14 @@ import java.util.List; import javax.annotation.Nonnull; import javax.security.auth.Subject; - -import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.api.Blob; import org.apache.jackrabbit.oak.api.BlobFactory; import org.apache.jackrabbit.oak.api.CommitFailedException; -import org.apache.jackrabbit.oak.api.ContentSession; import org.apache.jackrabbit.oak.api.QueryEngine; -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.plugins.index.diffindex.UUIDDiffIndexProviderWrapper; import org.apache.jackrabbit.oak.query.QueryEngineImpl; -import org.apache.jackrabbit.oak.security.authentication.SystemSubject; import org.apache.jackrabbit.oak.spi.commit.CommitHook; import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider; import org.apache.jackrabbit.oak.spi.commit.CompositeHook; @@ -47,10 +42,8 @@ import org.apache.jackrabbit.oak.spi.commit.PostCommitHook; import org.apache.jackrabbit.oak.spi.commit.PostValidationHook; import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider; -import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; import org.apache.jackrabbit.oak.spi.security.Context; -import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider; import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.security.authorization.AccessControlConfiguration; @@ -64,7 +57,7 @@ import static org.apache.jackrabbit.oak.commons.PathUtils.getName; import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath; -public class RootImpl implements Root { +public abstract class AbstractMutableRoot extends AbstractRoot { /** * Number of {@link #updated} calls for which changes are kept in memory. @@ -87,12 +80,7 @@ private final SecurityProvider securityProvider; private final QueryIndexProvider indexProvider; - - /** - * Current root {@code Tree} - */ - private final MutableTree rootTree; - + /** * Current branch this root operates on */ @@ -126,7 +114,7 @@ * @param securityProvider the security configuration. * @param indexProvider the query index provider. */ - public RootImpl(NodeStore store, + public AbstractMutableRoot(NodeStore store, CommitHook hook, PostCommitHook postHook, String workspaceName, @@ -145,20 +133,10 @@ NodeState root = branch.getHead(); builder = root.builder(); NodeBuilder secureBuilder = new SecureNodeBuilder(builder, getRootContext(root)); + rootTree = new MutableTree(this, secureBuilder, lastMove); } - - // TODO: review if these constructors really make sense and cannot be replaced. - public RootImpl(NodeStore store) { - this(store, EmptyHook.INSTANCE); - } - - public RootImpl(NodeStore store, CommitHook hook) { - // FIXME: define proper default or pass workspace name with the constructor - this(store, hook, PostCommitHook.EMPTY, Oak.DEFAULT_WORKSPACE_NAME, SystemSubject.INSTANCE, - new OpenSecurityProvider(), new CompositeQueryIndexProvider()); - } - + /** * Called whenever a method on this instance or on any {@code Tree} instance * obtained from this {@code Root} is called. This default implementation @@ -167,20 +145,16 @@ * the session has been logged out already). */ protected void checkLive() { - + } - + + protected String getWorkspaceName() { return workspaceName; } //---------------------------------------------------------------< Root >--- - - @Override - public ContentSession getContentSession() { - throw new UnsupportedOperationException(); - } - + @Override public boolean move(String sourcePath, String destPath) { if (PathUtils.isAncestor(sourcePath, destPath)) { @@ -188,7 +162,7 @@ } checkLive(); - MutableTree destParent = rootTree.getTree(getParentPath(destPath)); + MutableTree destParent = (MutableTree) rootTree.getTree(getParentPath(destPath)); if (!destParent.exists()) { return false; } @@ -196,8 +170,8 @@ boolean success = branch.move(sourcePath, destPath); reset(); if (success) { - getTree(getParentPath(sourcePath)).updateChildOrder(); - getTree(getParentPath(destPath)).updateChildOrder(); + ((MutableTree)getTree(getParentPath(sourcePath))).updateChildOrder(); + ((MutableTree)getTree(getParentPath(destPath))).updateChildOrder(); lastMove = lastMove.setMove(sourcePath, destParent, getName(destPath)); updated(); } @@ -211,18 +185,12 @@ boolean success = branch.copy(sourcePath, destPath); reset(); if (success) { - getTree(getParentPath(destPath)).updateChildOrder(); + ((MutableTree)getTree(getParentPath(destPath))).updateChildOrder(); updated(); } return success; } - - @Override - public MutableTree getTree(@Nonnull String path) { - checkLive(); - return rootTree.getTree(path); - } - + @Override public void rebase() { checkLive(); @@ -324,7 +292,7 @@ @Override protected NodeState getRootState() { - return RootImpl.this.getRootState(); + return AbstractMutableRoot.this.getRootState(); } @Override @@ -350,7 +318,7 @@ } @Nonnull - private QueryIndexProvider getIndexProvider() { + protected QueryIndexProvider getIndexProvider() { if (hasPendingChanges()) { return new UUIDDiffIndexProviderWrapper(indexProvider, getBaseState(), getRootState()); @@ -396,7 +364,7 @@ * @return root node state */ @Nonnull - private NodeState getRootState() { + protected NodeState getRootState() { return builder.getNodeState(); } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (working copy) @@ -202,7 +202,7 @@ @Nonnull private ImmutableTree getPermissionsRoot() { - return immutableRoot.getTree(PERMISSIONS_STORE_PATH + '/' + workspaceName); + return (ImmutableTree)immutableRoot.getTree(PERMISSIONS_STORE_PATH + '/' + workspaceName); } @Nonnull Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (working copy) @@ -97,7 +97,7 @@ @Override public Root getLatestRoot() { checkLive(); - RootImpl root = new RootImpl(store, hook, changeDispatcher.newHook(this), workspaceName, + AbstractMutableRoot root = new AbstractMutableRoot(store, hook, changeDispatcher.newHook(this), workspaceName, loginContext.getSubject(), securityProvider, indexProvider) { @Override protected void checkLive() { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java (working copy) @@ -43,7 +43,7 @@ import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; -import org.apache.jackrabbit.oak.core.RootImpl.Move; +import org.apache.jackrabbit.oak.core.AbstractMutableRoot.Move; import org.apache.jackrabbit.oak.plugins.memory.MemoryPropertyBuilder; import org.apache.jackrabbit.oak.plugins.memory.MultiStringPropertyState; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; @@ -55,7 +55,7 @@ /** * Underlying {@code Root} of this {@code Tree} instance */ - private final RootImpl root; + private final AbstractMutableRoot root; /** * Parent of this tree. Null for the root. @@ -65,13 +65,13 @@ /** Pointer into the list of pending moves */ private Move pendingMoves; - MutableTree(RootImpl root, NodeBuilder builder, Move pendingMoves) { + MutableTree(AbstractMutableRoot root, NodeBuilder builder, Move pendingMoves) { super("", builder); this.root = checkNotNull(root); this.pendingMoves = checkNotNull(pendingMoves); } - private MutableTree(RootImpl root, MutableTree parent, String name, Move pendingMoves) { + private MutableTree(AbstractMutableRoot root, MutableTree parent, String name, Move pendingMoves) { super(name, parent.nodeBuilder.getChildNode(name)); this.root = checkNotNull(root); this.parent = checkNotNull(parent); @@ -331,7 +331,7 @@ * @return a {@link Tree} instance for the child at {@code path}. */ @CheckForNull - MutableTree getTree(@Nonnull String path) { + protected AbstractTree getTree(@Nonnull String path) { checkArgument(isAbsolute(checkNotNull(path))); MutableTree child = this; for (String name : elements(path)) { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeInitializer.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeInitializer.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeInitializer.java (working copy) @@ -22,7 +22,8 @@ import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.Type; -import org.apache.jackrabbit.oak.core.RootImpl; +import org.apache.jackrabbit.oak.core.AbstractMutableRoot; +import org.apache.jackrabbit.oak.core.SystemMutableRoot; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore; import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.spi.commit.EmptyHook; @@ -67,7 +68,7 @@ } try { - new PrivilegeDefinitionWriter(new RootImpl(store)).writeBuiltInDefinitions(); + new PrivilegeDefinitionWriter(new SystemMutableRoot(store)).writeBuiltInDefinitions(); } catch (RepositoryException e) { log.error("Failed to register built-in privileges", e); throw new RuntimeException(e); Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java (working copy) @@ -16,7 +16,10 @@ */ package org.apache.jackrabbit.oak.core; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute; +import static org.apache.jackrabbit.oak.commons.PathUtils.elements; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -125,10 +128,10 @@ } public static ImmutableTree createFromRoot(@Nonnull Root root, @Nonnull TreeTypeProvider typeProvider) { - if (root instanceof RootImpl) { - return new ImmutableTree(((RootImpl) root).getBaseState(), typeProvider); + if (root instanceof AbstractMutableRoot) { + return new ImmutableTree(((AbstractMutableRoot) root).getBaseState(), typeProvider); } else if (root instanceof ImmutableRoot) { - return ((ImmutableRoot) root).getTree("/"); + return (ImmutableTree) root.getTree("/"); } else { throw new IllegalArgumentException("Unsupported Root implementation: " + root.getClass()); } @@ -287,4 +290,14 @@ } } + @Override + protected AbstractTree getTree(String path) { + checkArgument(isAbsolute(checkNotNull(path))); + AbstractTree child = this; + for (String name : elements(path)) { + child = (AbstractTree) child.getChild(name); + } + return child; + } + } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (working copy) @@ -1,524 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.jackrabbit.oak.core; - -import java.io.IOException; -import java.io.InputStream; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nonnull; -import javax.security.auth.Subject; - -import org.apache.jackrabbit.oak.Oak; -import org.apache.jackrabbit.oak.api.Blob; -import org.apache.jackrabbit.oak.api.BlobFactory; -import org.apache.jackrabbit.oak.api.CommitFailedException; -import org.apache.jackrabbit.oak.api.ContentSession; -import org.apache.jackrabbit.oak.api.QueryEngine; -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.plugins.index.diffindex.UUIDDiffIndexProviderWrapper; -import org.apache.jackrabbit.oak.query.QueryEngineImpl; -import org.apache.jackrabbit.oak.security.authentication.SystemSubject; -import org.apache.jackrabbit.oak.spi.commit.CommitHook; -import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider; -import org.apache.jackrabbit.oak.spi.commit.CompositeHook; -import org.apache.jackrabbit.oak.spi.commit.EditorHook; -import org.apache.jackrabbit.oak.spi.commit.EmptyHook; -import org.apache.jackrabbit.oak.spi.commit.PostCommitHook; -import org.apache.jackrabbit.oak.spi.commit.PostValidationHook; -import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider; -import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; -import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; -import org.apache.jackrabbit.oak.spi.security.Context; -import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider; -import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration; -import org.apache.jackrabbit.oak.spi.security.SecurityProvider; -import org.apache.jackrabbit.oak.spi.security.authorization.AccessControlConfiguration; -import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; -import org.apache.jackrabbit.oak.spi.state.NodeBuilder; -import org.apache.jackrabbit.oak.spi.state.NodeState; -import org.apache.jackrabbit.oak.spi.state.NodeStore; -import org.apache.jackrabbit.oak.spi.state.NodeStoreBranch; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.commons.PathUtils.getName; -import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath; - -public class RootImpl implements Root { - - /** - * Number of {@link #updated} calls for which changes are kept in memory. - */ - private static final int PURGE_LIMIT = Integer.getInteger("oak.root.purgeLimit", 1000); - - /** - * The underlying store to which this root belongs - */ - private final NodeStore store; - - private final CommitHook hook; - - private final PostCommitHook postHook; - - private final String workspaceName; - - private final Subject subject; - - private final SecurityProvider securityProvider; - - private final QueryIndexProvider indexProvider; - - /** - * Current root {@code Tree} - */ - private final MutableTree rootTree; - - /** - * Current branch this root operates on - */ - private NodeStoreBranch branch; - - /** - * Unsecured builder for the root tree - */ - private NodeBuilder builder; - - /** - * Sentinel for the next move operation to take place on the this root - */ - private Move lastMove = new Move(); - - /** - * Number of {@link #updated} occurred so since the last - * purge. - */ - private long modCount; - - private PermissionProvider permissionProvider; - - /** - * New instance bases on a given {@link NodeStore} and a workspace - * - * @param store node store - * @param hook the commit hook - * @param workspaceName name of the workspace - * @param subject the subject. - * @param securityProvider the security configuration. - * @param indexProvider the query index provider. - */ - public RootImpl(NodeStore store, - CommitHook hook, - PostCommitHook postHook, - String workspaceName, - Subject subject, - SecurityProvider securityProvider, - QueryIndexProvider indexProvider) { - this.store = checkNotNull(store); - this.hook = checkNotNull(hook); - this.postHook = postHook; - this.workspaceName = checkNotNull(workspaceName); - this.subject = checkNotNull(subject); - this.securityProvider = checkNotNull(securityProvider); - this.indexProvider = indexProvider; - - branch = this.store.branch(); - NodeState root = branch.getHead(); - builder = root.builder(); - NodeBuilder secureBuilder = new SecureNodeBuilder(builder, getRootContext(root)); - rootTree = new MutableTree(this, secureBuilder, lastMove); - } - - // TODO: review if these constructors really make sense and cannot be replaced. - public RootImpl(NodeStore store) { - this(store, EmptyHook.INSTANCE); - } - - public RootImpl(NodeStore store, CommitHook hook) { - // FIXME: define proper default or pass workspace name with the constructor - this(store, hook, PostCommitHook.EMPTY, Oak.DEFAULT_WORKSPACE_NAME, SystemSubject.INSTANCE, - new OpenSecurityProvider(), new CompositeQueryIndexProvider()); - } - - /** - * Called whenever a method on this instance or on any {@code Tree} instance - * obtained from this {@code Root} is called. This default implementation - * does nothing. Sub classes may override this method and throw an exception - * indicating that this {@code Root} instance is not live anymore (e.g. because - * the session has been logged out already). - */ - protected void checkLive() { - - } - - protected String getWorkspaceName() { - return workspaceName; - } - - //---------------------------------------------------------------< Root >--- - - @Override - public ContentSession getContentSession() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean move(String sourcePath, String destPath) { - if (PathUtils.isAncestor(sourcePath, destPath)) { - return false; - } - - checkLive(); - MutableTree destParent = rootTree.getTree(getParentPath(destPath)); - if (!destParent.exists()) { - return false; - } - purgePendingChanges(); - boolean success = branch.move(sourcePath, destPath); - reset(); - if (success) { - getTree(getParentPath(sourcePath)).updateChildOrder(); - getTree(getParentPath(destPath)).updateChildOrder(); - lastMove = lastMove.setMove(sourcePath, destParent, getName(destPath)); - updated(); - } - return success; - } - - @Override - public boolean copy(String sourcePath, String destPath) { - checkLive(); - purgePendingChanges(); - boolean success = branch.copy(sourcePath, destPath); - reset(); - if (success) { - getTree(getParentPath(destPath)).updateChildOrder(); - updated(); - } - return success; - } - - @Override - public MutableTree getTree(@Nonnull String path) { - checkLive(); - return rootTree.getTree(path); - } - - @Override - public void rebase() { - checkLive(); - if (!store.getRoot().equals(getBaseState())) { - purgePendingChanges(); - branch.rebase(); - reset(); - if (permissionProvider != null) { - permissionProvider.refresh(); - } - } - } - - @Override - public final void refresh() { - checkLive(); - branch = store.branch(); - reset(); - modCount = 0; - if (permissionProvider != null) { - permissionProvider.refresh(); - } - } - - @Override - public void commit() throws CommitFailedException { - checkLive(); - rebase(); - purgePendingChanges(); - CommitFailedException exception = Subject.doAs( - getCommitSubject(), new PrivilegedAction() { - @Override - public CommitFailedException run() { - try { - NodeState base = branch.getBase(); - NodeState newHead = branch.merge(getCommitHook(), postHook); - return null; - } catch (CommitFailedException e) { - return e; - } - } - }); - if (exception != null) { - throw exception; - } - refresh(); - } - - /** - * Combine the globally defined commit hook(s) with the hooks and - * validators defined by the various security related configurations. - * - * @return A commit hook combining repository global commit hook(s) with - * the pluggable hooks defined with the security modules. - */ - private CommitHook getCommitHook() { - List commitHooks = new ArrayList(); - commitHooks.add(hook); - List postValidationHooks = new ArrayList(); - for (SecurityConfiguration sc : securityProvider.getConfigurations()) { - for (CommitHook ch : sc.getCommitHooks(workspaceName)) { - if (ch instanceof PostValidationHook) { - postValidationHooks.add(ch); - } else if (ch != EmptyHook.INSTANCE) { - commitHooks.add(ch); - } - } - List validators = sc.getValidators(workspaceName); - if (!validators.isEmpty()) { - commitHooks.add(new EditorHook(CompositeEditorProvider.compose(validators))); - } - } - commitHooks.addAll(postValidationHooks); - return CompositeHook.compose(commitHooks); - } - - /** - * TODO: review again once the permission validation is completed. - * Build a read only subject for the {@link #commit()} call that makes the - * principals and the permission provider available to the commit hooks. - * - * @return a new read only subject. - */ - private Subject getCommitSubject() { - return new Subject(true, subject.getPrincipals(), - Collections.singleton(getPermissionProvider()), Collections.emptySet()); - } - - @Override - public boolean hasPendingChanges() { - checkLive(); - return modCount > 0; - } - - @Override - public QueryEngine getQueryEngine() { - checkLive(); - return new QueryEngineImpl(getIndexProvider()) { - - @Override - protected NodeState getRootState() { - return RootImpl.this.getRootState(); - } - - @Override - protected Tree getRootTree() { - return rootTree; - } - - }; - } - - @Nonnull - @Override - public BlobFactory getBlobFactory() { - checkLive(); - - return new BlobFactory() { - @Override - public Blob createBlob(InputStream inputStream) throws IOException { - checkLive(); - return store.createBlob(inputStream); - } - }; - } - - @Nonnull - private QueryIndexProvider getIndexProvider() { - if (hasPendingChanges()) { - return new UUIDDiffIndexProviderWrapper(indexProvider, - getBaseState(), getRootState()); - } - return indexProvider; - } - - //-----------------------------------------------------------< internal >--- - - /** - * Returns the node state from which the current branch was created. - * - * @return base node state - */ - @Nonnull - NodeState getBaseState() { - return branch.getBase(); - } - - /** - * Returns the secure view of the base state from which the current branch was creates. - * - * @return secure base node state - */ - NodeState getSecureBase() { - NodeState root = branch.getBase(); - return new SecureNodeState(root, getRootContext(root)); - } - - // TODO better way to determine purge limit. See OAK-175 - void updated() { - if (++modCount % PURGE_LIMIT == 0) { - purgePendingChanges(); - } - } - - //------------------------------------------------------------< private >--- - - /** - * Root node state of the tree including all transient changes at the time of - * this call. - * - * @return root node state - */ - @Nonnull - private NodeState getRootState() { - return builder.getNodeState(); - } - - /** - * Secure view of the root node state of the tree including all transient changes - * at the time of this call. - * - * @return secure root node state - */ - @Nonnull - private NodeState getSecureRootState() { - return rootTree.getNodeState(); - } - - @Nonnull - private SecurityContext getRootContext(NodeState root) { - return new SecurityContext(root, getPermissionProvider(), getAcContext()); - } - - @Nonnull - private PermissionProvider getPermissionProvider() { - if (permissionProvider == null) { - permissionProvider = createPermissionProvider(); - } - return permissionProvider; - } - - /** - * Purge all pending changes to the underlying {@link NodeStoreBranch}. - */ - private void purgePendingChanges() { - branch.setRoot(getRootState()); - reset(); - } - - /** - * Reset the root builder to the branch's current root state - */ - private void reset() { - NodeState root = branch.getHead(); - builder.reset(root); - } - - @Nonnull - private PermissionProvider createPermissionProvider() { - return getAcConfig().getPermissionProvider(this, subject.getPrincipals()); - } - - @Nonnull - private Context getAcContext() { - return getAcConfig().getContext(); - } - - @Nonnull - private AccessControlConfiguration getAcConfig() { - return securityProvider.getConfiguration(AccessControlConfiguration.class); - } - - //---------------------------------------------------------< MoveRecord >--- - - /** - * Instances of this class record move operations which took place on this root. - * They form a singly linked list where each move instance points to the next one. - * The last entry in the list is always an empty slot to be filled in by calling - * {@code setMove()}. This fills the slot with the source and destination of the move - * and links this move to the next one which will be the new empty slot. - *

- * Moves can be applied to {@code MutableTree} instances by calling {@code apply()}, - * which will execute all moves in the list on the passed tree instance - */ - class Move { - - /** - * source path - */ - private String source; - - /** - * Parent tree of the destination - */ - private MutableTree destParent; - - /** - * Name at the destination - */ - private String destName; - - /** - * Pointer to the next move. {@code null} if this is the last, empty slot - */ - private Move next; - - /** - * Set this move to the given source and destination. Creates a new empty slot, - * sets this as the next move and returns it. - */ - Move setMove(String source, MutableTree destParent, String destName) { - this.source = source; - this.destParent = destParent; - this.destName = destName; - return next = new Move(); - } - - /** - * Apply this and all subsequent moves to the passed tree instance. - */ - Move apply(MutableTree tree) { - Move move = this; - while (move.next != null) { - if (move.source.equals(tree.getPathInternal())) { - tree.moveTo(move.destParent, move.destName); - } - move = move.next; - } - return move; - } - - @Override - public String toString() { - return source == null - ? "NIL" - : '>' + source + ':' + PathUtils.concat(destParent.getPathInternal(), destName); - } - } -} Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserInitializer.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserInitializer.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserInitializer.java (working copy) @@ -16,24 +16,19 @@ */ package org.apache.jackrabbit.oak.security.user; -import java.security.Principal; -import java.util.Set; + import javax.annotation.Nonnull; import javax.jcr.RepositoryException; - import com.google.common.base.Strings; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.oak.api.AuthInfo; import org.apache.jackrabbit.oak.api.CommitFailedException; -import org.apache.jackrabbit.oak.api.ContentSession; import org.apache.jackrabbit.oak.api.Root; -import org.apache.jackrabbit.oak.core.RootImpl; +import org.apache.jackrabbit.oak.core.SystemMutableRoot; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.index.IndexConstants; import org.apache.jackrabbit.oak.plugins.index.IndexUtils; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore; -import org.apache.jackrabbit.oak.security.authentication.SystemSubject; import org.apache.jackrabbit.oak.spi.commit.CommitHook; import org.apache.jackrabbit.oak.spi.commit.EmptyHook; import org.apache.jackrabbit.oak.spi.commit.PostCommitHook; @@ -44,14 +39,13 @@ import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; import org.apache.jackrabbit.oak.spi.state.NodeState; -import org.apache.jackrabbit.oak.spi.state.NodeStore; import org.apache.jackrabbit.oak.spi.state.NodeStoreBranch; import org.apache.jackrabbit.oak.util.NodeUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; + /** * Creates initial set of users to be present in a given workspace. This @@ -105,7 +99,7 @@ throw new RuntimeException(e); } - Root root = new SystemRootImpl(store, commitHook, workspaceName, securityProvider, indexProvider); + Root root = new SystemMutableRoot(store, commitHook, workspaceName, securityProvider, indexProvider); UserConfiguration userConfiguration = securityProvider.getConfiguration(UserConfiguration.class); UserManager userManager = userConfiguration.getUserManager(root, NamePathMapper.DEFAULT); @@ -150,70 +144,4 @@ return store.getRoot(); } - //--------------------------------------------------------< inner class >--- - - private class SystemRootImpl extends RootImpl { - - private SystemRootImpl(NodeStore store, CommitHook hook, - String workspaceName, - SecurityProvider securityProvider, - QueryIndexProvider indexProvider) { - super(store, hook, PostCommitHook.EMPTY, workspaceName, SystemSubject.INSTANCE, - securityProvider, indexProvider); - } - - @Override - public ContentSession getContentSession() { - return new ContentSession() { - - private volatile boolean live = true; - - private void checkLive() { - checkState(live, "This session has been closed"); - } - - @Override - public void close() { - live = false; - } - - @Override - public String getWorkspaceName() { - return SystemRootImpl.this.getWorkspaceName(); - } - - @Override - public Root getLatestRoot() { - checkLive(); - return SystemRootImpl.this; - } - - @Override - public AuthInfo getAuthInfo() { - return new AuthInfo() { - - @Override - public String getUserID() { - return null; - } - - @Override - public Set getPrincipals() { - return SystemSubject.INSTANCE.getPrincipals(); - } - - @Override - public String[] getAttributeNames() { - return new String[]{}; - } - - @Override - public Object getAttribute(String attributeName) { - return null; - } - }; - } - }; - } - } } Index: oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java (revision 1506849) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java (working copy) @@ -502,7 +502,7 @@ } private CompiledPermissionImpl createPermissions(Set principals) { - ImmutableTree permissionsTree = new ImmutableRoot(root, TreeTypeProvider.EMPTY).getTree(PERMISSIONS_STORE_PATH); + ImmutableTree permissionsTree = (ImmutableTree) new ImmutableRoot(root, TreeTypeProvider.EMPTY).getTree(PERMISSIONS_STORE_PATH); return new CompiledPermissionImpl(principals, permissionsTree, pbp, rp, ImmutableSet.copyOf(DEFAULT_READ_PATHS)); } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java (revision 0) @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.core; + +import javax.annotation.Nonnull; +import org.apache.jackrabbit.oak.api.QueryEngine; +import org.apache.jackrabbit.oak.api.Root; +import org.apache.jackrabbit.oak.api.Tree; +import org.apache.jackrabbit.oak.query.QueryEngineImpl; +import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; +import org.apache.jackrabbit.oak.spi.state.NodeState; + +public abstract class AbstractRoot implements Root { + + protected AbstractTree rootTree; + + @Nonnull + @Override + public AbstractTree getTree(String path) { + checkLive(); + return rootTree.getTree(path); + } + + @Nonnull + @Override + public QueryEngine getQueryEngine() { + checkLive(); + return new QueryEngineImpl(getIndexProvider()) { + + @Override + protected NodeState getRootState() { + return AbstractRoot.this.getRootState(); + } + + @Override + protected Tree getRootTree() { + return rootTree; + } + + }; + } + + protected abstract void checkLive(); + + @Nonnull + protected abstract QueryIndexProvider getIndexProvider(); + + @Nonnull + protected abstract NodeState getRootState(); + +} Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java (working copy) @@ -21,7 +21,8 @@ import org.apache.felix.scr.annotations.Service; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.Type; -import org.apache.jackrabbit.oak.core.RootImpl; +import org.apache.jackrabbit.oak.core.AbstractMutableRoot; +import org.apache.jackrabbit.oak.core.SystemMutableRoot; import org.apache.jackrabbit.oak.plugins.index.IndexConstants; import org.apache.jackrabbit.oak.plugins.index.IndexUtils; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore; @@ -81,7 +82,7 @@ } catch (CommitFailedException e) { throw new RuntimeException(e); } - BuiltInNodeTypes.register(new RootImpl(store, new EditorHook(new RegistrationEditorProvider()))); + BuiltInNodeTypes.register(new SystemMutableRoot(store, new EditorHook(new RegistrationEditorProvider()))); return store.getRoot(); } Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java (revision 1506849) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java (working copy) @@ -216,7 +216,7 @@ } private static ImmutableTree getTree(NodeState beforeState, String path) { - return new ImmutableRoot(beforeState).getTree(path); + return (ImmutableTree) new ImmutableRoot(beforeState).getTree(path); } //------------------------------------------------------------< private >--- Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (revision 1506849) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (working copy) @@ -17,32 +17,26 @@ * under the License. */ package org.apache.jackrabbit.oak.core; - + import static com.google.common.base.Preconditions.checkArgument; -import static org.apache.jackrabbit.oak.commons.PathUtils.elements; - import javax.annotation.Nonnull; - import org.apache.jackrabbit.oak.api.BlobFactory; import org.apache.jackrabbit.oak.api.ContentSession; -import org.apache.jackrabbit.oak.api.QueryEngine; 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.plugins.index.property.PropertyIndexProvider; -import org.apache.jackrabbit.oak.query.QueryEngineImpl; +import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; import org.apache.jackrabbit.oak.spi.state.NodeState; +import static org.apache.jackrabbit.oak.commons.PathUtils.elements; + /** * Simple implementation of the Root interface that only supports simple read * operations based on the {@code NodeState} (or {@code ImmutableTree}) * passed to the constructor. This root implementation provides a query engine * with index support limited to the {@link PropertyIndexProvider}. */ -public final class ImmutableRoot implements Root { - - private final ImmutableTree rootTree; - +public final class ImmutableRoot extends AbstractRoot { + public ImmutableRoot(@Nonnull NodeState rootState) { this(new ImmutableTree(rootState)); } @@ -52,23 +46,25 @@ } public ImmutableRoot(@Nonnull ImmutableTree rootTree) { - checkArgument(rootTree.isRoot()); - this.rootTree = rootTree; + checkArgument(rootTree.isRoot()); + this.rootTree = rootTree; } - - //---------------------------------------------------------------< Root >--- - - - @Nonnull + + /*@Nonnull @Override public ImmutableTree getTree(@Nonnull String path) { - checkArgument(PathUtils.isAbsolute(path)); - ImmutableTree child = rootTree; + //checkArgument(PathUtils.isAbsolute(path)); + ImmutableTree child = (ImmutableTree )rootTree; for (String name : elements(path)) { child = child.getChild(name); } + System.out.println(child.getName()); return child; - } + }*/ + + + //---------------------------------------------------------------< Root >--- + @Override public boolean move(String sourcePath, String destPath) { @@ -99,23 +95,7 @@ public boolean hasPendingChanges() { return false; } - - @Nonnull - @Override - public QueryEngine getQueryEngine() { - return new QueryEngineImpl(new PropertyIndexProvider()) { - @Override - protected NodeState getRootState() { - return rootTree.state; - } - - @Override - protected Tree getRootTree() { - return rootTree; - } - }; - } - + @Nonnull @Override public BlobFactory getBlobFactory() { @@ -128,4 +108,19 @@ throw new UnsupportedOperationException(); } + @Override + protected void checkLive() { + //DO NOTHING + } + + @Override + protected QueryIndexProvider getIndexProvider() { + return new PropertyIndexProvider(); + } + + @Override + protected NodeState getRootState() { + return ((ImmutableTree)rootTree).state; + } + }