You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/07/22 17:16:58 UTC

svn commit: r1505715 [1/2] - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/ oak-core/src/main/java/org/apache/jackrabbit/oak/util/ oak-jcr/ oak-jcr/src/main/java...

Author: angela
Date: Mon Jul 22 15:16:57 2013
New Revision: 1505715

URL: http://svn.apache.org/r1505715
Log:
OAK-527 : permissions
- fix minor issue in Session#checkPermission that caused TCK test to fail
- remove related test from exclusion list in pom.xml
- adjust QueryTest that was relying on RepositoryException instead of javax.security.AccessControlException

OAK-773 : Workspace Import 
- refactor existing session import code to use OAK API instead of JCR API and use the same logic for workspace import
- move existing logic in NodeDelegate to calculate primary type and generation of autogenerated items to TreeUtil
- implement Workspace#importXML and #getImportContentHandler
- adjust pom.xml to reflect changes

Added:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java   (contents, props changed)
      - copied, changed from r1504432, jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/SessionImporter.java
Removed:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/SessionImporter.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CommitFailedException.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/NodeInfo.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/PropInfo.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
    jackrabbit/oak/trunk/oak-jcr/pom.xml
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.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
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/DocViewImportHandler.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImportHandler.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/SysViewImportHandler.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/QueryTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CommitFailedException.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CommitFailedException.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CommitFailedException.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CommitFailedException.java Mon Jul 22 15:16:57 2013
@@ -16,6 +16,15 @@
  */
 package org.apache.jackrabbit.oak.api;
 
+import javax.jcr.AccessDeniedException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.version.VersionException;
+
 import static java.lang.String.format;
 
 /**
@@ -126,4 +135,30 @@ public class CommitFailedException exten
         return code;
     }
 
+    /**
+     * Wraps the given {@link CommitFailedException} instance using the
+     * appropriate {@link javax.jcr.RepositoryException} subclass based on the
+     * {@link CommitFailedException#getType() type} of the given exception.
+     *
+     * @return matching repository exception
+     */
+    public RepositoryException asRepositoryException() {
+        if (isConstraintViolation()) {
+            return new ConstraintViolationException(this);
+        } else if (isOfType("Type")) {
+            return new NoSuchNodeTypeException(this);
+        } else if (isAccessViolation()) {
+            return new AccessDeniedException(this);
+        } else if (isOfType("Integrity")) {
+            return new ReferentialIntegrityException(this);
+        } else if (isOfType("State")) {
+            return new InvalidItemStateException(this);
+        } else if (isOfType("Version")) {
+            return new VersionException(this);
+        } else if (isOfType("Lock")) {
+            return new LockException(this);
+        } else {
+            return new RepositoryException(this);
+        }
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/NodeInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/NodeInfo.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/NodeInfo.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/NodeInfo.java Mon Jul 22 15:16:57 2013
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.spi.xml;
 
+import java.util.Collections;
+import javax.annotation.Nonnull;
+
 /**
  * Information about a node being imported. This class is used
  * by the XML import handlers to pass the parsed node information to the
@@ -40,7 +43,7 @@ public class NodeInfo {
     /**
      * Names of the mixin types of the node being imported.
      */
-    private final String[] mixinTypeNames;
+    private final Iterable<String> mixinTypeNames;
 
     /**
      * UUID of the node being imported.
@@ -55,11 +58,11 @@ public class NodeInfo {
      * @param mixinTypeNames names of the mixin types of the node being imported
      * @param uuid uuid of the node being imported
      */
-    public NodeInfo(String name, String primaryTypeName, String[] mixinTypeNames,
+    public NodeInfo(String name, String primaryTypeName, Iterable<String> mixinTypeNames,
                     String uuid) {
         this.name = name;
         this.primaryTypeName = primaryTypeName;
-        this.mixinTypeNames = mixinTypeNames;
+        this.mixinTypeNames = (mixinTypeNames == null) ? Collections.<String>emptyList() : mixinTypeNames;
         this.uuid = uuid;
     }
 
@@ -86,7 +89,8 @@ public class NodeInfo {
      *
      * @return mixin type names
      */
-    public String[] getMixinTypeNames() {
+    @Nonnull
+    public Iterable<String> getMixinTypeNames() {
         return mixinTypeNames;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/PropInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/PropInfo.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/PropInfo.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/xml/PropInfo.java Mon Jul 22 15:16:57 2013
@@ -16,11 +16,14 @@
  */
 package org.apache.jackrabbit.oak.spi.xml;
 
+import java.util.Collections;
+import java.util.List;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.nodetype.PropertyDefinition;
 
+import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.plugins.nodetype.EffectiveNodeType;
 
 /**
@@ -132,12 +135,16 @@ public class PropInfo {
         return values[0].getValue(targetType);
     }
 
-    public Value[] getValues(int targetType) throws RepositoryException {
-        Value[] va = new Value[values.length];
-        for (int i = 0; i < values.length; i++) {
-            va[i] = values[i].getValue(targetType);
+    public List<Value> getValues(int targetType) throws RepositoryException {
+        if (values.length == 0) {
+            return Collections.emptyList();
+        } else {
+            List<Value> vs = Lists.newArrayListWithCapacity(values.length);
+            for (TextValue value : values) {
+                vs.add(value.getValue(targetType));
+            }
+            return vs;
         }
-        return va;
     }
 
     //TODO check multivalue handling

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java Mon Jul 22 15:16:57 2013
@@ -16,19 +16,56 @@
  */
 package org.apache.jackrabbit.oak.util;
 
-import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
-import static org.apache.jackrabbit.oak.api.Type.STRINGS;
-
+import java.util.Calendar;
+import java.util.List;
+import java.util.Set;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
 
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.util.Text;
 
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.emptyList;
+import static org.apache.jackrabbit.JcrConstants.JCR_AUTOCREATED;
+import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
+import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTVALUES;
+import static org.apache.jackrabbit.JcrConstants.JCR_HASORDERABLECHILDNODES;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
+import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_MULTIPLE;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_SAMENAMESIBLINGS;
+import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
+import static org.apache.jackrabbit.oak.api.Type.DATE;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.commons.PathUtils.dropIndexFromName;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_CREATEDBY;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_LASTMODIFIEDBY;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_PROPERTY_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
+
 /**
  * Utility providing common operations for the {@code Tree} that are not provided
  * by the API.
@@ -87,6 +124,27 @@ public final class TreeUtil {
         return property != null && !property.isArray() && property.getValue(BOOLEAN);
     }
 
+
+    @CheckForNull
+    public static String getName(Tree tree, String name) {
+        PropertyState property = tree.getProperty(name);
+        if (property != null && property.getType() == NAME) {
+            return property.getValue(NAME);
+        } else {
+            return null;
+        }
+    }
+
+    @Nonnull
+    public static Iterable<String> getNames(Tree tree, String name) {
+        PropertyState property = tree.getProperty(name);
+        if (property != null && property.getType() == NAMES) {
+            return property.getValue(NAMES);
+        } else {
+            return emptyList();
+        }
+    }
+
     /**
      * Return the possibly non existing tree located at the passed {@code path} from
      * the location of the start {@code tree} or {@code null} if {@code path} results
@@ -112,4 +170,224 @@ public final class TreeUtil {
         return tree;
     }
 
+    public static Tree addChild(
+            Tree parent, String name, String typeName, Tree typeRoot, String userID)
+            throws RepositoryException {
+        Tree type = typeRoot.getChild(typeName);
+        if (!type.exists()) {
+            throw new NoSuchNodeTypeException(
+                    "Node type " + typeName + " does not exist");
+        } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
+            throw new ConstraintViolationException(
+                    "Node type " + typeName + " is abstract");
+        } else if (getBoolean(type, JCR_ISMIXIN)) {
+            throw new ConstraintViolationException(
+                    "Node type " + typeName + " is a mixin type");
+        }
+
+        Tree child = parent.addChild(name);
+        child.setProperty(JCR_PRIMARYTYPE, typeName, NAME);
+        if (getBoolean(type, JCR_HASORDERABLECHILDNODES)) {
+            child.setOrderableChildren(true);
+        }
+        autoCreateItems(child, type, typeRoot, userID);
+        return child;
+    }
+
+    public static void addMixin(Tree tree, String mixinName, Tree typeRoot, String userID) throws RepositoryException {
+        Tree type = typeRoot.getChild(mixinName);
+        if (!type.exists()) {
+            throw new NoSuchNodeTypeException(
+                    "Node type " + mixinName + " does not exist");
+        } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
+            throw new ConstraintViolationException(
+                    "Node type " + mixinName + " is abstract");
+        } else if (!getBoolean(type, JCR_ISMIXIN)) {
+            throw new ConstraintViolationException(
+                    "Node type " + mixinName + " is a not a mixin type");
+        }
+
+        List<String> mixins = Lists.newArrayList();
+        String primary = getName(tree, JCR_PRIMARYTYPE);
+        if (primary != null
+                && Iterables.contains(getNames(type, NodeTypeConstants.OAK_PRIMARY_SUBTYPES), primary)) {
+            return;
+        }
+
+        Set<String> subMixins = Sets.newHashSet(getNames(type, NodeTypeConstants.OAK_MIXIN_SUBTYPES));
+        for (String mixin : getNames(tree, NodeTypeConstants.JCR_MIXINTYPES)) {
+            if (mixinName.equals(mixin) || subMixins.contains(mixin)) {
+                return;
+            }
+            mixins.add(mixin);
+        }
+
+        mixins.add(mixinName);
+        tree.setProperty(JcrConstants.JCR_MIXINTYPES, mixins, NAMES);
+
+        autoCreateItems(tree, type, typeRoot, userID);
+    }
+
+    public static void autoCreateItems(Tree tree, Tree type, Tree typeRoot, String userID)
+            throws RepositoryException {
+        // TODO: use a separate oak:autoCreatePropertyDefinitions
+        Tree properties = type.getChild(OAK_NAMED_PROPERTY_DEFINITIONS);
+        for (Tree definitions : properties.getChildren()) {
+            String name = definitions.getName();
+            if (name.equals("oak:primaryType")
+                    || name.equals("oak:mixinTypes")) {
+                continue;
+            } else if (name.equals("oak:uuid")) {
+                name = JCR_UUID;
+            }
+            for (Tree definition : definitions.getChildren()) {
+                if (getBoolean(definition, JCR_AUTOCREATED)) {
+                    if (!tree.hasProperty(name)) {
+                        PropertyState property =
+                                autoCreateProperty(name, definition, userID);
+                        if (property != null) {
+                            tree.setProperty(property);
+                        } else {
+                            throw new RepositoryException(
+                                    "Unable to auto-create value for "
+                                    + PathUtils.concat(tree.getPath(), name));
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        // TODO: use a separate oak:autoCreateChildNodeDefinitions
+        // Note that we use only named, non-SNS child node definitions
+        // as there can be no reasonable default values for residual or
+        // SNS child nodes
+        Tree childNodes = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
+        for (Tree definitions : childNodes.getChildren()) {
+            String name = definitions.getName();
+            for (Tree definition : definitions.getChildren()) {
+                if (getBoolean(definition, JCR_AUTOCREATED)) {
+                    if (!tree.hasChild(name)) {
+                        String typeName =
+                                getName(definition, JCR_DEFAULTPRIMARYTYPE);
+                        addChild(tree, name, typeName, typeRoot, userID);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    public static PropertyState autoCreateProperty(@Nonnull String name,
+                                                   @Nonnull Tree definition,
+                                                   @CheckForNull String userID) {
+        if (JCR_UUID.equals(name)) {
+            String uuid = IdentifierManager.generateUUID();
+            return PropertyStates.createProperty(name, uuid, STRING);
+        } else if (JCR_CREATED.equals(name)) {
+            long now = Calendar.getInstance().getTime().getTime();
+            return PropertyStates.createProperty(name, now, DATE);
+        } else if (JCR_CREATEDBY.equals(name)) {
+            if (userID != null) {
+                return PropertyStates.createProperty(name, userID, STRING);
+            }
+        } else if (JCR_LASTMODIFIED.equals(name)) {
+            long now = Calendar.getInstance().getTime().getTime();
+            return PropertyStates.createProperty(name, now, DATE);
+        } else if (JCR_LASTMODIFIEDBY.equals(name)) {
+            if (userID != null) {
+                return PropertyStates.createProperty(name, userID, STRING);
+            }
+        }
+
+        // does the definition have a default value?
+        PropertyState values = definition.getProperty(JCR_DEFAULTVALUES);
+        if (values != null) {
+            Type<?> type = values.getType();
+            if (getBoolean(definition, JCR_MULTIPLE)) {
+                return PropertyStates.createProperty(
+                        name, values.getValue(type), type);
+            } else if (values.count() > 0) {
+                type = type.getBaseType();
+                return PropertyStates.createProperty(
+                        name, values.getValue(type, 0), type);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Finds the default primary type for a new child node with the given name.
+     *
+     * @param typeRoot root of the {@code /jcr:system/jcr:nodeTypes} tree
+     * @param parent parent node
+     * @param childName name of the new child node
+     * @return name of the default type, or {@code null} if not available
+     */
+    public static String getDefaultChildType(
+            Tree typeRoot, Tree parent, String childName) {
+        String name = dropIndexFromName(childName);
+        boolean sns = !name.equals(childName);
+        List<Tree> types = getEffectiveType(parent, typeRoot);
+
+        // first look for named node definitions
+        for (Tree type : types) {
+            Tree definitions = type
+                    .getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS)
+                    .getChild(name);
+            String defaultName = findDefaultPrimaryType(definitions, sns);
+            if (defaultName != null) {
+                return defaultName;
+            }
+        }
+
+        // then check residual definitions
+        for (Tree type : types) {
+            Tree definitions = type
+                    .getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+            String defaultName = findDefaultPrimaryType(definitions, sns);
+            if (defaultName != null) {
+                return defaultName;
+            }
+        }
+
+        // no matching child node definition found
+        return null;
+    }
+
+    /**
+     * Returns the effective node types of the given node.
+     */
+    public static List<Tree> getEffectiveType(Tree tree, Tree typeRoot) {
+        List<Tree> types = newArrayList();
+
+        String primary = getName(tree, JCR_PRIMARYTYPE);
+        if (primary != null) {
+            Tree type = typeRoot.getChild(primary);
+            if (type.exists()) {
+                types.add(type);
+            }
+        }
+
+        for (String mixin : getNames(tree, JCR_MIXINTYPES)) {
+            Tree type = typeRoot.getChild(mixin);
+            if (type.exists()) {
+                types.add(type);
+            }
+        }
+
+        return types;
+    }
+
+    public static String findDefaultPrimaryType(Tree definitions, boolean sns) {
+        for (Tree definition : definitions.getChildren()) {
+            String defaultName = getName(definition, JCR_DEFAULTPRIMARYTYPE);
+            if (defaultName != null
+                    && (!sns || getBoolean(definition, JCR_SAMENAMESIBLINGS))) {
+                return defaultName;
+            }
+        }
+        return null;
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Mon Jul 22 15:16:57 2013
@@ -63,41 +63,19 @@
       org.apache.jackrabbit.test.api.WorkspaceMoveSameNameSibsTest                                     <!-- OAK-118 -->
       org.apache.jackrabbit.test.api.WorkspaceMoveTest#testMoveNodesLocked                             <!-- OAK-118 -->
       org.apache.jackrabbit.test.api.WorkspaceMoveTest#testMoveNodesAccessDenied                       <!-- OAK-118 -->
-      org.apache.jackrabbit.test.api.CheckPermissionTest
-      org.apache.jackrabbit.test.api.DocumentViewImportTest#testSameUUIDAtAncestorWorkspaceHandler              <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.DocumentViewImportTest#testSameUUIDAtAncestorWorkspace                     <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionGetImportContentHandler                  <!-- OAK-127: no workspace import yet, test method is misnamed -->
-      org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceImportXml                              <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileParentWorkspaceContentHandler <!-- OAK-127: no workspace import yet, NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileParentSessionContentHandler   <!-- OAK-127: NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileParentWorkspace               <!-- OAK-127: no workspace import yet, NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileParentSession                 <!-- OAK-127: NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileChildWorkspaceContentHandler  <!-- OAK-127: no workspace import yet, NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileChildSessionContentHandler    <!-- OAK-127: NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileChildWorkspace                <!-- OAK-127: no workspace import yet, NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testVersioningExceptionFileChildSession                  <!-- OAK-127: NodeImpl.checkin() not implemented -->
-      org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionWorkspaceWithHandler                    <!-- OAK-127: no workspace import yet, no session scoped locking -->
+
+      <!-- locking not implemented -->
+      org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionWorkspaceWithHandler                    <!-- OAK-127: no session scoped locking -->
       org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionSessionWithHandler                      <!-- OAK-127: no session scoped locking -->
-      org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionWorkspace                               <!-- OAK-127: no workspace import yet, no session scoped locking -->
+      org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionWorkspace                               <!-- OAK-127: no session scoped locking -->
       org.apache.jackrabbit.test.api.SerializationTest#testLockExceptionSession                                 <!-- OAK-127: no session scoped locking -->
-      org.apache.jackrabbit.test.api.SerializationTest#testWorkspaceGetImportContentHandlerExceptions           <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testWorkspaceImportXmlExceptions                         <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionWorkspaceWithHandler               <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionWorkspace                          <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testNodeTypeConstraintViolationWorkspaceWithHandler      <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testNodeTypeConstraintViolationWorkspace                 <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testStreamHandling                                       <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testInvalidXmlThrowsSaxException                         <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testInvalidXmlThrowsInvalidSerializedDataException       <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_stream_workspace_skipBinary_noRecurse  <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_stream_workspace_skipBinary_recurse    <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_stream_workspace_saveBinary_noRecurse  <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_stream_workspace_saveBinary_recurse    <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_handler_workspace_skipBinary_noRecurse <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_handler_workspace_skipBinary_recurse   <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_handler_workspace_saveBinary_noRecurse <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.SerializationTest#testExportSysView_handler_workspace_saveBinary_recurse   <!-- OAK-127: no workspace import yet -->
-      org.apache.jackrabbit.test.api.HasPermissionTest
+
+      <!-- overwrite not detected during import -->
+      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionWorkspaceWithHandler               <!-- OAK-127: overwrite -->
+      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionSessionWithHandler                 <!-- OAK-127: overwrite -->
+      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionWorkspace                          <!-- OAK-127: overwrite -->
+      org.apache.jackrabbit.test.api.SerializationTest#testOverwriteExceptionSession                            <!-- OAK-127: overwrite -->
+
       org.apache.jackrabbit.test.api.lock.LockManagerTest#testAddInvalidLockToken                      <!-- OAK-150 ... -->
       org.apache.jackrabbit.test.api.lock.LockManagerTest#testLockNonLockable
       org.apache.jackrabbit.test.api.lock.LockTest#testGetNode
@@ -282,7 +260,6 @@
       org.apache.jackrabbit.oak.jcr.security.authorization.NodeTypeManagementTest#testCopy                          <!-- OAK-711 -->
       org.apache.jackrabbit.oak.jcr.security.authorization.NodeTypeManagementTest#testWorkspaceMove                 <!-- OAK-711 -->
       org.apache.jackrabbit.oak.jcr.security.authorization.NodeTypeManagementTest#testSessionMove                   <!-- OAK-711 -->
-      org.apache.jackrabbit.oak.jcr.security.authorization.NodeTypeManagementTest#testWorkspaceImportXML            <!-- OAK-773 -->
       org.apache.jackrabbit.oak.jcr.security.authorization.WriteTest#testWriteOnParentWithNoReadePriv               <!-- OAK-869 -->
 
       org.apache.jackrabbit.oak.jcr.security.authorization.VersionManagementTest#testRemoveVersion   <!-- OAK-168 -->
@@ -294,7 +271,7 @@
       org.apache.jackrabbit.oak.jcr.security.authorization.CopyTest#testCopyInvisibleProperty        <!-- OAK-920 -->
       org.apache.jackrabbit.oak.jcr.security.authorization.CopyTest#testCopyInvisibleAcContent       <!-- OAK-920 -->
 
-      org.apache.jackrabbit.oak.jcr.security.user.MemberNodeImportTest <!-- OAK-414, OAK-482 -->
+      org.apache.jackrabbit.oak.jcr.security.user.MemberNodeImportTest                        <!-- OAK-414, OAK-482 -->
       org.apache.jackrabbit.oak.jcr.security.user.UserImportTest#testImportGroupIntoUsersTree <!-- OAK-821 -->
 
       org.apache.jackrabbit.core.query.ExcerptTest#testMoreTextDotsAtEnd                      <!-- OAK-318 -->

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionContext.java Mon Jul 22 15:16:57 2013
@@ -16,12 +16,9 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.PathNotFoundException;
@@ -68,6 +65,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Instances of this class are passed to all JCR implementation classes
  * (e.g. {@code SessionImpl}, {@code NodeImpl}, etc.) and provide access to
@@ -317,12 +316,22 @@ public class SessionContext implements N
         }
     }
 
-    //-----------------------------------------------------------< internal >---
+    public void refresh(boolean includeRoot) {
+        if (includeRoot) {
+            getSessionDelegate().getRoot().refresh();
+        }
+        if (permissionProvider != null) {
+            permissionProvider.refresh();
+        }
+    }
+
     @Nonnull
-    AccessManager getAccessManager() throws RepositoryException {
+    public AccessManager getAccessManager() throws RepositoryException {
         return new AccessManager(getPermissionProvider());
     }
 
+    //-----------------------------------------------------------< internal >---
+
     void dispose() {
         if (observationManager != null) {
             observationManager.dispose();
@@ -330,12 +339,6 @@ public class SessionContext implements N
         namespaces.clear();
     }
 
-    void refresh() {
-        if (permissionProvider != null) {
-            permissionProvider.refresh();
-        }
-    }
-
     //------------------------------------------------------------< private >---
     @Nonnull
     private PermissionProvider getPermissionProvider() {

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=1505715&r1=1505714&r2=1505715&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 Mon Jul 22 15:16:57 2013
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.jcr;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.security.AccessControlException;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.AccessDeniedException;
@@ -37,7 +38,6 @@ import javax.jcr.ValueFactory;
 import javax.jcr.Workspace;
 import javax.jcr.lock.LockManager;
 import javax.jcr.retention.RetentionManager;
-import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlManager;
 
 import org.apache.jackrabbit.api.JackrabbitSession;
@@ -382,7 +382,7 @@ public class SessionImpl implements Jack
             @Override
             protected Void perform() throws RepositoryException {
                 sd.save();
-                sessionContext.refresh();
+                sessionContext.refresh(false);
                 return null;
             }
         });
@@ -394,7 +394,7 @@ public class SessionImpl implements Jack
             @Override
             protected Void perform() throws RepositoryException {
                 sd.refresh(keepChanges);
-                sessionContext.refresh();
+                sessionContext.refresh(false);
                 return null;
             }
 
@@ -429,7 +429,7 @@ public class SessionImpl implements Jack
     @Nonnull
     public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior)
             throws RepositoryException {
-        return new ImportHandler(getNode(parentAbsPath), sessionContext, uuidBehavior);
+        return new ImportHandler(parentAbsPath, sessionContext, sd.getRoot(), uuidBehavior, false);
     }
 
     @Override

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=1505715&r1=1505714&r2=1505715&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 Mon Jul 22 15:16:57 2013
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.jcr;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.annotation.Nonnull;
+import javax.jcr.InvalidSerializedDataException;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
@@ -34,18 +35,22 @@ import javax.jcr.version.VersionManager;
 
 import org.apache.jackrabbit.api.JackrabbitWorkspace;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.commons.xml.ParsingContentHandler;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
 import org.apache.jackrabbit.oak.jcr.lock.LockManagerImpl;
 import org.apache.jackrabbit.oak.jcr.query.QueryManagerImpl;
 import org.apache.jackrabbit.oak.jcr.version.VersionManagerImpl;
+import org.apache.jackrabbit.oak.jcr.xml.ImportHandler;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.name.ReadWriteNamespaceRegistry;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.ReadWriteNodeTypeManager;
 import org.apache.jackrabbit.util.Text;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
 
@@ -233,16 +238,34 @@ public class WorkspaceImpl implements Ja
     public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws RepositoryException {
         ensureIsAlive();
 
-        // TODO
-        throw new UnsupportedRepositoryOperationException("TODO: Workspace.getImportContentHandler");
+        Root writeRoot = sessionContext.getSessionDelegate().getContentSession().getLatestRoot();
+        return new ImportHandler(parentAbsPath, sessionContext, writeRoot, uuidBehavior, true);
     }
 
     @Override
     public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException, RepositoryException {
         ensureIsAlive();
 
-        // TODO -> SPI
-        throw new UnsupportedRepositoryOperationException("TODO: Workspace.importXML");
+        try {
+            ContentHandler handler = getImportContentHandler(parentAbsPath, uuidBehavior);
+            new ParsingContentHandler(handler).parse(in);
+        } catch (SAXException e) {
+            Throwable exception = e.getException();
+            if (exception instanceof RepositoryException) {
+                throw (RepositoryException) exception;
+            } else if (exception instanceof IOException) {
+                throw (IOException) exception;
+            } else if (exception instanceof CommitFailedException) {
+                throw ((CommitFailedException) exception).asRepositoryException();
+            } else {
+                throw new InvalidSerializedDataException("XML parse error", e);
+            }
+        } finally {
+            // JCR-2903
+            if (in != null) {
+                try { in.close(); } catch (IOException ignore) {}
+            }
+        }
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java Mon Jul 22 15:16:57 2013
@@ -16,6 +16,30 @@
  */
 package org.apache.jackrabbit.oak.jcr.delegate;
 
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Tree.Status;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+
 import static com.google.common.base.Objects.toStringHelper;
 import static com.google.common.collect.Iterables.addAll;
 import static com.google.common.collect.Iterables.contains;
@@ -23,14 +47,7 @@ import static com.google.common.collect.
 import static com.google.common.collect.Iterators.transform;
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Sets.newHashSet;
-import static java.util.Collections.emptyList;
-import static org.apache.jackrabbit.JcrConstants.JCR_AUTOCREATED;
-import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
-import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
-import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTVALUES;
-import static org.apache.jackrabbit.JcrConstants.JCR_HASORDERABLECHILDNODES;
 import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
-import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED;
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_MULTIPLE;
 import static org.apache.jackrabbit.JcrConstants.JCR_NODETYPENAME;
@@ -40,56 +57,20 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.JCR_SAMENAMESIBLINGS;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
 import static org.apache.jackrabbit.JcrConstants.NT_BASE;
-import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
-import static org.apache.jackrabbit.oak.api.Type.DATE;
-import static org.apache.jackrabbit.oak.api.Type.NAME;
-import static org.apache.jackrabbit.oak.api.Type.NAMES;
-import static org.apache.jackrabbit.oak.api.Type.STRING;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINED;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINEDS;
 import static org.apache.jackrabbit.oak.commons.PathUtils.dropIndexFromName;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_CREATEDBY;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_LASTMODIFIEDBY;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_HAS_PROTECTED_RESIDUAL_CHILD_NODES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_HAS_PROTECTED_RESIDUAL_PROPERTIES;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MIXIN_SUBTYPES;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_PROPERTY_DEFINITIONS;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PRIMARY_SUBTYPES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PROTECTED_CHILD_NODES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PROTECTED_PROPERTIES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_PROPERTY_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_SUPERTYPES;
 
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.api.Tree.Status;
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.core.IdentifierManager;
-import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
-import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
-import org.apache.jackrabbit.oak.util.TreeUtil;
-
 /**
  * {@code NodeDelegate} serve as internal representations of {@code Node}s.
  * Most methods of this class throw an {@code InvalidItemStateException}
@@ -167,14 +148,14 @@ public class NodeDelegate extends ItemDe
         String name = dropIndexFromName(nameWithIndex);
         boolean sns = !name.equals(nameWithIndex);
         Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
-        List<Tree> types = getEffectiveType(parent, typeRoot);
+        List<Tree> types = TreeUtil.getEffectiveType(parent, typeRoot);
 
         boolean protectedResidual = false;
         for (Tree type : types) {
-            if (contains(getNames(type, OAK_PROTECTED_CHILD_NODES), name)) {
+            if (contains(TreeUtil.getNames(type, OAK_PROTECTED_CHILD_NODES), name)) {
                 return true;
             } else if (!protectedResidual) {
-                protectedResidual = getBoolean(
+                protectedResidual = TreeUtil.getBoolean(
                         type, OAK_HAS_PROTECTED_RESIDUAL_CHILD_NODES);
             }
         }
@@ -184,9 +165,9 @@ public class NodeDelegate extends ItemDe
         // there's a matching, protected one.
         if (protectedResidual) {
             Set<String> typeNames = newHashSet();
-            for (Tree type : getEffectiveType(tree, typeRoot)) {
-                typeNames.add(getName(type, JCR_NODETYPENAME));
-                addAll(typeNames, getNames(type, OAK_SUPERTYPES));
+            for (Tree type : TreeUtil.getEffectiveType(tree, typeRoot)) {
+                typeNames.add(TreeUtil.getName(type, JCR_NODETYPENAME));
+                addAll(typeNames, TreeUtil.getNames(type, OAK_SUPERTYPES));
             }
 
             for (Tree type : types) {
@@ -194,8 +175,8 @@ public class NodeDelegate extends ItemDe
                         type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
                 for (String typeName : typeNames) {
                     Tree definition = definitions.getChild(typeName);
-                    if ((!sns || getBoolean(definition, JCR_SAMENAMESIBLINGS))
-                            && getBoolean(definition, JCR_PROTECTED)) {
+                    if ((!sns || TreeUtil.getBoolean(definition, JCR_SAMENAMESIBLINGS))
+                            && TreeUtil.getBoolean(definition, JCR_PROTECTED)) {
                         return true;
                     }
                 }
@@ -208,14 +189,14 @@ public class NodeDelegate extends ItemDe
     boolean isProtected(String property) throws InvalidItemStateException {
         Tree tree = getTree();
         Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
-        List<Tree> types = getEffectiveType(tree, typeRoot);
+        List<Tree> types = TreeUtil.getEffectiveType(tree, typeRoot);
 
         boolean protectedResidual = false;
         for (Tree type : types) {
-            if (contains(getNames(type, OAK_PROTECTED_PROPERTIES), property)) {
+            if (contains(TreeUtil.getNames(type, OAK_PROTECTED_PROPERTIES), property)) {
                 return true;
             } else if (!protectedResidual) {
-                protectedResidual = getBoolean(
+                protectedResidual = TreeUtil.getBoolean(
                         type, OAK_HAS_PROTECTED_RESIDUAL_PROPERTIES);
             }
         }
@@ -228,7 +209,7 @@ public class NodeDelegate extends ItemDe
                 Tree definitions = type.getChild(OAK_RESIDUAL_PROPERTY_DEFINITIONS);
                 for (Tree definition : definitions.getChildren()) {
                     // TODO: check for matching property type?
-                    if (getBoolean(definition, JCR_PROTECTED)) {
+                    if (TreeUtil.getBoolean(definition, JCR_PROTECTED)) {
                         return true;
                     }
                 }
@@ -376,8 +357,8 @@ public class NodeDelegate extends ItemDe
     public boolean canAddMixin(String typeName) throws RepositoryException {
         Tree type = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH).getChild(typeName);
         if (type.exists()) {
-            return !getBoolean(type, JCR_IS_ABSTRACT)
-                    && getBoolean(type, JCR_ISMIXIN);
+            return !TreeUtil.getBoolean(type, JCR_IS_ABSTRACT)
+                    && TreeUtil.getBoolean(type, JCR_ISMIXIN);
         } else {
             throw new NoSuchNodeTypeException(
                     "Node type " + typeName + " does not exist");
@@ -385,38 +366,7 @@ public class NodeDelegate extends ItemDe
     }
 
     public void addMixin(String typeName) throws RepositoryException {
-        Tree type = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH).getChild(typeName);
-        if (!type.exists()) {
-            throw new NoSuchNodeTypeException(
-                    "Node type " + typeName + " does not exist");
-        } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
-            throw new ConstraintViolationException(
-                    "Node type " + typeName + " is abstract");
-        } else if (!getBoolean(type, JCR_ISMIXIN)) {
-            throw new ConstraintViolationException(
-                    "Node type " + typeName + " is a not a mixin type");
-        }
-
-        Tree tree = getTree();
-        List<String> mixins = newArrayList();
-
-        String primary = getName(tree, JCR_PRIMARYTYPE);
-        if (primary != null
-                && contains(getNames(type, OAK_PRIMARY_SUBTYPES), primary)) {
-            return;
-        }
-
-        Set<String> subMixins = newHashSet(getNames(type, OAK_MIXIN_SUBTYPES));
-        for (String mixin : getNames(tree, JCR_MIXINTYPES)) {
-            if (typeName.equals(mixin) || subMixins.contains(mixin)) {
-                return;
-            }
-            mixins.add(mixin);
-        }
-
-        mixins.add(typeName);
-        tree.setProperty(JCR_MIXINTYPES, mixins, NAMES);
-        autoCreateItems(tree, type, sessionDelegate.getRoot().getTree(NODE_TYPES_PATH));
+        TreeUtil.addMixin(getTree(), typeName, sessionDelegate.getRoot().getTree(NODE_TYPES_PATH), getUserID());
     }
 
     /**
@@ -450,14 +400,14 @@ public class NodeDelegate extends ItemDe
         if (definition == null) {
             throw new ConstraintViolationException(
                     "No matching property definition: " + propertyState);
-        } else if (!setProtected && getBoolean(definition, JCR_PROTECTED)) {
+        } else if (!setProtected && TreeUtil.getBoolean(definition, JCR_PROTECTED)) {
             throw new ConstraintViolationException(
                     "Property is protected: " + propertyState);
         }
         Type<?> requiredType =
-                Type.fromString(getString(definition, JCR_REQUIREDTYPE));
+                Type.fromString(TreeUtil.getString(definition, JCR_REQUIREDTYPE));
         if (requiredType != Type.UNDEFINED) {
-            if (getBoolean(definition, JCR_MULTIPLE)) {
+            if (TreeUtil.getBoolean(definition, JCR_MULTIPLE)) {
                 requiredType = requiredType.getArrayType();
             }
             propertyState = PropertyStates.convert(propertyState, requiredType);
@@ -474,12 +424,12 @@ public class NodeDelegate extends ItemDe
 
         // Find applicable node types
         List<Tree> types = newArrayList();
-        String primaryName = getName(tree, JCR_PRIMARYTYPE);
+        String primaryName = TreeUtil.getName(tree, JCR_PRIMARYTYPE);
         if (primaryName == null) {
             primaryName = NT_BASE;
         }
         types.add(typeRoot.getChild(primaryName));
-        for (String mixinName : getNames(tree, JCR_MIXINTYPES)) {
+        for (String mixinName : TreeUtil.getNames(tree, JCR_MIXINTYPES)) {
             types.add(typeRoot.getChild(mixinName));
         }
 
@@ -516,7 +466,7 @@ public class NodeDelegate extends ItemDe
             }
             if (!exactTypeMatch) {
                 for (Tree def : definitions.getChildren()) {
-                    if (propertyType.isArray() == getBoolean(def, JCR_MULTIPLE)) {
+                    if (propertyType.isArray() == TreeUtil.getBoolean(def, JCR_MULTIPLE)) {
                         return def;
                     }
                 }
@@ -536,7 +486,7 @@ public class NodeDelegate extends ItemDe
             }
             if (!exactTypeMatch) {
                 for (Tree def : definitions.getChildren()) {
-                    if (propertyType.isArray() == getBoolean(def, JCR_MULTIPLE)) {
+                    if (propertyType.isArray() == TreeUtil.getBoolean(def, JCR_MULTIPLE)) {
                         return def;
                     }
                 }
@@ -564,7 +514,7 @@ public class NodeDelegate extends ItemDe
 
         Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
         if (typeName == null) {
-            typeName = getDefaultChildType(typeRoot, tree, name);
+            typeName = TreeUtil.getDefaultChildType(typeRoot, tree, name);
             if (typeName == null) {
                 throw new ConstraintViolationException(
                         "No default node type available for node "
@@ -605,191 +555,7 @@ public class NodeDelegate extends ItemDe
     private Tree internalAddChild(
             Tree parent, String name, String typeName, Tree typeRoot)
             throws RepositoryException {
-        Tree type = typeRoot.getChild(typeName);
-        if (!type.exists()) {
-            throw new NoSuchNodeTypeException(
-                    "Node type " + typeName + " does not exist");
-        } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
-            throw new ConstraintViolationException(
-                    "Node type " + typeName + " is abstract");
-        } else if (getBoolean(type, JCR_ISMIXIN)) {
-            throw new ConstraintViolationException(
-                    "Node type " + typeName + " is a mixin type");
-        }
-
-        Tree child = parent.addChild(name);
-        child.setProperty(JCR_PRIMARYTYPE, typeName, NAME);
-        if (getBoolean(type, JCR_HASORDERABLECHILDNODES)) {
-            child.setOrderableChildren(true);
-        }
-        autoCreateItems(child, type, typeRoot);
-        return child;
-    }
-
-    private void autoCreateItems(Tree tree, Tree type, Tree typeRoot)
-            throws RepositoryException {
-        // TODO: use a separate oak:autoCreatePropertyDefinitions
-        Tree properties = type.getChild(OAK_NAMED_PROPERTY_DEFINITIONS);
-        for (Tree definitions : properties.getChildren()) {
-            String name = definitions.getName();
-            if (name.equals("oak:primaryType")
-                    || name.equals("oak:mixinTypes")) {
-                continue;
-            } else if (name.equals("oak:uuid")) {
-                name = JCR_UUID;
-            }
-            for (Tree definition : definitions.getChildren()) {
-                if (getBoolean(definition, JCR_AUTOCREATED)) {
-                    if (!tree.hasProperty(name)) {
-                        PropertyState property =
-                                autoCreateProperty(name, definition);
-                        if (property != null) {
-                            tree.setProperty(property);
-                        } else {
-                            throw new RepositoryException(
-                                    "Unable to auto-create value for "
-                                    + PathUtils.concat(tree.getPath(), name));
-                        }
-                    }
-                    break;
-                }
-            }
-        }
-
-        // TODO: use a separate oak:autoCreateChildNodeDefinitions
-        // Note that we use only named, non-SNS child node definitions
-        // as there can be no reasonable default values for residual or
-        // SNS child nodes
-        Tree childNodes = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
-        for (Tree definitions : childNodes.getChildren()) {
-            String name = definitions.getName();
-            for (Tree definition : definitions.getChildren()) {
-                if (getBoolean(definition, JCR_AUTOCREATED)) {
-                    if (!tree.hasChild(name)) {
-                        String typeName =
-                                getName(definition, JCR_DEFAULTPRIMARYTYPE);
-                        internalAddChild(tree, name, typeName, typeRoot);
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-    private PropertyState autoCreateProperty(String name, Tree definition) {
-        if (JCR_UUID.equals(name)) {
-            String uuid = IdentifierManager.generateUUID();
-            return PropertyStates.createProperty(name, uuid, STRING);
-        } else if (JCR_CREATED.equals(name)) {
-            long now = Calendar.getInstance().getTime().getTime();
-            return PropertyStates.createProperty(name, now, DATE);
-        } else if (JCR_CREATEDBY.equals(name)) {
-            String userID = sessionDelegate.getAuthInfo().getUserID();
-            if (userID != null) {
-                return PropertyStates.createProperty(name, userID, STRING);
-            }
-        } else if (JCR_LASTMODIFIED.equals(name)) {
-            long now = Calendar.getInstance().getTime().getTime();
-            return PropertyStates.createProperty(name, now, DATE);
-        } else if (JCR_LASTMODIFIEDBY.equals(name)) {
-            String userID = sessionDelegate.getAuthInfo().getUserID();
-            if (userID != null) {
-                return PropertyStates.createProperty(name, userID, STRING);
-            }
-        }
-
-        // does the definition have a default value?
-        PropertyState values = definition.getProperty(JCR_DEFAULTVALUES);
-        if (values != null) {
-            Type<?> type = values.getType();
-            if (getBoolean(definition, JCR_MULTIPLE)) {
-                return PropertyStates.createProperty(
-                        name, values.getValue(type), type);
-            } else if (values.count() > 0) {
-                type = type.getBaseType();
-                return PropertyStates.createProperty(
-                        name, values.getValue(type, 0), type);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Finds the default primary type for a new child node with the given name.
-     *
-     * @param typeRoot root of the {@code /jcr:system/jcr:nodeTypes} tree
-     * @param parent parent node
-     * @param childName name of the new child node
-     * @return name of the default type, or {@code null} if not available
-     */
-    private static String getDefaultChildType(
-            Tree typeRoot, Tree parent, String childName) {
-        String name = dropIndexFromName(childName);
-        boolean sns = !name.equals(childName);
-        List<Tree> types = getEffectiveType(parent, typeRoot);
-
-        // first look for named node definitions
-        for (Tree type : types) {
-            Tree definitions = type
-                    .getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS)
-                    .getChild(name);
-            String defaultName =
-                    findDefaultPrimaryType(typeRoot, definitions, sns);
-            if (defaultName != null) {
-                return defaultName;
-            }
-        }
-
-        // then check residual definitions
-        for (Tree type : types) {
-            Tree definitions = type
-                    .getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
-            String defaultName =
-                    findDefaultPrimaryType(typeRoot, definitions, sns);
-            if (defaultName != null) {
-                return defaultName;
-            }
-        }
-
-        // no matching child node definition found
-        return null;
-    }
-
-    /**
-     * Returns the effective node types of the given node.
-     */
-    private static List<Tree> getEffectiveType(Tree tree, Tree typeRoot) {
-        List<Tree> types = newArrayList();
-
-        String primary = getName(tree, JCR_PRIMARYTYPE);
-        if (primary != null) {
-            Tree type = typeRoot.getChild(primary);
-            if (type.exists()) {
-                types.add(type);
-            }
-        }
-
-        for (String mixin : getNames(tree, JCR_MIXINTYPES)) {
-            Tree type = typeRoot.getChild(mixin);
-            if (type.exists()) {
-                types.add(type);
-            }
-        }
-
-        return types;
-    }
-
-    private static String findDefaultPrimaryType(
-            Tree typeRoot, Tree definitions, boolean sns) {
-        for (Tree definition : definitions.getChildren()) {
-            String defaultName = getName(definition, JCR_DEFAULTPRIMARYTYPE);
-            if (defaultName != null
-                    && (!sns || getBoolean(definition, JCR_SAMENAMESIBLINGS))) {
-                return defaultName;
-            }
-        }
-        return null;
+        return TreeUtil.addChild(parent, name, typeName, typeRoot, getUserID());
     }
 
     @Nonnull // FIXME this should be package private. OAK-672
@@ -810,42 +576,7 @@ public class NodeDelegate extends ItemDe
         return TreeUtil.getTree(tree, relPath);
     }
 
-    // Generic property value accessors. TODO: add to Tree?
-
-    private static boolean getBoolean(Tree tree, String name) {
-        PropertyState property = tree.getProperty(name);
-        return property != null
-                && property.getType() == BOOLEAN
-                && property.getValue(BOOLEAN);
-    }
-
-    @CheckForNull
-    private static String getString(Tree tree, String name) {
-        PropertyState property = tree.getProperty(name);
-        if (property != null && property.getType() == STRING) {
-            return property.getValue(STRING);
-        } else {
-            return null;
-        }
-    }
-
-    @CheckForNull
-    private static String getName(Tree tree, String name) {
-        PropertyState property = tree.getProperty(name);
-        if (property != null && property.getType() == NAME) {
-            return property.getValue(NAME);
-        } else {
-            return null;
-        }
-    }
-
-    @Nonnull
-    private static Iterable<String> getNames(Tree tree, String name) {
-        PropertyState property = tree.getProperty(name);
-        if (property != null && property.getType() == NAMES) {
-            return property.getValue(NAMES);
-        } else {
-            return emptyList();
-        }
+    private String getUserID() {
+        return sessionDelegate.getAuthInfo().getUserID();
     }
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java Mon Jul 22 15:16:57 2013
@@ -16,24 +16,12 @@
  */
 package org.apache.jackrabbit.oak.jcr.delegate;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.MINUTES;
-
 import java.io.IOException;
-
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.InvalidItemStateException;
 import javax.jcr.ItemExistsException;
 import javax.jcr.PathNotFoundException;
-import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.RepositoryException;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.version.VersionException;
 
 import org.apache.jackrabbit.oak.api.AuthInfo;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -48,6 +36,10 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+
 /**
  * TODO document
  */
@@ -389,24 +381,7 @@ public class SessionDelegate {
      * @return matching repository exception
      */
     private static RepositoryException newRepositoryException(CommitFailedException exception) {
-        checkNotNull(exception);
-        if (exception.isConstraintViolation()) {
-            return new ConstraintViolationException(exception);
-        } else if (exception.isOfType("Type")) {
-            return new NoSuchNodeTypeException(exception);
-        } else if (exception.isAccessViolation()) {
-            return new AccessDeniedException(exception);
-        } else if (exception.isOfType("Integrity")) {
-            return new ReferentialIntegrityException(exception);
-        } else if (exception.isOfType("State")) {
-            return new InvalidItemStateException(exception);
-        } else if (exception.isOfType("Version")) {
-            return new VersionException(exception);
-        } else if (exception.isOfType("Lock")) {
-            return new LockException(exception);
-        } else {
-            return new RepositoryException(exception);
-        }
+        return exception.asRepositoryException();
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/DocViewImportHandler.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/DocViewImportHandler.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/DocViewImportHandler.java Mon Jul 22 15:16:57 2013
@@ -29,6 +29,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
 
+import com.google.common.collect.Lists;
 import org.apache.jackrabbit.commons.NamespaceHelper;
 import org.apache.jackrabbit.oak.namepath.JcrNameParser;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceConstants;
@@ -78,14 +79,14 @@ class DocViewImportHandler extends Targe
      * @return the parsed names
      * @throws SAXException if an invalid name was encountered
      */
-    private String[] parseNames(String value) throws SAXException {
+    private Iterable<String> parseNames(String value) throws SAXException {
         String[] names = value.split("\\p{Space}+");
-        String[] qnames = new String[names.length];
-        for (int i = 0; i < names.length; i++) {
+        List<String> qnames = Lists.newArrayListWithCapacity(names.length);
+        for (String name : names) {
             try {
-                qnames[i] = new NameInfo(names[i]).getRepoQualifiedName();
+                qnames.add(new NameInfo(name).getRepoQualifiedName());
             } catch (RepositoryException e) {
-                throw new SAXException("Invalid name: " + names[i], e);
+                throw new SAXException("Invalid name: " + name, e);
             }
         }
         return qnames;
@@ -224,7 +225,7 @@ class DocViewImportHandler extends Targe
             // properties
             String id = null;
             String nodeTypeName = null;
-            String[] mixinTypes = null;
+            Iterable<String> mixinTypes = null;
 
             List<PropInfo> props = new ArrayList<PropInfo>(atts.getLength());
             for (int i = 0; i < atts.getLength(); i++) {

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImportHandler.java?rev=1505715&r1=1505714&r2=1505715&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImportHandler.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImportHandler.java Mon Jul 22 15:16:57 2013
@@ -18,12 +18,12 @@ package org.apache.jackrabbit.oak.jcr.xm
 
 import java.util.HashMap;
 import java.util.Map;
-
-import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.ValueFactory;
 
 import org.apache.jackrabbit.commons.NamespaceHelper;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.jcr.SessionContext;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceConstants;
 import org.slf4j.Logger;
@@ -53,17 +53,26 @@ import org.xml.sax.helpers.DefaultHandle
 public class ImportHandler extends DefaultHandler {
     private static final Logger log = LoggerFactory.getLogger(ImportHandler.class);
 
+    private final Root root;
+    private final SessionContext sessionContext;
     private final Importer importer;
     private final NamespaceHelper helper;
     private final ValueFactory valueFactory;
+    private final boolean isWorkspaceImport;
+
     protected Locator locator;
     private TargetImportHandler targetHandler;
     private final Map<String, String> tempPrefixMap = new HashMap<String, String>();
 
-    public ImportHandler(Node importTargetNode, SessionContext sessionContext, int uuidBehavior) {
+    public ImportHandler(String absPath, SessionContext sessionContext,
+                         Root root, int uuidBehavior, boolean isWorkspaceImport)
+            throws RepositoryException {
+        this.root = root;
+        this.sessionContext = sessionContext;
         this.helper = new NamespaceHelper(sessionContext.getSession());
-        this.importer = new SessionImporter(importTargetNode, sessionContext, helper, uuidBehavior);
+        this.importer = new ImporterImpl(absPath, sessionContext, root, uuidBehavior, isWorkspaceImport);
         this.valueFactory = sessionContext.getValueFactory();
+        this.isWorkspaceImport = isWorkspaceImport;
     }
 
     //---------------------------------------------------------< ErrorHandler >
@@ -101,6 +110,14 @@ public class ImportHandler extends Defau
         if (targetHandler != null) {
             targetHandler.endDocument();
         }
+        if (isWorkspaceImport) {
+            try {
+                root.commit();
+                sessionContext.refresh(true);
+            } catch (CommitFailedException e) {
+                throw new SAXException(e);
+            }
+        }
     }
 
     /**