You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-dev@jackrabbit.apache.org by md...@apache.org on 2012/03/15 14:33:33 UTC
svn commit: r1300973 [1/3] - in /jackrabbit/oak/trunk/oak-jcr: ./
src/main/java/org/apache/jackrabbit/oak/jcr/
src/main/java/org/apache/jackrabbit/oak/jcr/configuration/
src/main/java/org/apache/jackrabbit/oak/jcr/json/
src/main/java/org/apache/jackrab...
Author: mduerig
Date: Thu Mar 15 13:33:32 2012
New Revision: 1300973
URL: http://svn.apache.org/viewvc?rev=1300973&view=rev
Log:
OAK-5: JCR bindings for Oak
pass CRUDTest
Added:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/GlobalContext.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionFactory.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionFactory.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/OakRepositoryConfiguration.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/RepositoryConfiguration.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/DefaultJsonTokenizer.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/FullJsonParser.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonHandler.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonParser.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonTokenizer.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonValue.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsopHandler.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsopParser.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/LevelOrderJsonParser.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/ParseException.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/Token.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/UnescapingJsonTokenizer.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/Authenticator.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/AuthenticatorImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/CredentialsInfo.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeLog.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/EmptyNodeState.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/NodeStateProvider.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/PersistentNodeState.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/PropertyStateImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/TransientNodeState.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/TransientSpace.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Function0.java
- copied, changed from r1299739, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Function0.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Function1.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Function1.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/ItemNameMatcher.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Iterators.java
- copied, changed from r1299781, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Iterators.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/PagedIterator.java
- copied, changed from r1299746, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/PagedIterator.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Path.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Predicate.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicate.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/Unchecked.java
- copied, changed from r1299739, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Unchecked.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/util/ValueConverter.java
- copied, changed from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ValueConverter.java
Modified:
jackrabbit/oak/trunk/oak-jcr/pom.xml
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/OakRepositoryFactory.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Thu Mar 15 13:33:32 2012
@@ -42,6 +42,11 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-core</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>2.4.0</version>
</dependency>
@@ -52,6 +57,11 @@
</dependency>
<dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
Copied: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/GlobalContext.java (from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/GlobalContext.java?p2=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/GlobalContext.java&p1=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java&r1=1299713&r2=1300973&rev=1300973&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/GlobalContext.java Thu Mar 15 13:33:32 2012
@@ -17,15 +17,15 @@
* under the License.
*/
-package org.apache.jackrabbit;
+package org.apache.jackrabbit.oak.jcr;
import org.apache.jackrabbit.commons.SimpleValueFactory;
-import org.apache.jackrabbit.configuration.RepositoryConfiguration;
import org.apache.jackrabbit.mk.MicroKernelFactory;
import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.security.Authenticator;
-import org.apache.jackrabbit.security.AuthenticatorImpl;
-import org.apache.jackrabbit.utils.Unchecked;
+import org.apache.jackrabbit.oak.jcr.configuration.RepositoryConfiguration;
+import org.apache.jackrabbit.oak.jcr.security.Authenticator;
+import org.apache.jackrabbit.oak.jcr.security.AuthenticatorImpl;
+import org.apache.jackrabbit.oak.jcr.util.Unchecked;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
@@ -36,16 +36,17 @@ import java.util.Map;
import static java.text.MessageFormat.format;
/**
- * Poor Java's dependency injection
+ * Poor man's dependency injection
+ * todo: replace by some more sophisticated mechanism
*/
public class GlobalContext {
private final Map<Class<?>, Object> instances = new HashMap<Class<?>, Object>();
public GlobalContext(RepositoryConfiguration repositoryConfiguration) throws RepositoryException {
- put(ValueFactory.class, new SimpleValueFactory());
+ put(ValueFactory.class, new SimpleValueFactory());
put(RepositoryConfiguration.class, repositoryConfiguration);
put(MicroKernel.class, MicroKernelFactory.getInstance(repositoryConfiguration.getMicrokernelUrl()));
- put(Repository.class, RepositoryImpl.create(this));
+ put(Repository.class, new RepositoryImpl(this));
put(Authenticator.class, AuthenticatorImpl.INSTANCE);
put(SessionFactory.class, SessionImpl.FACTORY);
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java Thu Mar 15 13:33:32 2012
@@ -16,6 +16,9 @@
*/
package org.apache.jackrabbit.oak.jcr;
+import org.apache.jackrabbit.oak.jcr.SessionImpl.Context;
+import org.apache.jackrabbit.oak.jcr.state.TransientNodeState;
+import org.apache.jackrabbit.oak.jcr.util.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,13 +42,16 @@ import javax.jcr.version.VersionExceptio
* <code>ItemImpl</code>...
*/
abstract class ItemImpl implements Item {
+ protected final Context sessionContext;
/**
* logger instance
*/
private static final Logger log = LoggerFactory.getLogger(ItemImpl.class);
- private final SessionImpl session = null;
+ protected ItemImpl(Context sessionContext) {
+ this.sessionContext = sessionContext;
+ }
@Override
public String getPath() throws RepositoryException {
@@ -79,8 +85,7 @@ abstract class ItemImpl implements Item
@Override
public Session getSession() throws RepositoryException {
- // TODO
- return null;
+ return sessionContext.getSession();
}
@Override
@@ -150,6 +155,11 @@ abstract class ItemImpl implements Item
}
//--------------------------------------------------------------------------
+
+ SessionImpl getOakSession() {
+ return sessionContext.getSession();
+ }
+
/**
* Performs a sanity check on this item and the associated session.
*
@@ -157,7 +167,7 @@ abstract class ItemImpl implements Item
*/
void checkStatus() throws RepositoryException {
// check session status
- session.checkIsAlive();
+ getOakSession().checkIsAlive();
// TODO: validate item state.
}
@@ -169,7 +179,7 @@ abstract class ItemImpl implements Item
* @throws RepositoryException
*/
void checkSessionHasPendingChanges() throws RepositoryException {
- session.checkHasPendingChanges();
+ getOakSession().checkHasPendingChanges();
}
/**
@@ -179,6 +189,11 @@ abstract class ItemImpl implements Item
* @throws RepositoryException
*/
ValueFactory getValueFactory() throws RepositoryException {
- return session.getValueFactory();
+ return getOakSession().getValueFactory();
+ }
+
+ protected static TransientNodeState getNodeState(Context sessionContext, Path path) {
+ return sessionContext.getNodeStateProvider().getNodeState(path);
}
+
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java Thu Mar 15 13:33:32 2012
@@ -16,7 +16,21 @@
*/
package org.apache.jackrabbit.oak.jcr;
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
+import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter;
+import org.apache.jackrabbit.oak.jcr.SessionImpl.Context;
+import org.apache.jackrabbit.oak.jcr.json.JsonValue;
+import org.apache.jackrabbit.oak.jcr.json.JsonValue.JsonAtom;
+import org.apache.jackrabbit.oak.jcr.state.PropertyStateImpl;
+import org.apache.jackrabbit.oak.jcr.state.TransientNodeState;
+import org.apache.jackrabbit.oak.jcr.util.Function1;
+import org.apache.jackrabbit.oak.jcr.util.ItemNameMatcher;
+import org.apache.jackrabbit.oak.jcr.util.Iterators;
import org.apache.jackrabbit.oak.jcr.util.LogUtil;
+import org.apache.jackrabbit.oak.jcr.util.Path;
+import org.apache.jackrabbit.oak.jcr.util.Predicate;
+import org.apache.jackrabbit.oak.jcr.util.ValueConverter;
+import org.apache.jackrabbit.oak.model.PropertyState;
import org.apache.jackrabbit.value.ValueHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,6 +69,9 @@ import javax.jcr.version.VersionManager;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
+import java.util.Iterator;
+
+import static org.apache.jackrabbit.oak.jcr.util.Iterators.filter;
/**
* <code>NodeImpl</code>...
@@ -66,7 +83,76 @@ public class NodeImpl extends ItemImpl i
*/
private static final Logger log = LoggerFactory.getLogger(NodeImpl.class);
+ private final TransientNodeState state;
+
+ static boolean exist(Context sessionContext, Path path) {
+ return getNodeState(sessionContext, path) != null;
+ }
+
+ static Node create(Context sessionContext, Path path) throws PathNotFoundException {
+ TransientNodeState state = getNodeState(sessionContext, path);
+ if (state == null) {
+ throw new PathNotFoundException(path.toJcrPath());
+ }
+
+ return new NodeImpl(sessionContext, state);
+ }
+
+ static Node create(Context sessionContext, TransientNodeState state) {
+ return new NodeImpl(sessionContext, state);
+ }
+
+ private NodeImpl(Context sessionContext, TransientNodeState state) {
+ super(sessionContext);
+ this.state = state;
+ }
+
//---------------------------------------------------------------< Item >---
+
+ @Override
+ public String getPath() throws RepositoryException {
+ return path().toJcrPath();
+ }
+
+ @Override
+ public String getName() throws RepositoryException {
+ return state.getName();
+ }
+
+ @Override
+ public Item getAncestor(int depth) throws RepositoryException {
+ Path parent = path().getAncestor(depth);
+ if (parent == null) {
+ throw new ItemNotFoundException(path().toJcrPath() + "has no ancestor of depth " + depth);
+ }
+
+ return create(sessionContext, parent);
+ }
+
+ @Override
+ public Node getParent() throws RepositoryException {
+ if (state.isRoot()) {
+ throw new ItemNotFoundException("Root has no parent");
+ }
+
+ return create(sessionContext, path().getParent());
+ }
+
+ @Override
+ public int getDepth() throws RepositoryException {
+ return path().getDepth();
+ }
+
+ @Override
+ public boolean isNew() {
+ return state.isNew();
+ }
+
+ @Override
+ public boolean isModified() {
+ return state.isModified();
+ }
+
/**
* @see javax.jcr.Item#isNode()
*/
@@ -90,15 +176,24 @@ public class NodeImpl extends ItemImpl i
*/
@Override
public Node addNode(String relPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException {
- return addNode(relPath, null);
+ checkStatus();
+ Path newPath = path().concat(relPath);
+ TransientNodeState parentState = getNodeState(sessionContext, newPath.getParent());
+ TransientNodeState childState = parentState.addNode(newPath.getName());
+ return create(sessionContext, childState);
}
@Override
public Node addNode(String relPath, String primaryNodeTypeName) throws ItemExistsException, PathNotFoundException, NoSuchNodeTypeException, LockException, VersionException, ConstraintViolationException, RepositoryException {
checkStatus();
+ Node childNode = addNode(relPath);
+ childNode.setPrimaryType(primaryNodeTypeName);
+ return childNode;
+ }
- // TODO
- return null;
+ @Override
+ public void remove() throws RepositoryException {
+ state.remove();
}
@Override
@@ -127,8 +222,8 @@ public class NodeImpl extends ItemImpl i
public Property setProperty(String name, Value value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
checkStatus();
- // TODO
- return null;
+ state.setProperty(name, ValueConverter.toJsonValue(value));
+ return getProperty(name);
}
/**
@@ -149,8 +244,8 @@ public class NodeImpl extends ItemImpl i
public Property setProperty(String name, Value[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
checkStatus();
- // TODO
- return null;
+ state.setProperty(name, ValueConverter.toJsonValue(values));
+ return getProperty(name);
}
/**
@@ -265,62 +360,88 @@ public class NodeImpl extends ItemImpl i
@Override
public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
- // TODO
- return null;
+ return create(sessionContext, path().concat(relPath));
}
@Override
public NodeIterator getNodes() throws RepositoryException {
checkStatus();
- // TODO
- return null;
+ Iterator<TransientNodeState> childNodeStates = state.getNodes();
+ return new NodeIteratorAdapter(nodeIterator(childNodeStates));
}
@Override
- public NodeIterator getNodes(String namePattern) throws RepositoryException {
+ public NodeIterator getNodes(final String namePattern) throws RepositoryException {
checkStatus();
- // TODO
- return null;
+ Iterator<TransientNodeState> childNodeStates = filter(state.getNodes(),
+ new Predicate<TransientNodeState>() {
+ @Override
+ public boolean evaluate(TransientNodeState state) {
+ return ItemNameMatcher.matches(state.getName(), namePattern);
+ }
+ });
+
+ return new NodeIteratorAdapter(nodeIterator(childNodeStates));
}
@Override
- public NodeIterator getNodes(String[] nameGlobs) throws RepositoryException {
+ public NodeIterator getNodes(final String[] nameGlobs) throws RepositoryException {
checkStatus();
- // TODO
- return null;
+ Iterator<TransientNodeState> childNodeStates = filter(state.getNodes(),
+ new Predicate<TransientNodeState>() {
+ @Override
+ public boolean evaluate(TransientNodeState state) {
+ return ItemNameMatcher.matches(state.getName(), nameGlobs);
+ }
+ });
+
+ return new NodeIteratorAdapter(nodeIterator(childNodeStates));
}
@Override
public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
checkStatus();
- // TODO
- return null;
+ return PropertyImpl.create(sessionContext, path().concat(relPath));
}
@Override
public PropertyIterator getProperties() throws RepositoryException {
checkStatus();
- // TODO
- return null;
+ Iterator<PropertyState> properties = state.getProperties();
+ return new PropertyIteratorAdapter(propertyIterator(properties));
}
@Override
- public PropertyIterator getProperties(String namePattern) throws RepositoryException {
+ public PropertyIterator getProperties(final String namePattern) throws RepositoryException {
checkStatus();
- // TODO
- return null;
+ Iterator<PropertyState> properties = filter(state.getProperties(),
+ new Predicate<PropertyState>() {
+ @Override
+ public boolean evaluate(PropertyState entry) {
+ return ItemNameMatcher.matches(entry.getName(), namePattern);
+ }
+ });
+
+ return new PropertyIteratorAdapter(propertyIterator(properties));
}
@Override
- public PropertyIterator getProperties(String[] nameGlobs) throws RepositoryException {
- // TODO
- return null;
+ public PropertyIterator getProperties(final String[] nameGlobs) throws RepositoryException {
+ Iterator<PropertyState> propertyNames = filter(state.getProperties(),
+ new Predicate<PropertyState>() {
+ @Override
+ public boolean evaluate(PropertyState entry) {
+ return ItemNameMatcher.matches(entry.getName(), nameGlobs);
+ }
+ });
+
+ return new PropertyIteratorAdapter(propertyIterator(propertyNames));
}
/**
@@ -400,32 +521,28 @@ public class NodeImpl extends ItemImpl i
public boolean hasNode(String relPath) throws RepositoryException {
checkStatus();
- // TODO
- return false;
+ return exist(sessionContext, path().concat(relPath));
}
@Override
public boolean hasProperty(String relPath) throws RepositoryException {
checkStatus();
- // TODO
- return false;
+ return PropertyImpl.exist(sessionContext, path().concat(relPath));
}
@Override
public boolean hasNodes() throws RepositoryException {
checkStatus();
- // TODO
- return false;
+ return state.hasNodes();
}
@Override
public boolean hasProperties() throws RepositoryException {
checkStatus();
- // TODO
- return false;
+ return state.hasProperties();
}
@Override
@@ -456,22 +573,25 @@ public class NodeImpl extends ItemImpl i
public void setPrimaryType(String nodeTypeName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
checkStatus();
- // TODO
-
+ state.setProperty("jcr:primaryType", JsonAtom.string(nodeTypeName));
}
@Override
public void addMixin(String mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
checkStatus();
- // TODO
+ JsonValue mixins = state.getPropertyValue("jcr:mixinTypes");
+ mixins.asArray().add(JsonAtom.string(mixinName));
+ state.setProperty("jcr:mixinTypes", mixins);
}
@Override
public void removeMixin(String mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
checkStatus();
- // TODO
+ JsonValue mixins = state.getPropertyValue("jcr:mixinTypes");
+ mixins.asArray().remove(JsonAtom.string(mixinName));
+ state.setProperty("jcr:mixinTypes", mixins);
}
@Override
@@ -696,4 +816,27 @@ public class NodeImpl extends ItemImpl i
private VersionManager getVersionManager() throws RepositoryException {
return getSession().getWorkspace().getVersionManager();
}
+
+ private Path path() {
+ return state.getPath();
+ }
+
+ private Iterator<Node> nodeIterator(Iterator<TransientNodeState> childNodeStates) {
+ return Iterators.map(childNodeStates, new Function1<TransientNodeState, Node>() {
+ @Override
+ public Node apply(TransientNodeState state) {
+ return NodeImpl.create(sessionContext, state);
+ }
+ });
+ }
+
+ private Iterator<Property> propertyIterator(Iterator<PropertyState> properties) {
+ return Iterators.map(properties, new Function1<PropertyState, Property>() {
+ @Override
+ public Property apply(PropertyState state) { // fixme don't cast
+ JsonValue value = ((PropertyStateImpl) state).getValue();
+ return PropertyImpl.create(sessionContext, NodeImpl.this.state, state.getName(), value);
+ }
+ });
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/OakRepositoryFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/OakRepositoryFactory.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/OakRepositoryFactory.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/OakRepositoryFactory.java Thu Mar 15 13:33:32 2012
@@ -16,14 +16,15 @@
*/
package org.apache.jackrabbit.oak.jcr;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Map;
+import org.apache.jackrabbit.oak.jcr.configuration.OakRepositoryConfiguration;
+import org.apache.jackrabbit.oak.jcr.configuration.RepositoryConfiguration;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.RepositoryFactory;
-import javax.jcr.UnsupportedRepositoryOperationException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Map;
@SuppressWarnings("rawtypes")
public class OakRepositoryFactory implements RepositoryFactory {
@@ -47,10 +48,12 @@ public class OakRepositoryFactory implem
return null;
}
- private Repository getRepository(URI uri, Map parameters)
+ private static Repository getRepository(URI uri, Map parameters)
throws RepositoryException {
- throw new UnsupportedRepositoryOperationException(
- "jcr-oak repository URIs are not yet supported: " + uri);
+
+ parameters.put(RepositoryConfiguration.MICROKERNEL_URL, "simple:target/repository-test/repository");
+ GlobalContext context = new GlobalContext(OakRepositoryConfiguration.create(parameters));
+ return context.getInstance(Repository.class);
}
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java Thu Mar 15 13:33:32 2012
@@ -16,12 +16,18 @@
*/
package org.apache.jackrabbit.oak.jcr;
+import org.apache.jackrabbit.oak.jcr.SessionImpl.Context;
+import org.apache.jackrabbit.oak.jcr.json.JsonValue;
+import org.apache.jackrabbit.oak.jcr.state.TransientNodeState;
import org.apache.jackrabbit.oak.jcr.util.LogUtil;
+import org.apache.jackrabbit.oak.jcr.util.Path;
+import org.apache.jackrabbit.oak.jcr.util.ValueConverter;
import org.apache.jackrabbit.value.ValueHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Binary;
+import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
@@ -30,6 +36,7 @@ import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
+import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
@@ -49,6 +56,38 @@ public class PropertyImpl extends ItemIm
*/
private static final Logger log = LoggerFactory.getLogger(PropertyImpl.class);
+ private final TransientNodeState parentState;
+ private final String name;
+ private final JsonValue value;
+
+ static Property create(Context sessionContext, Path path) throws PathNotFoundException,
+ ItemNotFoundException {
+
+ TransientNodeState parentState = getNodeState(sessionContext, path.getParent());
+ if (parentState == null) {
+ throw new PathNotFoundException(path.toJcrPath());
+ }
+
+ String name = path.getName();
+ JsonValue value = parentState.getPropertyValue(name);
+ return new PropertyImpl(sessionContext, parentState, name, value);
+ }
+
+ static Property create(Context sessionContext, TransientNodeState parentState, String name, JsonValue value) {
+ return new PropertyImpl(sessionContext, parentState, name, value);
+ }
+
+ public static boolean exist(Context sessionContext, Path path) {
+ TransientNodeState parentState = getNodeState(sessionContext, path.getParent());
+ return parentState != null && parentState.hasProperty(path.getName());
+ }
+
+ private PropertyImpl(Context sessionContext, TransientNodeState parentState, String name, JsonValue value) {
+ super(sessionContext);
+ this.parentState = parentState;
+ this.name = name;
+ this.value = value;
+ }
//---------------------------------------------------------------< Item >---
/**
@@ -59,6 +98,16 @@ public class PropertyImpl extends ItemIm
return false;
}
+ @Override
+ public String getPath() throws RepositoryException {
+ return parentState.getPath().concat(name).toJcrPath();
+ }
+
+ @Override
+ public String getName() throws RepositoryException {
+ return name;
+ }
+
/**
* @see javax.jcr.Item#accept(javax.jcr.ItemVisitor)
*/
@@ -68,6 +117,42 @@ public class PropertyImpl extends ItemIm
visitor.visit(this);
}
+ @Override
+ public Item getAncestor(int depth) throws RepositoryException {
+ if (depth == getDepth() - 1) {
+ return getParent();
+ }
+ else {
+ return getParent().getAncestor(depth);
+ }
+ }
+
+ @Override
+ public Node getParent() throws RepositoryException {
+ return NodeImpl.create(sessionContext, parentState);
+ }
+
+ @Override
+ public int getDepth() throws RepositoryException {
+ return parentState.getPath().getDepth() + 1;
+ }
+
+ @Override
+ public boolean isNew() {
+ return parentState.isPropertyNew(name);
+ }
+
+ @Override
+ public boolean isModified() {
+ return parentState.isPropertyModified(name);
+ }
+
+ @Override
+ public void remove() throws RepositoryException {
+ parentState.removeProperty(name);
+ }
+
+
//-----------------------------------------------------------< Property >---
/**
* @see Property#setValue(Value)
@@ -256,8 +341,12 @@ public class PropertyImpl extends ItemIm
throw new ValueFormatException(LogUtil.safeGetJCRPath(this) + " is multi-valued.");
}
- // TODO
- return null;
+ if (!value.isAtom()) {
+ throw new ValueFormatException(value.toJson());
+ }
+
+ ValueFactory valueFactory = sessionContext.getValueFactory();
+ return ValueConverter.toValue(valueFactory, value.asAtom());
}
@Override
@@ -267,8 +356,12 @@ public class PropertyImpl extends ItemIm
throw new ValueFormatException(LogUtil.safeGetJCRPath(this) + " is not multi-valued.");
}
- // TODO
- return new Value[0];
+ if (!value.isArray()) {
+ throw new ValueFormatException(value.toJson());
+ }
+
+ ValueFactory valueFactory = sessionContext.getValueFactory();
+ return ValueConverter.toValue(valueFactory, value.asArray());
}
/**
@@ -422,14 +515,23 @@ public class PropertyImpl extends ItemIm
@Override
public int getType() throws RepositoryException {
- // TODO
- return 0;
+ if (isMultiple()) {
+ Value[] values = getValues();
+ if (values.length == 0) {
+ return PropertyType.UNDEFINED;
+ }
+ else {
+ return values[0].getType();
+ }
+ }
+ else {
+ return getValue().getType();
+ }
}
@Override
public boolean isMultiple() throws RepositoryException {
- // TODO
- return false;
+ return value.isArray();
}
//------------------------------------------------------------< private >---
@@ -464,7 +566,12 @@ public class PropertyImpl extends ItemIm
throw new IllegalArgumentException("Property type of a value cannot be undefined (" + LogUtil.safeGetJCRPath(this) + ").");
}
- // TODO -> set value on the property state and remember operation.
+ if (value == null) {
+ remove();
+ }
+ else {
+ parentState.setProperty(name, ValueConverter.toJsonValue(value));
+ }
}
/**
@@ -479,7 +586,12 @@ public class PropertyImpl extends ItemIm
throw new IllegalArgumentException("Property type of a value cannot be undefined (" + LogUtil.safeGetJCRPath(this) + ").");
}
- // TODO -> internal set values to the property and remember operation
+ if (value == null) {
+ remove();
+ }
+ else {
+ parentState.setProperty(name, ValueConverter.toJsonValue(values));
+ }
}
/**
@@ -497,4 +609,5 @@ public class PropertyImpl extends ItemIm
return value.getString().length();
}
}
+
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java Thu Mar 15 13:33:32 2012
@@ -39,8 +39,14 @@ public class RepositoryImpl extends Abst
*/
private static final Logger log = LoggerFactory.getLogger(RepositoryImpl.class);
+ private final GlobalContext context;
+
private Map<String, Value[]> descriptors;
+ public RepositoryImpl(GlobalContext context) {
+ this.context = context;
+ }
+
//---------------------------------------------------------< Repository >---
/**
* @see javax.jcr.Repository#getDescriptorKeys()
@@ -102,8 +108,8 @@ public class RepositoryImpl extends Abst
*/
@Override
public Session login(Credentials credentials, String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
- // TODO -> SPI
- return null;
+ SessionFactory sessionFactory = context.getInstance(SessionFactory.class);
+ return sessionFactory.createSession(context, credentials, workspaceName);
}
//------------------------------------------------------------< private >---
Copied: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java (from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java?p2=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java&p1=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java&r1=1299713&r2=1300973&rev=1300973&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java Thu Mar 15 13:33:32 2012
@@ -17,11 +17,11 @@
* under the License.
*/
-package org.apache.jackrabbit;
+package org.apache.jackrabbit.oak.jcr;
import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.security.CredentialsInfo;
-import org.apache.jackrabbit.state.NodeStateProvider;
+import org.apache.jackrabbit.oak.jcr.security.CredentialsInfo;
+import org.apache.jackrabbit.oak.jcr.state.NodeStateProvider;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
Copied: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionFactory.java (from r1299713, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionFactory.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionFactory.java?p2=jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionFactory.java&p1=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionFactory.java&r1=1299713&r2=1300973&rev=1300973&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionFactory.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionFactory.java Thu Mar 15 13:33:32 2012
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.jackrabbit;
+package org.apache.jackrabbit.oak.jcr;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java Thu Mar 15 13:33:32 2012
@@ -17,6 +17,13 @@
package org.apache.jackrabbit.oak.jcr;
import org.apache.jackrabbit.commons.AbstractSession;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.oak.jcr.security.Authenticator;
+import org.apache.jackrabbit.oak.jcr.security.CredentialsInfo;
+import org.apache.jackrabbit.oak.jcr.state.NodeStateProvider;
+import org.apache.jackrabbit.oak.jcr.state.TransientNodeState;
+import org.apache.jackrabbit.oak.jcr.state.TransientSpace;
+import org.apache.jackrabbit.oak.jcr.util.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
@@ -27,6 +34,7 @@ import javax.jcr.InvalidItemStateExcepti
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.ReferentialIntegrityException;
@@ -54,34 +62,122 @@ public class SessionImpl extends Abstrac
*/
private static final Logger log = LoggerFactory.getLogger(SessionImpl.class);
- private final Workspace workspace = null;
- private final ValueFactory valueFactory = null;
+ private final Workspace workspace;
+ private final GlobalContext globalContext;
+ private final CredentialsInfo credentialsInfo;
+ private final String workspaceName;
+ private final MicroKernel microKernel;
+ private final TransientSpace transientSpace;
+ private final NodeStateProvider nodeStateProvider;
+
+ private String revision;
+ private boolean isAlive = true;
+
+ public static final SessionFactory FACTORY = new SessionFactory() {
+ @Override
+ public Session createSession(GlobalContext globalContext, Credentials credentials,
+ String workspaceName) throws LoginException, NoSuchWorkspaceException {
+
+ Authenticator authenticator = globalContext.getInstance(Authenticator.class);
+ CredentialsInfo credentialsInfo = authenticator.authenticate(credentials);
+ MicroKernel microKernel = globalContext.getInstance(MicroKernel.class);
+ String revision = microKernel.getHeadRevision();
+
+ if (workspaceName == null) {
+ workspaceName = WorkspaceImpl.DEFAULT_WORKSPACE_NAME;
+ }
+
+ if (!microKernel.nodeExists('/' + workspaceName, revision)) {
+ if (WorkspaceImpl.DEFAULT_WORKSPACE_NAME.equals(workspaceName)) {
+ WorkspaceImpl.createWorkspace(microKernel, workspaceName);
+ revision = microKernel.getHeadRevision();
+ }
+ else {
+ throw new NoSuchWorkspaceException(workspaceName);
+ }
+ }
+
+ return new SessionImpl(globalContext, credentialsInfo, workspaceName, revision);
+ }
+ };
+
+ public interface Context extends SessionContext<SessionImpl>{}
+
+ private final Context sessionContext = new Context() {
+ @Override
+ public SessionImpl getSession() {
+ return SessionImpl.this;
+ }
+
+ @Override
+ public GlobalContext getGlobalContext() {
+ return globalContext;
+ }
+
+ @Override
+ public CredentialsInfo getCredentialsInfo() {
+ return credentialsInfo;
+ }
+
+ @Override
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ @Override
+ public MicroKernel getMicrokernel() {
+ return microKernel;
+ }
+
+ @Override
+ public String getRevision() {
+ return revision;
+ }
+
+ @Override
+ public ValueFactory getValueFactory() {
+ return globalContext.getInstance(ValueFactory.class);
+ }
+
+ @Override
+ public NodeStateProvider getNodeStateProvider() {
+ return nodeStateProvider;
+ }
+ };
+
+ private SessionImpl(GlobalContext globalContext, CredentialsInfo credentialsInfo, String workspaceName,
+ String revision) {
+
+ this.globalContext = globalContext;
+ this.credentialsInfo = credentialsInfo;
+ this.workspaceName = workspaceName;
+ this.revision = revision;
+ workspace = new WorkspaceImpl(sessionContext);
+ microKernel = globalContext.getInstance(MicroKernel.class);
+ transientSpace = new TransientSpace(workspaceName, microKernel, revision);
+ nodeStateProvider = new NodeStateProvider(sessionContext, transientSpace);
+ }
- private boolean isAlive;
//------------------------------------------------------------< Session >---
@Override
public Repository getRepository() {
- // TODO
- return null;
+ return globalContext.getInstance(Repository.class);
}
@Override
public String getUserID() {
- // TODO
- return null;
+ return credentialsInfo.getUserId();
}
@Override
public String[] getAttributeNames() {
- // TODO
- return new String[0];
+ return credentialsInfo.getAttributeNames();
}
@Override
public Object getAttribute(String name) {
- // TODO
- return null;
+ return credentialsInfo.getAttribute(name);
}
@Override
@@ -92,9 +188,7 @@ public class SessionImpl extends Abstrac
@Override
public Node getRootNode() throws RepositoryException {
checkIsAlive();
-
- // TODO
- return null;
+ return NodeImpl.create(sessionContext, Path.create(workspaceName));
}
@Override
@@ -116,39 +210,39 @@ public class SessionImpl extends Abstrac
@Override
public void move(String srcAbsPath, String destAbsPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException {
checkIsAlive();
+ Path sourcePath = Path.create(workspaceName, srcAbsPath);
+ TransientNodeState sourceParent = nodeStateProvider.getNodeState(sourcePath.getParent());
+ if (sourceParent == null) {
+ throw new PathNotFoundException(srcAbsPath);
+ }
- // TODO
-
+ sourceParent.move(sourcePath.getName(), Path.create(workspaceName, destAbsPath));
}
@Override
public void save() throws AccessDeniedException, ItemExistsException, ReferentialIntegrityException, ConstraintViolationException, InvalidItemStateException, VersionException, LockException, NoSuchNodeTypeException, RepositoryException {
checkIsAlive();
-
- // TODO
-
+ revision = transientSpace.save();
+ nodeStateProvider.clear();
}
@Override
public void refresh(boolean keepChanges) throws RepositoryException {
checkIsAlive();
-
- // TODO
-
+ revision = transientSpace.refresh(keepChanges);
+ nodeStateProvider.clear();
}
@Override
public boolean hasPendingChanges() throws RepositoryException {
checkIsAlive();
-
- // TODO
- return false;
+ return transientSpace.isDirty();
}
@Override
public ValueFactory getValueFactory() throws UnsupportedRepositoryOperationException, RepositoryException {
checkIsAlive();
- return valueFactory;
+ return sessionContext.getValueFactory();
}
@Override
@@ -198,6 +292,7 @@ public class SessionImpl extends Abstrac
return;
}
+ isAlive = false;
// TODO
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java?rev=1300973&r1=1300972&r2=1300973&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java Thu Mar 15 13:33:32 2012
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.jcr;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.oak.jcr.SessionImpl.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
@@ -48,24 +50,28 @@ import java.io.InputStream;
* <code>WorkspaceImpl</code>...
*/
public class WorkspaceImpl implements Workspace {
+ public static final String DEFAULT_WORKSPACE_NAME = "default";
/**
* logger instance
*/
private static final Logger log = LoggerFactory.getLogger(WorkspaceImpl.class);
- private final SessionImpl session = null;
- private final String name = null;
+ private final Context sessionContext;
+
+ public WorkspaceImpl(Context sessionContext) {
+ this.sessionContext = sessionContext;
+ }
//----------------------------------------------------------< Workspace >---
@Override
public Session getSession() {
- return session;
+ return sessionContext.getSession();
}
@Override
public String getName() {
- return name;
+ return sessionContext.getWorkspaceName();
}
@Override
@@ -75,8 +81,8 @@ public class WorkspaceImpl implements Wo
@Override
public void copy(String srcWorkspace, String srcAbsPath, String destAbsPath) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
- session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO -> SPI
@@ -84,8 +90,8 @@ public class WorkspaceImpl implements Wo
@Override
public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
- session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO -> SPI
@@ -93,8 +99,8 @@ public class WorkspaceImpl implements Wo
@Override
public void move(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
- session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO -> SPI
@@ -107,8 +113,8 @@ public class WorkspaceImpl implements Wo
@Override
public LockManager getLockManager() throws UnsupportedRepositoryOperationException, RepositoryException {
- session.checkIsAlive();
- session.checkSupportedOption(Repository.OPTION_LOCKING_SUPPORTED);
+ getOakSession().checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_LOCKING_SUPPORTED);
// TODO
return null;
@@ -116,7 +122,7 @@ public class WorkspaceImpl implements Wo
@Override
public QueryManager getQueryManager() throws RepositoryException {
- session.checkIsAlive();
+ getOakSession().checkIsAlive();
// TODO
return null;
@@ -124,7 +130,7 @@ public class WorkspaceImpl implements Wo
@Override
public NamespaceRegistry getNamespaceRegistry() throws RepositoryException {
- session.checkIsAlive();
+ getOakSession().checkIsAlive();
// TODO
return null;
@@ -132,7 +138,7 @@ public class WorkspaceImpl implements Wo
@Override
public NodeTypeManager getNodeTypeManager() throws RepositoryException {
- session.checkIsAlive();
+ getOakSession().checkIsAlive();
// TODO
return null;
@@ -140,8 +146,8 @@ public class WorkspaceImpl implements Wo
@Override
public ObservationManager getObservationManager() throws UnsupportedRepositoryOperationException, RepositoryException {
- session.checkSupportedOption(Repository.OPTION_OBSERVATION_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_OBSERVATION_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO
return null;
@@ -149,8 +155,8 @@ public class WorkspaceImpl implements Wo
@Override
public VersionManager getVersionManager() throws UnsupportedRepositoryOperationException, RepositoryException {
- session.checkIsAlive();
- session.checkSupportedOption(Repository.OPTION_VERSIONING_SUPPORTED);
+ getOakSession().checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_VERSIONING_SUPPORTED);
// TODO
return null;
@@ -158,7 +164,7 @@ public class WorkspaceImpl implements Wo
@Override
public String[] getAccessibleWorkspaceNames() throws RepositoryException {
- session.checkIsAlive();
+ getOakSession().checkIsAlive();
// TODO
return new String[0];
@@ -166,8 +172,8 @@ public class WorkspaceImpl implements Wo
@Override
public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws PathNotFoundException, ConstraintViolationException, VersionException, LockException, AccessDeniedException, RepositoryException {
- session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO
return null;
@@ -175,35 +181,47 @@ public class WorkspaceImpl implements Wo
@Override
public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException, VersionException, PathNotFoundException, ItemExistsException, ConstraintViolationException, InvalidSerializedDataException, LockException, AccessDeniedException, RepositoryException {
- session.checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
- session.checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
+ getOakSession().checkIsAlive();
// TODO -> SPI
}
@Override
public void createWorkspace(String name) throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
- session.checkIsAlive();
- session.checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
- // TODO -> SPI
+ getOakSession().checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
+
+ createWorkspace(sessionContext.getMicrokernel(), name);
}
@Override
public void createWorkspace(String name, String srcWorkspace) throws AccessDeniedException, UnsupportedRepositoryOperationException, NoSuchWorkspaceException, RepositoryException {
- session.checkIsAlive();
- session.checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
+ getOakSession().checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
// TODO -> SPI
}
@Override
public void deleteWorkspace(String name) throws AccessDeniedException, UnsupportedRepositoryOperationException, NoSuchWorkspaceException, RepositoryException {
- session.checkIsAlive();
- session.checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
+ getOakSession().checkIsAlive();
+ getOakSession().checkSupportedOption(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED);
- // TODO -> SPI
+ MicroKernel microKernel = sessionContext.getMicrokernel();
+ String revision = microKernel.getHeadRevision();
+ microKernel.commit("/", "- \"" + name + '\"', revision, null);
}
//------------------------------------------------------------< private >---
+
+ private SessionImpl getOakSession() {
+ return sessionContext.getSession();
+ }
+
+ static void createWorkspace(MicroKernel microKernel,String name) {
+ String revision = microKernel.getHeadRevision();
+ microKernel.commit("/", "+ \"" + name + "\" : {}", revision, null);
+ }
}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/OakRepositoryConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/OakRepositoryConfiguration.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/OakRepositoryConfiguration.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/OakRepositoryConfiguration.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,70 @@
+/*
+ * 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.jcr.configuration;
+
+import javax.jcr.RepositoryException;
+import java.util.Collections;
+import java.util.Map;
+
+import static java.text.MessageFormat.format;
+
+public class OakRepositoryConfiguration implements RepositoryConfiguration {
+ private final Map<String, String> parameters;
+ private final String microkernelUrl;
+ private final int nodeStateCacheSize;
+
+ private OakRepositoryConfiguration(Map<String, String> parameters) throws RepositoryException {
+ this.parameters = Collections.unmodifiableMap(parameters);
+
+ microkernelUrl = getParameterMap().get(MICROKERNEL_URL);
+ if (microkernelUrl == null) {
+ throw new RepositoryException(format("Missing configuration value for {0}", MICROKERNEL_URL));
+ }
+
+ String size = getParameterMap().get(NODE_STATE_CACHE_SIZE);
+ try {
+ nodeStateCacheSize = size == null ? 0 : Integer.parseInt(size);
+ }
+ catch (NumberFormatException e) {
+ throw new RepositoryException(format("Invalid configuration value {0} for {1}",
+ size, NODE_STATE_CACHE_SIZE), e);
+ }
+
+ }
+
+ public static RepositoryConfiguration create(Map<String, String> parameters) throws RepositoryException {
+ return new OakRepositoryConfiguration(parameters);
+ }
+
+ @Override
+ public final Map<String, String> getParameterMap() {
+ return parameters;
+ }
+
+ @Override
+ public String getMicrokernelUrl() throws RepositoryException {
+ return microkernelUrl;
+ }
+
+ @Override
+ public int getNodeStateCacheSize() {
+ return nodeStateCacheSize;
+ }
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/RepositoryConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/RepositoryConfiguration.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/RepositoryConfiguration.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/configuration/RepositoryConfiguration.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.configuration;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+
+public interface RepositoryConfiguration {
+ String MICROKERNEL_URL = RepositoryConfiguration.class.getName() + ".microkernel-url";
+ String NODE_STATE_CACHE_SIZE = RepositoryConfiguration.class.getName() + ".node-state-cache-size";
+
+ Map<String, String> getParameterMap();
+ String getMicrokernelUrl() throws RepositoryException;
+ int getNodeStateCacheSize();
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/DefaultJsonTokenizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/DefaultJsonTokenizer.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/DefaultJsonTokenizer.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/DefaultJsonTokenizer.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,214 @@
+/*
+ * 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.jcr.json;
+
+import org.apache.jackrabbit.oak.jcr.json.Token.Type;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This JSON tokenizer operates on a string as its input. For maximal performance
+ * it <em>does not</em> unescape JSON string values.
+ * Use {@link JsonValue#unescape(String)} to unescape the text of {@link Token}s
+ * of type {@link Type#STRING}.
+ *
+ * @see UnescapingJsonTokenizer
+ */
+public class DefaultJsonTokenizer extends JsonTokenizer {
+ private final String json;
+
+ private int pos;
+
+ /**
+ * Create a tokenizer for the given input string
+ * @param json
+ */
+ public DefaultJsonTokenizer(String json) {
+ this.json = json;
+ }
+
+ /**
+ * @see JsonTokenizer#JsonTokenizer(JsonTokenizer)
+ */
+ protected DefaultJsonTokenizer(DefaultJsonTokenizer tokenizer) {
+ super(tokenizer);
+ json = tokenizer.json;
+ pos = tokenizer.pos;
+ }
+
+ @Override
+ protected Token nextToken() {
+ skipWhiteSpace();
+ if (pos >= json.length()) {
+ return createToken(Type.EOF, "", pos);
+ }
+
+ switch (json.charAt(pos)) {
+ case '{': return createToken(Type.BEGIN_OBJECT, "{", pos++);
+ case '}': return createToken(Type.END_OBJECT, "}", pos++);
+ case '[': return createToken(Type.BEGIN_ARRAY, "[", pos++);
+ case ']': return createToken(Type.END_ARRAY, "]", pos++);
+ case ':': return createToken(Type.COLON, ":", pos++);
+ case ',': return createToken(Type.COMMA, ",", pos++);
+ case 't': return readLiteral(Type.TRUE, "true");
+ case 'f': return readLiteral(Type.FALSE, "false");
+ case 'n': return readLiteral(Type.NULL, "null");
+ case '"': return readString();
+ default: return isNumber() ? readNumber() : readUnknown();
+ }
+ }
+
+ @Override
+ public int pos() {
+ return peek().pos();
+ }
+
+ @Override
+ public void setPos(int pos) {
+ currentToken = null;
+ this.pos = pos;
+ }
+
+ @Override
+ public String toString() {
+ return (currentToken == null ? "" : currentToken) + " " + json.substring(pos);
+ }
+
+ @Override
+ public DefaultJsonTokenizer copy() {
+ return new DefaultJsonTokenizer(this);
+ }
+
+ //------------------------------------------< protected >---
+
+ /**
+ * Advance {@link #pos()} until the current character is not a
+ * whitespace character.
+ */
+ protected void skipWhiteSpace() {
+ while (pos < json.length() && Character.isWhitespace(json.charAt(pos))) {
+ pos++;
+ }
+ }
+
+ /**
+ * Factory method for creating {@link Token}s
+ * @param type
+ * @param text
+ * @param pos
+ * @return a new token
+ */
+ protected Token createToken(Type type, String text, int pos) {
+ return new Token(type, text, pos);
+ }
+
+ /**
+ * Read the literal {@code text} and create a token of the given {@code type}
+ * @param type
+ * @param text
+ * @return a new token
+ * @throws ParseException if {@code text} cannot be read at the current position
+ */
+ protected Token readLiteral(Type type, String text) {
+ if (json.substring(pos).startsWith(text)) {
+ Token token = createToken(type, text, pos);
+ pos += text.length();
+ return token;
+ }
+ else {
+ throw new ParseException(pos, "Expected '" + text + ",' found: " + excerpt(json, pos, 40));
+ }
+ }
+
+ /**
+ * Read a JSON string and create a {@link Token.Type#STRING} token.
+ * @return a new token
+ * @throws ParseException if no string can be read at the current position
+ */
+ protected Token readString() {
+ int i;
+ boolean found = false;
+ boolean even = true;
+
+ // starting at pos + 1, find index i of the first quote character in json which
+ // is preceded by an even number of backslash characters
+ for (i = pos + 1; i < json.length() && !(found = json.charAt(i) == '"' && even); i++) {
+ even = json.charAt(i) != '\\' || !even;
+ }
+
+ if (found) {
+ Token token = createToken(Type.STRING, json.substring(pos + 1, i), pos);
+ pos = i + 1;
+ return token;
+ }
+ else {
+ throw new ParseException(pos, "Expected string, found. " + excerpt(json, pos, 40));
+ }
+ }
+
+ private static final Pattern NUMBER_PATTERN = Pattern.compile(
+ "(\\+|-)?(\\d+)((\\.)(\\d+))?(((e|E)(\\+|-)?)(\\d+))?");
+
+ /**
+ * Read a JSON number and create a {@link Token.Type#NUMBER} token.
+ * @return a new token
+ * @throws ParseException if no number can be read at the current position
+ */
+ protected Token readNumber() {
+ Matcher matcher = NUMBER_PATTERN.matcher(json.substring(pos));
+ if (matcher.lookingAt()) {
+ Token token = createToken(Type.NUMBER, matcher.group(), pos);
+ pos += matcher.end();
+ return token;
+ }
+ else {
+ throw new ParseException(pos, "Expected number, found. " + excerpt(json, pos, 40));
+ }
+ }
+
+ /**
+ * Read from the current position until a new token starts and create a
+ * {@link Token.Type#UNKNOWN} token.
+ * @return a new token
+ */
+ protected Token readUnknown() {
+ int start = pos++;
+ while (pos < json.length() && "{}[]:,tfn+-0123456789\" ".indexOf(json.charAt(pos)) == -1) {
+ pos++;
+ }
+ return new Token(Type.UNKNOWN, json.substring(start, pos), start);
+ }
+
+ //------------------------------------------< private >---
+
+ private boolean isNumber() {
+ // true if first character is a digit or a sign and second character is a digit
+ char first = json.charAt(pos);
+ return !(!Character.isDigit(first) &&
+ ('+' != first && '-' != first || pos + 1 >= json.length() ||
+ !Character.isDigit(json.charAt(pos + 1))));
+ }
+
+ private static String excerpt(String string, int pos, int len) {
+ return string.substring(pos, Math.min(string.length(), pos + len)) + "...";
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/FullJsonParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/FullJsonParser.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/FullJsonParser.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/FullJsonParser.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,117 @@
+/*
+ * 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.jcr.json;
+
+import org.apache.jackrabbit.oak.jcr.json.JsonValue.JsonArray;
+import org.apache.jackrabbit.oak.jcr.json.JsonValue.JsonAtom;
+import org.apache.jackrabbit.oak.jcr.json.JsonValue.JsonObject;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+/**
+ * Utility class for parsing JSON objects and arrays into
+ * {@link JsonObject}s and {@link JsonArray}s, respectively.
+ *
+ * @see LevelOrderJsonParser
+ */
+public class FullJsonParser {
+ private FullJsonParser() { }
+
+ /**
+ * Parse a JSON object from {@code tokenizer}
+ * @param tokenizer
+ * @return a {@code JsonObject}
+ * @throws ParseException
+ */
+ public static JsonObject parseObject(JsonTokenizer tokenizer) {
+ ObjectHandler objectHandler = new ObjectHandler();
+ new JsonParser(objectHandler).parseObject(tokenizer);
+ return objectHandler.getObject();
+ }
+
+ /**
+ * Parse a JSON array from {@code tokenizer}
+ * @param tokenizer
+ * @return a {@code JsonArray}
+ * @throws ParseException
+ */
+ public static JsonArray parseArray(JsonTokenizer tokenizer) {
+ ArrayHandler arrayHandler = new ArrayHandler();
+ new JsonParser(arrayHandler).parseArray(tokenizer);
+ return arrayHandler.getArray();
+ }
+
+ /**
+ * This implementation of a {@code JsonHandler} builds up a {@code JsonObject}
+ * by recursively descending into its constituents.
+ */
+ public static class ObjectHandler extends JsonHandler {
+ private final JsonObject object = new JsonObject(new LinkedHashMap<String, JsonValue>());
+
+ @Override
+ public void atom(Token key, Token value) {
+ object.put(key.text(), new JsonAtom(value));
+ }
+
+ @Override
+ public void object(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ object.put(key.text(), parseObject(tokenizer));
+ }
+
+ @Override
+ public void array(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ object.put(key.text(), parseArray(tokenizer));
+ }
+
+ public JsonObject getObject() {
+ return object;
+ }
+
+ }
+
+ /**
+ * This implementation of a {@code JsonHandler} builds up a {@code JsonArray}
+ * by recursively descending into its constituents.
+ */
+ public static class ArrayHandler extends JsonHandler {
+ private final JsonArray array = new JsonArray(new ArrayList<JsonValue>());
+
+ @Override
+ public void atom(Token key, Token value) {
+ array.add(new JsonAtom(value));
+ }
+
+ @Override
+ public void object(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ array.add(parseObject(tokenizer));
+ }
+
+ @Override
+ public void array(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ array.add(parseArray(tokenizer));
+ }
+
+ public JsonArray getArray() {
+ return array;
+ }
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonHandler.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonHandler.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonHandler.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,84 @@
+/*
+ * 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.jcr.json;
+
+/**
+ * Handler for semantic actions of a {@link JsonParser}.
+ * This class provides a handler which fully parses a JSON
+ * document by recursive decent without executing any actions.
+ * <p/>
+ * Override this class to add semantic actions as needed.
+ */
+public class JsonHandler {
+
+ /**
+ * Default instance which can be used to skip any part of a
+ * JSON document.
+ */
+ public static final JsonHandler INSTANCE = new JsonHandler();
+
+ /**
+ * A primitive JSON value (ATOM) has been parsed.
+ * @param key
+ * @param value
+ */
+ public void atom(Token key, Token value) { }
+
+ /**
+ * A COMMA has been parsed
+ * @param token
+ */
+ public void comma(Token token) { }
+
+ /**
+ * Parser PAIR. This implementation simply delegates back
+ * to {@link JsonParser#parsePair(JsonTokenizer)}
+ *
+ * @param parser
+ * @param tokenizer
+ */
+ public void pair(JsonParser parser, JsonTokenizer tokenizer) {
+ parser.parsePair(tokenizer);
+ }
+
+ /**
+ * Parser OBJECT. This implementation simply delegates back
+ * to {@link JsonParser#parseObject(JsonTokenizer)}
+ *
+ * @param parser
+ * @param key
+ * @param tokenizer
+ */
+ public void object(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ parser.parseObject(tokenizer);
+ }
+
+ /**
+ * Parser ARRAY. This implementation simply delegates back
+ * to {@link JsonParser#parseArray(JsonTokenizer)}
+ *
+ * @param parser
+ * @param key
+ * @param tokenizer
+ */
+ public void array(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ parser.parseArray(tokenizer);
+ }
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonParser.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonParser.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonParser.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,172 @@
+/*
+ * 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.jcr.json;
+
+
+import org.apache.jackrabbit.oak.jcr.json.Token.Type;
+
+/**
+ * A parser for the JSON format accepting the following grammar:
+ *
+ * <pre>
+ * OBJECT ::= { (PAIR (, PAIR)*)? }
+ * PAIR ::= STRING : VALUE
+ * VALUE ::= OBJECT | ARRAY | STRING | NUMBER | true | false | null
+ * ARRAY ::= [ (VALUE (, VALUE)*)? ]
+ * </pre>
+ *
+ * Semantic actions are attached through a {@link JsonHandler} instance
+ * which is passed to the constructor. For each of the above productions
+ * the parser provides a corresponding method which take a {@link JsonTokenizer}
+ * for reading the JSON input. These methods call the respective call back on the
+ * {@code JsonHandler} for each of the constituents of the production.
+ * <p/>
+ * Note: In contrast to conventional parsers, this parser <em>does not</em>
+ * recursively decent into nested structures (OBJECT, ARRAY and PAIR, that is).
+ * Instead it calls the respective method on the {@code JsonHandler} which
+ * is can use this parser instance or any other parser to continue parsing.
+ *
+ * @see <a href="http://www.json.org/">json.org</a>
+ */
+public final class JsonParser {
+ private final JsonHandler jsonHandler;
+
+ public JsonParser(JsonHandler jsonHandler) {
+ this.jsonHandler = jsonHandler;
+ }
+
+ /**
+ * Parses
+ * <pre>
+ * OBJECT ::= { (PAIR (, PAIR)*)? }
+ * </pre>
+ * Calls {@link JsonHandler#comma(Token)}
+ * @param tokenizer
+ * @throws ParseException
+ */
+ public void parseObject(JsonTokenizer tokenizer) {
+ tokenizer.read(Type.BEGIN_OBJECT);
+
+ if (tryParsePair(tokenizer)) {
+ while (tokenizer.peek(Type.COMMA)) {
+ jsonHandler.comma(tokenizer.read());
+ if (!tryParsePair(tokenizer)) {
+ throw new ParseException(tokenizer.pos(), "Expected pair, found: " + tokenizer.peek());
+ }
+ }
+ }
+ tokenizer.read(Type.END_OBJECT);
+ }
+
+ /**
+ * Parses
+ * <pre>
+ * PAIR ::= STRING: VALUE
+ * </pre>
+ * @param tokenizer
+ * @throws ParseException
+ */
+ public void parsePair(JsonTokenizer tokenizer) {
+ if (!tokenizer.peek(Type.STRING)) {
+ throw new ParseException(tokenizer.pos(), "Expected string, found: " + tokenizer.peek());
+ }
+
+ Token key = tokenizer.read();
+ tokenizer.read(Type.COLON);
+ parseValue(key, tokenizer);
+ }
+
+ /**
+ * Parses
+ * <pre>
+ * VALUE ::= OBJECT | ARRAY | STRING | NUMBER | true | false | null
+ * </pre>
+ * Calls one of {@link JsonHandler#object(JsonParser, Token, JsonTokenizer)},
+ * {@link JsonHandler#array(JsonParser, Token, JsonTokenizer)} and
+ * {@link JsonHandler#atom(Token, Token)}
+ * @param tokenizer
+ * @throws ParseException
+ */
+ public void parseValue(Token key, JsonTokenizer tokenizer) {
+ switch (tokenizer.peek().type()) {
+ case BEGIN_OBJECT:
+ jsonHandler.object(this, key, tokenizer);
+ break;
+ case BEGIN_ARRAY:
+ jsonHandler.array(this, key, tokenizer);
+ break;
+ case STRING:
+ case NUMBER:
+ case TRUE:
+ case FALSE:
+ case NULL:
+ jsonHandler.atom(key, tokenizer.read());
+ break;
+ default:
+ throw new ParseException(tokenizer.pos(), "Expected value, found: " + tokenizer.peek());
+ }
+ }
+
+ /**
+ * Parses
+ * <pre>
+ * ARRAY ::= [ (VALUE (, VALUE)*)? ]
+ * </pre>
+ * Calls {@link JsonHandler#comma(Token)}
+ * @param tokenizer
+ * @throws ParseException
+ */
+ public void parseArray(JsonTokenizer tokenizer) {
+ tokenizer.read(Type.BEGIN_ARRAY);
+
+ if (tryParseValue(tokenizer)) {
+ while (tokenizer.peek(Type.COMMA)) {
+ jsonHandler.comma(tokenizer.read());
+ if (!tryParseValue(tokenizer)) {
+ throw new ParseException(tokenizer.pos(), "Expected value, found: " + tokenizer.peek());
+ }
+ }
+ }
+ tokenizer.read(Type.END_ARRAY);
+ }
+
+ //------------------------------------------< private >---
+
+ private boolean tryParsePair(JsonTokenizer tokenizer) {
+ if (tokenizer.peek(Type.STRING)) {
+ jsonHandler.pair(this, tokenizer);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ private boolean tryParseValue(JsonTokenizer tokenizer) {
+ if (tokenizer.peek(Type.END_ARRAY)) {
+ return false;
+ }
+ else {
+ parseValue(null, tokenizer);
+ return true;
+ }
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonTokenizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonTokenizer.java?rev=1300973&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonTokenizer.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/json/JsonTokenizer.java Thu Mar 15 13:33:32 2012
@@ -0,0 +1,138 @@
+/*
+ * 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.jcr.json;
+
+import org.apache.jackrabbit.oak.jcr.json.Token.Type;
+
+/**
+ * Abstract base class for JSON tokenizers.
+ * A JSON tokenizer breaks a stream of character into {@link Token}s. It has
+ * a current {@link #pos() position} and methods for inspecting, reading and
+ * skipping the token at the current position.
+ */
+public abstract class JsonTokenizer {
+
+ /**
+ * The current token which has been read ahead, if any.
+ * {@code null} otherwise.
+ */
+ protected Token currentToken;
+
+ /**
+ * Copy constructor. To be used in conjunction with {@link #copy()}
+ * @param tokenizer
+ */
+ protected JsonTokenizer(JsonTokenizer tokenizer) {
+ currentToken = tokenizer.currentToken;
+ }
+
+ protected JsonTokenizer() { }
+
+ /**
+ * Returns the current token without advancing the {@link #pos() position}
+ * @return current token
+ */
+ public Token peek() {
+ if (currentToken == null) {
+ currentToken = nextToken();
+ }
+
+ return currentToken;
+ }
+
+ /**
+ * @param type
+ * @return {@code true} if and only if the current token is of the given {@code type}
+ */
+ public boolean peek(Type type) {
+ return peek().type() == type;
+ }
+
+ /**
+ * Returns the current token and advances the {@link #pos() position}
+ * @return current token
+ */
+ public Token read() {
+ if (currentToken == null) {
+ return nextToken();
+ }
+ else {
+ Token token = currentToken;
+ currentToken = null;
+ return token;
+ }
+ }
+
+ /**
+ * Returns the current token and advances the {@link #pos() position} if the token
+ * is of the given {@code type}.
+ * @param type
+ * @return current token
+ * @throws ParseException if the token is not of the given {@code type}.
+ */
+ public Token read(Type type) {
+ Token token = peek();
+ if (token.type() == type) {
+ return read();
+ }
+ else {
+ throw new ParseException(token.pos(), "Expected token type " + type + ", found: " + token);
+ }
+ }
+
+ /**
+ * Advances the {@link #pos() position} if the token is of the given {@code type}.
+ * @param type
+ * @return {@code true} if and only if the is token is of the given {@code type}.
+ */
+ public boolean skip(Type type) {
+ if (peek(type)) {
+ read();
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * @return the current position
+ */
+ public abstract int pos();
+
+ /**
+ * Set the current position
+ * @param pos
+ */
+ public abstract void setPos(int pos);
+
+ /**
+ * Create a copy of this tokenizer with the same state. Implementations usually
+ * create a new instance by calling the (overriden) {@link #JsonTokenizer(JsonTokenizer) copy constructor}.
+ * @return copy of this tokenizer
+ */
+ public abstract JsonTokenizer copy();
+
+ /**
+ * Read the next token from the input and advance the current {@link #pos() positon}.
+ * @return next token
+ */
+ protected abstract Token nextToken();
+}