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 2012/10/19 14:27:09 UTC
svn commit: r1400068 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/api/
main/java/org/apache/jackrabbit/oak/core/
test/java/org/apache/jackrabbit/oak/api/
Author: mduerig
Date: Fri Oct 19 12:27:09 2012
New Revision: 1400068
URL: http://svn.apache.org/viewvc?rev=1400068&view=rev
Log:
OAK-387: Clarify behavior/state of Root and Tree after calling ContentSession#close()
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java?rev=1400068&r1=1400067&r2=1400068&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java Fri Oct 19 12:27:09 2012
@@ -26,6 +26,10 @@ import javax.annotation.Nonnull;
* <p>
* The data returned by this class filtered for the access rights that are set
* in the {@link ContentSession} that created this object.
+ * <p>
+ * All root instances created by a content session become invalid after the
+ * content session is closed. Any method called on an invalid root instance
+ * will throw an {@code InvalidStateException}.
*/
public interface Root {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java?rev=1400068&r1=1400067&r2=1400068&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java Fri Oct 19 12:27:09 2012
@@ -51,6 +51,10 @@ import javax.annotation.Nonnull;
* The data returned by this class and intermediary objects such as
* {@link PropertyState} is filtered for the access rights that are set in the
* {@link ContentSession} that created the {@link Root} of this object.
+ * <p>
+ * All tree instances created in the context of a content session become invalid
+ * after the content session is closed. Any method called on an invalid tree instance
+ * will throw an {@code InvalidStateException}.
*/
public interface Tree {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java?rev=1400068&r1=1400067&r2=1400068&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java Fri Oct 19 12:27:09 2012
@@ -35,6 +35,8 @@ import org.apache.jackrabbit.oak.spi.sta
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkState;
+
/**
* {@code MicroKernel}-based implementation of the {@link ContentSession} interface.
*/
@@ -49,6 +51,8 @@ class ContentSessionImpl implements Cont
private final ConflictHandler conflictHandler;
private final QueryIndexProvider indexProvider;
+ private volatile boolean live = true;
+
public ContentSessionImpl(LoginContext loginContext,
AccessControlProvider accProvider, String workspaceName,
NodeStore store, ConflictHandler conflictHandler,
@@ -61,10 +65,15 @@ class ContentSessionImpl implements Cont
this.indexProvider = indexProvider;
}
+ private void checkLive() {
+ checkState(live, "This session has been closed");
+ }
+
//-----------------------------------------------------< ContentSession >---
@Nonnull
@Override
public AuthInfo getAuthInfo() {
+ checkLive();
Set<AuthInfo> infoSet = loginContext.getSubject().getPublicCredentials(AuthInfo.class);
if (infoSet.isEmpty()) {
return AuthInfo.EMPTY;
@@ -81,7 +90,13 @@ class ContentSessionImpl implements Cont
@Nonnull
@Override
public Root getLatestRoot() {
- RootImpl root = new RootImpl(store, workspaceName, loginContext.getSubject(), accProvider, indexProvider);
+ checkLive();
+ RootImpl root = new RootImpl(store, workspaceName, loginContext.getSubject(), accProvider, indexProvider) {
+ @Override
+ protected void checkLive() {
+ ContentSessionImpl.this.checkLive();
+ }
+ };
if (conflictHandler != null) {
root.setConflictHandler(conflictHandler);
}
@@ -90,6 +105,7 @@ class ContentSessionImpl implements Cont
@Override
public Blob createBlob(InputStream inputStream) throws IOException {
+ checkLive();
return store.createBlob(inputStream);
}
@@ -98,6 +114,7 @@ class ContentSessionImpl implements Cont
public synchronized void close() throws IOException {
try {
loginContext.logout();
+ live = false;
} catch (LoginException e) {
log.error("Error during logout.", e);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java?rev=1400068&r1=1400067&r2=1400068&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java Fri Oct 19 12:27:09 2012
@@ -140,9 +140,14 @@ public class RootImpl implements Root {
return conflictHandler;
}
+ protected void checkLive() {
+
+ }
+
//---------------------------------------------------------------< Root >---
@Override
public boolean move(String sourcePath, String destPath) {
+ checkLive();
TreeImpl source = rootTree.getTree(sourcePath);
if (source == null) {
return false;
@@ -164,23 +169,27 @@ public class RootImpl implements Root {
@Override
public boolean copy(String sourcePath, String destPath) {
+ checkLive();
purgePendingChanges();
return branch.copy(sourcePath, destPath);
}
@Override
public TreeImpl getTree(String path) {
+ checkLive();
return rootTree.getTree(path);
}
@Override
public TreeLocation getLocation(String path) {
+ checkLive();
checkArgument(path.startsWith("/"));
return rootTree.getLocation().getChild(path.substring(1));
}
@Override
public void rebase() {
+ checkLive();
if (!store.getRoot().equals(rootTree.getBaseState())) {
purgePendingChanges();
NodeState base = getBaseState();
@@ -192,12 +201,14 @@ public class RootImpl implements Root {
@Override
public final void refresh() {
+ checkLive();
branch = store.branch();
rootTree = TreeImpl.createRoot(this);
}
@Override
public void commit() throws CommitFailedException {
+ checkLive();
rebase();
purgePendingChanges();
CommitFailedException exception = Subject.doAs(
@@ -236,11 +247,13 @@ public class RootImpl implements Root {
@Override
public boolean hasPendingChanges() {
+ checkLive();
return !getBaseState().equals(rootTree.getNodeState());
}
@Nonnull
public ChangeExtractor getChangeExtractor() {
+ checkLive();
return new ChangeExtractor() {
private NodeState baseLine = store.getRoot();
@@ -255,6 +268,7 @@ public class RootImpl implements Root {
@Override
public SessionQueryEngine getQueryEngine() {
+ checkLive();
return new SessionQueryEngineImpl(store, indexProvider);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java?rev=1400068&r1=1400067&r2=1400068&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java Fri Oct 19 12:27:09 2012
@@ -99,16 +99,19 @@ public class TreeImpl implements Tree, P
@Override
public String getName() {
+ root.checkLive();
return name;
}
@Override
public boolean isRoot() {
+ root.checkLive();
return parent == null;
}
@Override
public String getPath() {
+ root.checkLive();
if (isRoot()) {
// shortcut
return "/";
@@ -121,6 +124,7 @@ public class TreeImpl implements Tree, P
@Override
public Tree getParent() {
+ root.checkLive();
if (parent != null && canRead(parent)) {
return parent;
} else {
@@ -130,6 +134,7 @@ public class TreeImpl implements Tree, P
@Override
public PropertyState getProperty(String name) {
+ root.checkLive();
PropertyState property = internalGetProperty(name);
if (canRead(property)) {
return property;
@@ -141,6 +146,7 @@ public class TreeImpl implements Tree, P
@Override
public Status getPropertyStatus(String name) {
// TODO: see OAK-212
+ root.checkLive();
Status nodeStatus = getStatus();
if (nodeStatus == Status.NEW) {
return (hasProperty(name)) ? Status.NEW : null;
@@ -170,16 +176,19 @@ public class TreeImpl implements Tree, P
@Override
public boolean hasProperty(String name) {
+ root.checkLive();
return getProperty(name) != null;
}
@Override
public long getPropertyCount() {
+ root.checkLive();
return Iterables.size(getProperties());
}
@Override
public Iterable<? extends PropertyState> getProperties() {
+ root.checkLive();
return Iterables.filter(getNodeBuilder().getProperties(),
new Predicate<PropertyState>() {
@Override
@@ -191,6 +200,7 @@ public class TreeImpl implements Tree, P
@Override
public TreeImpl getChild(String name) {
+ root.checkLive();
TreeImpl child = internalGetChild(name);
if (child != null && canRead(child)) {
return child;
@@ -201,6 +211,7 @@ public class TreeImpl implements Tree, P
@Override
public Status getStatus() {
+ root.checkLive();
if (isRemoved()) {
return Status.REMOVED;
}
@@ -223,17 +234,20 @@ public class TreeImpl implements Tree, P
@Override
public boolean hasChild(String name) {
+ root.checkLive();
return getChild(name) != null;
}
@Override
public long getChildrenCount() {
// TODO: make sure cnt respects access control
+ root.checkLive();
return getNodeBuilder().getChildNodeCount();
}
@Override
public Iterable<Tree> getChildren() {
+ root.checkLive();
Iterable<String> childNames;
if (hasOrderableChildren()) {
childNames = getOrderedChildNames();
@@ -263,6 +277,7 @@ public class TreeImpl implements Tree, P
@Override
public Tree addChild(String name) {
+ root.checkLive();
if (!hasChild(name)) {
getNodeBuilder().child(name);
if (hasOrderableChildren()) {
@@ -281,6 +296,7 @@ public class TreeImpl implements Tree, P
@Override
public boolean remove() {
+ root.checkLive();
if (isRemoved()) {
throw new IllegalStateException("Cannot remove removed tree");
}
@@ -306,6 +322,7 @@ public class TreeImpl implements Tree, P
@Override
public boolean orderBefore(final String name) {
+ root.checkLive();
if (isRoot()) {
// root does not have siblings
return false;
@@ -352,6 +369,7 @@ public class TreeImpl implements Tree, P
@Override
public void setProperty(PropertyState property) {
+ root.checkLive();
NodeBuilder builder = getNodeBuilder();
builder.setProperty(property);
root.purge();
@@ -359,6 +377,7 @@ public class TreeImpl implements Tree, P
@Override
public <T> void setProperty(String name, T value) {
+ root.checkLive();
NodeBuilder builder = getNodeBuilder();
builder.setProperty(name, value);
root.purge();
@@ -366,6 +385,7 @@ public class TreeImpl implements Tree, P
@Override
public <T> void setProperty(String name, T value, Type<T> type) {
+ root.checkLive();
NodeBuilder builder = getNodeBuilder();
builder.setProperty(name, value, type);
root.purge();
@@ -373,6 +393,7 @@ public class TreeImpl implements Tree, P
@Override
public void removeProperty(String name) {
+ root.checkLive();
NodeBuilder builder = getNodeBuilder();
builder.removeProperty(name);
root.purge();
@@ -380,6 +401,7 @@ public class TreeImpl implements Tree, P
@Override
public TreeLocation getLocation() {
+ root.checkLive();
return new NodeLocation(this);
}
@@ -502,8 +524,8 @@ public class TreeImpl implements Tree, P
}
/**
- * @return <code>true</code> if this tree has orderable children;
- * <code>false</code> otherwise.
+ * @return {@code true} if this tree has orderable children;
+ * {@code false} otherwise.
*/
private boolean hasOrderableChildren() {
return internalGetProperty(OAK_CHILD_ORDER) != null;
@@ -521,7 +543,7 @@ public class TreeImpl implements Tree, P
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
- PropertyState childOrder = internalGetProperty(OAK_CHILD_ORDER);
+ final PropertyState childOrder = internalGetProperty(OAK_CHILD_ORDER);
int index = 0;
@Override
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java?rev=1400068&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java Fri Oct 19 12:27:09 2012
@@ -0,0 +1,73 @@
+/*
+ * 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.api;
+
+import java.io.IOException;
+
+import javax.jcr.NoSuchWorkspaceException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictValidator;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ContentSessionTest {
+
+ private ContentRepository repository;
+
+ @Before
+ public void setUp() {
+ repository = new Oak()
+ .with(new ConflictValidator())
+ .with(new AnnotatingConflictHandler())
+ .createContentRepository();
+ }
+
+ @After
+ public void tearDown() {
+ repository = null;
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void throwOnClosedSession() throws LoginException, NoSuchWorkspaceException, IOException {
+ ContentSession session = repository.login(null, null);
+ session.close();
+ session.getLatestRoot();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void throwOnClosedRoot() throws LoginException, NoSuchWorkspaceException, IOException {
+ ContentSession session = repository.login(null, null);
+ Root root = session.getLatestRoot();
+ session.close();
+ root.getTree("/");
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void throwOnClosedTree() throws LoginException, NoSuchWorkspaceException, IOException {
+ ContentSession session = repository.login(null, null);
+ Root root = session.getLatestRoot();
+ Tree tree = root.getTree("/");
+ session.close();
+ tree.getChild("any");
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/ContentSessionTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL