Return-Path: X-Original-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Delivered-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5318091C7 for ; Wed, 16 May 2012 00:27:40 +0000 (UTC) Received: (qmail 45132 invoked by uid 500); 16 May 2012 00:27:40 -0000 Delivered-To: apmail-jackrabbit-oak-commits-archive@jackrabbit.apache.org Received: (qmail 45110 invoked by uid 500); 16 May 2012 00:27:40 -0000 Mailing-List: contact oak-commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: oak-commits@jackrabbit.apache.org Delivered-To: mailing list oak-commits@jackrabbit.apache.org Received: (qmail 45095 invoked by uid 99); 16 May 2012 00:27:40 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 May 2012 00:27:40 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 May 2012 00:27:34 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 26839238897A; Wed, 16 May 2012 00:27:13 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1338959 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: kernel/ plugins/memory/ spi/state/ Date: Wed, 16 May 2012 00:27:12 -0000 To: oak-commits@jackrabbit.apache.org From: jukka@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120516002713.26839238897A@eris.apache.org> Author: jukka Date: Wed May 16 00:27:12 2012 New Revision: 1338959 URL: http://svn.apache.org/viewvc?rev=1338959&view=rev Log: OAK-68: Extension point for commit validation Flesh out the MemoryNodeStore as an example of how the commit hook could/should work Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeState.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueFactoryImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueFactoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueFactoryImpl.java?rev=1338959&r1=1338958&r2=1338959&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueFactoryImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueFactoryImpl.java Wed May 16 00:27:12 2012 @@ -28,7 +28,7 @@ import java.math.BigDecimal; * {@code CoreValueFactoryImpl} is the default implementation of the * {@code CoreValueFactory} interface. */ -class CoreValueFactoryImpl implements CoreValueFactory { +public class CoreValueFactoryImpl implements CoreValueFactory { private final MicroKernel mk; Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java?rev=1338959&r1=1338958&r2=1338959&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java Wed May 16 00:27:12 2012 @@ -25,7 +25,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -class PropertyStateImpl implements PropertyState { +public class PropertyStateImpl implements PropertyState { private final String name; private final CoreValue value; Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java?rev=1338959&r1=1338958&r2=1338959&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java Wed May 16 00:27:12 2012 @@ -18,9 +18,11 @@ */ package org.apache.jackrabbit.oak.plugins.memory; +import java.util.Iterator; import java.util.Map; import org.apache.jackrabbit.oak.spi.state.AbstractChildNodeEntry; +import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.NodeState; /** @@ -28,6 +30,36 @@ import org.apache.jackrabbit.oak.spi.sta */ public class MemoryChildNodeEntry extends AbstractChildNodeEntry { + public static Iterable iterable( + final Map map) { + return new Iterable() { + @Override + public Iterator iterator() { + return MemoryChildNodeEntry.iterator(map); + } + }; + } + + public static Iterator iterator( + Map map) { + final Iterator> iterator = + map.entrySet().iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + @Override + public ChildNodeEntry next() { + return new MemoryChildNodeEntry(iterator.next()); + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + private final String name; private final NodeState node; Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java?rev=1338959&r1=1338958&r2=1338959&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java Wed May 16 00:27:12 2012 @@ -16,20 +16,18 @@ */ package org.apache.jackrabbit.oak.plugins.memory; +import java.util.Collections; +import java.util.Map; + import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.spi.state.AbstractNodeState; import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.NodeState; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; - /** * Basic in-memory node state implementation. */ -public class MemoryNodeState extends AbstractNodeState - implements Iterable { +public class MemoryNodeState extends AbstractNodeState { /** * Singleton instance of an empty node state, i.e. one with neither @@ -87,27 +85,7 @@ public class MemoryNodeState extends Abs @Override public Iterable getChildNodeEntries() { - return this; - } - - @Override - public Iterator iterator() { - final Iterator> iterator = - nodes.entrySet().iterator(); - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - @Override - public ChildNodeEntry next() { - return new MemoryChildNodeEntry(iterator.next()); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; + return MemoryChildNodeEntry.iterable(nodes); } } Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java?rev=1338959&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java Wed May 16 00:27:12 2012 @@ -0,0 +1,110 @@ +/* + * 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.plugins.memory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.jackrabbit.oak.api.CoreValue; +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.kernel.PropertyStateImpl; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStateBuilder; + +/** + * Basic in-memory node state builder. + */ +public class MemoryNodeStateBuilder implements NodeStateBuilder { + + private final NodeState base; + + private final Map properties = + new HashMap(); + + private final Map nodes = + new HashMap(); + + public MemoryNodeStateBuilder(NodeState base) { + assert base != null; + this.base = base; + } + + @Override + public NodeState getNodeState() { + return new ModifiedNodeState( + base, + new HashMap(properties), + new HashMap(nodes)); + } + + @Override + public NodeStateBuilder getChildBuilder(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public NodeStateBuilder addNode(String name, NodeState nodeState) { + nodes.put(name, nodeState); + return this; + } + + @Override + public NodeStateBuilder addNode(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean removeNode(String name) { + nodes.put(name, null); + return false; + } + + @Override + public PropertyState setProperty(String name, CoreValue value) { + PropertyState property = new PropertyStateImpl(name, value); + properties.put(name, property); + return property; + } + + @Override + public PropertyState setProperty(String name, List values) { + PropertyState property = new PropertyStateImpl(name, values); + properties.put(name, property); + return property; + } + + @Override + public void removeProperty(String name) { + properties.put(name, null); + } + + @Override + public boolean moveTo(NodeStateBuilder destParent, String destName) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean copyTo(NodeStateBuilder destParent, String destName) { + // TODO Auto-generated method stub + return false; + } + +} Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java?rev=1338959&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java Wed May 16 00:27:12 2012 @@ -0,0 +1,71 @@ +/* + * 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.plugins.memory; + +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.jackrabbit.oak.api.CommitFailedException; +import org.apache.jackrabbit.oak.api.CoreValueFactory; +import org.apache.jackrabbit.oak.kernel.CoreValueFactoryImpl; +import org.apache.jackrabbit.oak.spi.commit.CommitHook; +import org.apache.jackrabbit.oak.spi.state.AbstractNodeStore; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStateBuilder; + +/** + * Basic in-memory node state implementation. + */ +public class MemoryNodeStore extends AbstractNodeStore { + + private final AtomicReference root = + new AtomicReference(MemoryNodeState.EMPTY_NODE); + + private final CommitHook commitHook; + + public MemoryNodeStore(CommitHook commitHook) { + this.commitHook = commitHook; + } + + @Override + public NodeState getRoot() { + return root.get(); + } + + @Override + public NodeStateBuilder getBuilder(NodeState base) { + return new MemoryNodeStateBuilder(base); + } + + @Override + public CoreValueFactory getValueFactory() { + return new CoreValueFactoryImpl(null); // FIXME + } + + @Override + public void setRoot(NodeState newRoot) throws CommitFailedException { + while (true) { + NodeState oldRoot = getRoot(); + NodeState setRoot = commitHook.beforeCommit(this, oldRoot, newRoot); + if (root.compareAndSet(oldRoot, setRoot)) { + return; + } else { + // TODO: try to rebase the changes in newRoot + } + } + } + +} Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java?rev=1338959&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java Wed May 16 00:27:12 2012 @@ -0,0 +1,185 @@ +/* + * 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.plugins.memory; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.collections.IteratorUtils; +import org.apache.commons.collections.Predicate; +import org.apache.commons.collections.PredicateUtils; +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.ProxyNodeState; + +public class ModifiedNodeState extends ProxyNodeState { + + private final Map properties; + + private final Map nodes; + + public ModifiedNodeState( + NodeState base, + Map properties, + Map nodes) { + super(base); + this.properties = properties; + this.nodes = nodes; + } + + @Override + public PropertyState getProperty(String name) { + if (properties.containsKey(name)) { + return properties.get(name); + } else { + return super.getProperty(name); + } + } + + @Override + public long getPropertyCount() { + long count = super.getPropertyCount(); + for (Map.Entry entry : properties.entrySet()) { + if (super.getProperty(entry.getKey()) != null) { + if (entry.getValue() == null) { + count--; + } + } else { + if (entry.getValue() != null) { + count++; + } + } + } + return count; + } + + @Override + public Iterable getProperties() { + if (properties.isEmpty()) { + return super.getProperties(); // shortcut + } + final Iterable unmodified = + super.getProperties(); + final Iterable modified = + properties.values(); + return new Iterable() { + @Override @SuppressWarnings("unchecked") + public Iterator iterator() { + Iterator a = IteratorUtils.filteredIterator( + unmodified.iterator(), + new UnmodifiedPropertyPredicate()); + Iterator b = IteratorUtils.filteredIterator( + modified.iterator(), + PredicateUtils.notNullPredicate()); + return IteratorUtils.chainedIterator(a, b); + } + }; + } + + @Override + public NodeState getChildNode(String name) { + if (nodes.containsKey(name)) { + return nodes.get(name); + } else { + return super.getChildNode(name); + } + } + + @Override + public long getChildNodeCount() { + long count = super.getPropertyCount(); + for (Map.Entry entry : nodes.entrySet()) { + if (super.getChildNode(entry.getKey()) != null) { + if (entry.getValue() == null) { + count--; + } + } else { + if (entry.getValue() != null) { + count++; + } + } + } + return count; + } + + @Override + public Iterable getChildNodeEntries() { + if (nodes.isEmpty()) { + return super.getChildNodeEntries(); // shortcut + } + final Iterable unmodified = + super.getChildNodeEntries(); + final Iterable modified = + MemoryChildNodeEntry.iterable(nodes); + return new Iterable() { + @Override @SuppressWarnings("unchecked") + public Iterator iterator() { + Iterator a = IteratorUtils.filteredIterator( + unmodified.iterator(), + new UnmodifiedChildNodePredicate()); + Iterator b = IteratorUtils.filteredIterator( + modified.iterator(), + new UndeletedChildNodePredicate()); + return IteratorUtils.chainedIterator(a, b); + } + }; + } + + private class UnmodifiedPropertyPredicate implements Predicate { + + @Override + public boolean evaluate(Object object) { + if (object instanceof PropertyState) { + PropertyState property = ((PropertyState) object); + return !properties.containsKey(property.getName()); + } else { + return false; + } + } + + } + + private class UnmodifiedChildNodePredicate implements Predicate { + + @Override + public boolean evaluate(Object object) { + if (object instanceof ChildNodeEntry) { + ChildNodeEntry entry = ((ChildNodeEntry) object); + return !nodes.containsKey(entry.getName()); + } else { + return false; + } + } + + } + + private class UndeletedChildNodePredicate implements Predicate { + + @Override + public boolean evaluate(Object object) { + if (object instanceof ChildNodeEntry) { + ChildNodeEntry entry = ((ChildNodeEntry) object); + return entry.getNodeState() != null; + } else { + return false; + } + } + + } + +} Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeState.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeState.java?rev=1338959&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeState.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeState.java Wed May 16 00:27:12 2012 @@ -0,0 +1,92 @@ +/* + * 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.spi.state; + +import org.apache.jackrabbit.oak.api.PropertyState; + +/** + * Proxy node state that delegates all method calls to another instance. + * Mostly useful as a base class for more complicated decorator functionality. + */ +public class ProxyNodeState implements NodeState { + + protected NodeState delegate; + + protected ProxyNodeState(NodeState delegate) { + assert delegate != null; + this.delegate = delegate; + } + + @Override + public PropertyState getProperty(String name) { + return delegate.getProperty(name); + } + + @Override + public long getPropertyCount() { + return delegate.getPropertyCount(); + } + + @Override + public Iterable getProperties() { + return delegate.getProperties(); + } + + @Override + public NodeState getChildNode(String name) { + return delegate.getChildNode(name); + } + + @Override + public long getChildNodeCount() { + return delegate.getChildNodeCount(); + } + + @Override + public Iterable getChildNodeEntries() { + return delegate.getChildNodeEntries(); + } + + //------------------------------------------------------------< Object >-- + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean equals(Object that) { + // Note the careful ordering of calls here. We need to undo the + // proxying, but still allow a possible subclass to implement + // custom equality checks if it wants to. Thus we don't simply + // look inside another ProxyNodeState instance, but rather let + // it handle the equality check against our delegate instance. + // If it's just another call to this same method, the resulting + // final equality check will be that.delegate.equals(delegate). + if (that instanceof ProxyNodeState) { + return that.equals(delegate); + } else { + return delegate.equals(that); + } + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + +}