You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/10/21 13:38:44 UTC

svn commit: r827966 [2/15] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/management/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/...

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Wed Oct 21 11:38:31 2009
@@ -29,23 +29,20 @@
 import javax.jcr.PathNotFoundException;
 import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeDefinition;
-import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.nodetype.ConstraintViolationException;
 
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
-import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
+import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.ItemStateListener;
-import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
@@ -55,7 +52,11 @@
 import org.apache.jackrabbit.core.version.VersionImpl;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -86,12 +87,12 @@
 
     private static Logger log = LoggerFactory.getLogger(ItemManager.class);
 
-    private final NodeDefinition rootNodeDef;
+    private final org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl rootNodeDef;
     private final NodeId rootNodeId;
 
     protected final SessionImpl session;
 
-    private final ItemStateManager itemStateProvider;
+    private final SessionItemStateManager sism;
     private final HierarchyManager hierMgr;
 
     /**
@@ -107,17 +108,19 @@
     /**
      * Creates a new per-session instance <code>ItemManager</code> instance.
      *
-     * @param itemStateProvider the item state provider associated with
-     *                          the new instance
-     * @param hierMgr           the hierarchy manager
-     * @param session           the session associated with the new instance
-     * @param rootNodeDef       the definition of the root node
-     * @param rootNodeId        the id of the root node
-     */
-    protected ItemManager(SessionItemStateManager itemStateProvider, HierarchyManager hierMgr,
-                          SessionImpl session, NodeDefinition rootNodeDef,
+     * @param sism        the item state manager associated with the new
+     *                    instance
+     * @param hierMgr     the hierarchy manager
+     * @param session     the session associated with the new instance
+     * @param rootNodeDef the definition of the root node
+     * @param rootNodeId  the id of the root node
+     */
+    protected ItemManager(SessionItemStateManager sism,
+                          HierarchyManager hierMgr,
+                          SessionImpl session,
+                          org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl rootNodeDef,
                           NodeId rootNodeId) {
-        this.itemStateProvider = itemStateProvider;
+        this.sism = sism;
         this.hierMgr = hierMgr;
         this.session = session;
         this.rootNodeDef = rootNodeDef;
@@ -145,7 +148,7 @@
             SessionItemStateManager itemStateProvider,
             HierarchyManager hierMgr,
             SessionImpl session,
-            NodeDefinition rootNodeDef,
+            org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl rootNodeDef,
             NodeId rootNodeId) {
         ItemManager mgr = new ItemManager(itemStateProvider, hierMgr,
                 session, rootNodeDef, rootNodeId);
@@ -163,52 +166,106 @@
         shareableNodesCache.clear();
     }
 
-    NodeDefinition getDefinition(NodeState state)
+    NodeDefinitionImpl getDefinition(NodeState state)
             throws RepositoryException {
         if (state.getId().equals(rootNodeId)) {
             // special handling required for root node
             return rootNodeDef;
         }
 
-        NodeDefId defId = state.getDefinitionId();
-        NodeDefinitionImpl def = session.getNodeTypeManager().getNodeDefinition(defId);
-        if (def == null) {
-            /**
-             * todo need proper way of handling inconsistent/corrupt definition
-             * e.g. 'flag' items that refer to non-existent definitions
-             */
-            log.warn("node at " + safeGetJCRPath(state.getNodeId())
-                    + " has invalid definitionId (" + defId + ")");
+        NodeId parentId = state.getParentId();
+        if (parentId == null) {
+            // removed state has parentId set to null
+            // get from overlayed state
+            parentId = state.getOverlayedState().getParentId();
+        }
+        NodeState parentState = null;
+        try {
+            NodeImpl parent = (NodeImpl) getItem(parentId);
+            parentState = parent.getNodeState();
+            if (state.getParentId() == null) {
+                // indicates state has been removed, must use
+                // overlayed state of parent, otherwise child node entry
+                // cannot be found. unless the parentState is new, which
+                // means it was recreated in place of a removed node
+                // that used to be the actual parent
+                if (parentState.getStatus() == ItemState.STATUS_NEW) {
+                    // force getting parent from attic
+                    parentState = null;
+                } else {
+                    parentState = (NodeState) parentState.getOverlayedState();
+                }
+            }
+        } catch (ItemNotFoundException e) {
+            // parent probably removed, get it from attic. see below
+        }
 
-            // fallback: try finding applicable definition
-            NodeImpl parent = (NodeImpl) getItem(state.getParentId());
-            NodeState parentState = parent.getNodeState();
-            ChildNodeEntry cne = parentState.getChildNodeEntry(state.getNodeId());
-            def = parent.getApplicableChildNodeDefinition(cne.getName(), state.getNodeTypeName());
-            state.setDefinitionId(def.unwrap().getId());
+        if (parentState == null) {
+            try {
+                // use overlayed state if available
+                parentState = (NodeState) sism.getAttic().getItemState(
+                        parentId).getOverlayedState();
+            } catch (ItemStateException ex) {
+                throw new RepositoryException(ex);
+            }
+        }
+
+        // get child node entry
+        ChildNodeEntry cne = parentState.getChildNodeEntry(state.getNodeId());
+        NodeTypeRegistry ntReg = session.getNodeTypeManager().getNodeTypeRegistry();
+        try {
+            EffectiveNodeType ent = ntReg.getEffectiveNodeType(
+                    parentState.getNodeTypeName(), parentState.getMixinTypeNames());
+            QNodeDefinition def;
+            try {
+                def = ent.getApplicableChildNodeDef(
+                    cne.getName(), state.getNodeTypeName(), ntReg);
+            } catch (ConstraintViolationException e) {
+                // fallback to child node definition of a nt:unstructured
+                ent = ntReg.getEffectiveNodeType(NameConstants.NT_UNSTRUCTURED);
+                def = ent.getApplicableChildNodeDef(
+                        cne.getName(), state.getNodeTypeName(), ntReg);
+                log.warn("Fallback to nt:unstructured due to unknown child " +
+                        "node definition for type '" + state.getNodeTypeName() + "'");
+            }
+            return session.getNodeTypeManager().getNodeDefinition(def);
+        } catch (NodeTypeConflictException e) {
+            throw new RepositoryException(e);
         }
-        return def;
     }
 
-    PropertyDefinition getDefinition(PropertyState state)
+    PropertyDefinitionImpl getDefinition(PropertyState state)
             throws RepositoryException {
-        PropDefId defId = state.getDefinitionId();
-        PropertyDefinitionImpl def = session.getNodeTypeManager().getPropertyDefinition(defId);
-        if (def == null) {
-            /**
-             * todo need proper way of handling inconsistent/corrupt definition
-             * e.g. 'flag' items that refer to non-existent definitions
-             */
-            log.warn("property at " + safeGetJCRPath(state.getPropertyId())
-                    + " has invalid definitionId (" + defId + ")");
-
-            // fallback: try finding applicable definition
+        try {
             NodeImpl parent = (NodeImpl) getItem(state.getParentId());
-            def = parent.getApplicablePropertyDefinition(
+            return parent.getApplicablePropertyDefinition(
                     state.getName(), state.getType(), state.isMultiValued(), true);
-            state.setDefinitionId(def.unwrap().getId());
+        } catch (ItemNotFoundException e) {
+            // parent probably removed, get it from attic
+        }
+        try {
+            NodeState parent = (NodeState) sism.getAttic().getItemState(
+                    state.getParentId()).getOverlayedState();
+            NodeTypeRegistry ntReg = session.getNodeTypeManager().getNodeTypeRegistry();
+            EffectiveNodeType ent = ntReg.getEffectiveNodeType(
+                    parent.getNodeTypeName(), parent.getMixinTypeNames());
+            QPropertyDefinition def;
+            try {
+                def = ent.getApplicablePropertyDef(
+                    state.getName(), state.getType(), state.isMultiValued());
+            } catch (ConstraintViolationException e) {
+                ent = ntReg.getEffectiveNodeType(NameConstants.NT_UNSTRUCTURED);
+                def = ent.getApplicablePropertyDef(state.getName(),
+                        state.getType(), state.isMultiValued());
+                log.warn("Fallback to nt:unstructured due to unknown property " +
+                        "definition for '" + state.getName() + "'");
+            }
+            return session.getNodeTypeManager().getPropertyDefinition(def);
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        } catch (NodeTypeConflictException e) {
+            throw new RepositoryException(e);
         }
-        return def;
     }
 
     /**
@@ -228,7 +285,7 @@
             session.sanityCheck();
 
             // shortcut: check if state exists for the given item
-            if (!itemStateProvider.hasItemState(itemId)) {
+            if (!sism.hasItemState(itemId)) {
                 return false;
             }
             getItemData(itemId, path, true);
@@ -310,7 +367,7 @@
             // NOTE: permission check & caching within createItemData
             ItemState state;
             try {
-                state = itemStateProvider.getItemState(itemId);
+                state = sism.getItemState(itemId);
             } catch (NoSuchItemStateException nsise) {
                 throw new ItemNotFoundException(itemId.toString());
             } catch (ItemStateException ise) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java Wed Oct 21 11:38:31 2009
@@ -31,10 +31,8 @@
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.lock.LockManager;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
-import org.apache.jackrabbit.core.nodetype.NodeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.retention.RetentionRegistry;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.authorization.Permission;
@@ -43,6 +41,9 @@
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QItemDefinition;
+import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -130,6 +131,8 @@
 
     protected final RetentionRegistry retentionReg;
 
+    protected final ItemManager itemMgr;
+
     /**
      * Creates a new <code>ItemValidator</code> instance.
      *
@@ -140,7 +143,9 @@
     public ItemValidator(NodeTypeRegistry ntReg,
                          HierarchyManager hierMgr,
                          SessionImpl session) throws RepositoryException {
-        this(ntReg, hierMgr, session, session.getLockManager(), session.getAccessManager(), session.getRetentionRegistry());
+        this(ntReg, hierMgr, session, session.getLockManager(),
+                session.getAccessManager(), session.getRetentionRegistry(),
+                session.getItemManager());
     }
 
     /**
@@ -152,19 +157,22 @@
      * @param lockMgr    lockMgr
      * @param accessMgr  accessMgr
      * @param retentionReg
+     * @param itemMgr    the item manager
      */
     public ItemValidator(NodeTypeRegistry ntReg,
                          HierarchyManager hierMgr,
                          PathResolver resolver,
                          LockManager lockMgr,
                          AccessManager accessMgr,
-                         RetentionRegistry retentionReg) {
+                         RetentionRegistry retentionReg,
+                         ItemManager itemMgr) {
         this.ntReg = ntReg;
         this.hierMgr = hierMgr;
         this.resolver = resolver;
         this.lockMgr = lockMgr;
         this.accessMgr = accessMgr;
         this.retentionReg = retentionReg;
+        this.itemMgr = itemMgr;
     }
 
     /**
@@ -190,7 +198,7 @@
                 ntReg.getEffectiveNodeType(nodeState.getNodeTypeName());
         // effective node type (primary type incl. mixins)
         EffectiveNodeType entPrimaryAndMixins = getEffectiveNodeType(nodeState);
-        NodeDef def = ntReg.getNodeDef(nodeState.getDefinitionId());
+        QNodeDefinition def = itemMgr.getDefinition(nodeState).unwrap();
 
         // check if primary type satisfies the 'required node types' constraint
         Name[] requiredPrimaryTypes = def.getRequiredPrimaryTypes();
@@ -204,9 +212,9 @@
             }
         }
         // mandatory properties
-        PropDef[] pda = entPrimaryAndMixins.getMandatoryPropDefs();
+        QPropertyDefinition[] pda = entPrimaryAndMixins.getMandatoryPropDefs();
         for (int i = 0; i < pda.length; i++) {
-            PropDef pd = pda[i];
+            QPropertyDefinition pd = pda[i];
             if (!nodeState.hasPropertyName(pd.getName())) {
                 String msg = safeGetJCRPath(nodeState.getNodeId())
                         + ": mandatory property " + pd.getName()
@@ -216,9 +224,9 @@
             }
         }
         // mandatory child nodes
-        NodeDef[] cnda = entPrimaryAndMixins.getMandatoryNodeDefs();
+        QItemDefinition[] cnda = entPrimaryAndMixins.getMandatoryNodeDefs();
         for (int i = 0; i < cnda.length; i++) {
-            NodeDef cnd = cnda[i];
+            QItemDefinition cnd = cnda[i];
             if (!nodeState.hasChildNodeEntry(cnd.getName())) {
                 String msg = safeGetJCRPath(nodeState.getNodeId())
                         + ": mandatory child node " + cnd.getName()
@@ -246,7 +254,7 @@
      */
     public void validate(PropertyState propState)
             throws ConstraintViolationException, RepositoryException {
-        PropDef def = ntReg.getPropDef(propState.getDefinitionId());
+        QPropertyDefinition def = itemMgr.getDefinition(propState).unwrap();
         InternalValue[] values = propState.getValues();
         int type = PropertyType.UNDEFINED;
         for (int i = 0; i < values.length; i++) {
@@ -451,12 +459,12 @@
      * @param name
      * @param nodeTypeName
      * @param parentState
-     * @return a <code>NodeDef</code>
+     * @return a <code>QNodeDefinition</code>
      * @throws ConstraintViolationException if no applicable child node definition
      *                                      could be found
      * @throws RepositoryException          if another error occurs
      */
-    public NodeDef findApplicableNodeDefinition(Name name,
+    public QNodeDefinition findApplicableNodeDefinition(Name name,
                                                 Name nodeTypeName,
                                                 NodeState parentState)
             throws RepositoryException, ConstraintViolationException {
@@ -479,12 +487,12 @@
      * @param type
      * @param multiValued
      * @param parentState
-     * @return a <code>PropDef</code>
+     * @return a <code>QPropertyDefinition</code>
      * @throws ConstraintViolationException if no applicable property definition
      *                                      could be found
      * @throws RepositoryException          if another error occurs
      */
-    public PropDef findApplicablePropertyDefinition(Name name,
+    public QPropertyDefinition findApplicablePropertyDefinition(Name name,
                                                     int type,
                                                     boolean multiValued,
                                                     NodeState parentState)
@@ -510,12 +518,12 @@
      * @param name
      * @param type
      * @param parentState
-     * @return a <code>PropDef</code>
+     * @return a <code>QPropertyDefinition</code>
      * @throws ConstraintViolationException if no applicable property definition
      *                                      could be found
      * @throws RepositoryException          if another error occurs
      */
-    public PropDef findApplicablePropertyDefinition(Name name,
+    public QPropertyDefinition findApplicablePropertyDefinition(Name name,
                                                     int type,
                                                     NodeState parentState)
             throws RepositoryException, ConstraintViolationException {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Wed Oct 21 11:38:31 2009
@@ -71,16 +71,10 @@
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
-import org.apache.jackrabbit.core.nodetype.ItemDef;
-import org.apache.jackrabbit.core.nodetype.NodeDef;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.nodetype.PropDef;
-import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
 import org.apache.jackrabbit.core.query.QueryManagerImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.state.ChildNodeEntry;
@@ -92,6 +86,9 @@
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QItemDefinition;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.conversion.NameException;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -108,6 +105,8 @@
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_CURRENT_LIFECYCLE_STATE;
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.MIX_LIFECYCLE;
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.MIX_REFERENCEABLE;
+import org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl;
 
 /**
  * <code>NodeImpl</code> implements the <code>Node</code> interface.
@@ -144,6 +143,23 @@
                     + state.getNodeTypeName() + "' of " + this);
             data.getNodeState().setNodeTypeName(NameConstants.NT_UNSTRUCTURED);
         }
+        List<Name> unknown = null;
+        for (Name mixinName : state.getMixinTypeNames()) {
+            if (!ntReg.isRegistered(mixinName)) {
+                if (unknown == null) {
+                    unknown = new ArrayList<Name>();
+                }
+                unknown.add(mixinName);
+                log.warn("Ignoring unknown mixin type '" + mixinName +
+                        "' of " + this);
+            }
+        }
+        if (unknown != null) {
+            // ignore unknown mixin type names
+            Set<Name> known = new HashSet<Name>(state.getMixinTypeNames());
+            known.removeAll(unknown);
+            state.setMixinTypeNames(known);
+        }
     }
 
     /**
@@ -404,6 +420,18 @@
         }
     }
 
+    /**
+     * Creates a new property with the given name and <code>type</code> hint and
+     * property definition. If the given property definition is not of type
+     * <code>UNDEFINED</code>, then it takes precendence over the
+     * <code>type</code> hint.
+     *
+     * @param name the name of the property to create.
+     * @param type the type hint.
+     * @param def  the associated property definition.
+     * @return the property instance.
+     * @throws RepositoryException if the property cannot be created.
+     */
     protected synchronized PropertyImpl createChildProperty(Name name, int type,
                                                             PropertyDefinitionImpl def)
             throws RepositoryException {
@@ -411,18 +439,20 @@
         // create a new property state
         PropertyState propState;
         try {
-            PropDef propDef = def.unwrap();
+            QPropertyDefinition propDef = def.unwrap();
+            if (def.getRequiredType() != PropertyType.UNDEFINED) {
+                type = def.getRequiredType();
+            }
             propState =
                     stateMgr.createTransientPropertyState(getNodeId(), name,
                             ItemState.STATUS_NEW);
             propState.setType(type);
             propState.setMultiValued(propDef.isMultiple());
-            propState.setDefinitionId(propDef.getId());
             // compute system generated values if necessary
             InternalValue[] genValues = session.getNodeTypeInstanceHandler()
                     .computeSystemGeneratedPropertyValues(data.getNodeState(), propDef);
             if (genValues == null) {
-                genValues = propDef.getDefaultValues();
+                genValues = InternalValue.create(propDef.getDefaultValues());
             }
             if (genValues != null) {
                 propState.setValues(genValues);
@@ -450,7 +480,6 @@
     }
 
     protected synchronized NodeImpl createChildNode(Name name,
-                                                    NodeDefinitionImpl def,
                                                     NodeTypeImpl nodeType,
                                                     NodeId id)
             throws RepositoryException {
@@ -463,7 +492,6 @@
             nodeState =
                     stateMgr.createTransientNodeState(id, nodeType.getQName(),
                             getNodeId(), ItemState.STATUS_NEW);
-            nodeState.setDefinitionId(def.unwrap().getId());
         } catch (ItemStateException ise) {
             String msg = "failed to add child node " + name + " to " + this;
             log.debug(msg);
@@ -495,15 +523,14 @@
         PropertyDefinition[] pda = nodeType.getAutoCreatedPropertyDefinitions();
         for (int i = 0; i < pda.length; i++) {
             PropertyDefinitionImpl pd = (PropertyDefinitionImpl) pda[i];
-            node.createChildProperty(pd.getQName(), pd.getRequiredType(), pd);
+            node.createChildProperty(pd.unwrap().getName(), pd.getRequiredType(), pd);
         }
 
         // recursively add 'auto-create' child nodes defined in node type
         NodeDefinition[] nda = nodeType.getAutoCreatedNodeDefinitions();
         for (int i = 0; i < nda.length; i++) {
             NodeDefinitionImpl nd = (NodeDefinitionImpl) nda[i];
-            node.createChildNode(nd.getQName(), nd,
-                    (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+            node.createChildNode(nd.unwrap().getName(), (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
         }
 
         return node;
@@ -570,13 +597,12 @@
         }
     }
 
-    protected void onRedefine(NodeDefId defId) throws RepositoryException {
+    protected void onRedefine(QNodeDefinition def) throws RepositoryException {
         NodeDefinitionImpl newDef =
-                session.getNodeTypeManager().getNodeDefinition(defId);
+                session.getNodeTypeManager().getNodeDefinition(def);
         // modify the state of 'this', i.e. the target node
-        NodeState thisState = (NodeState) getOrCreateTransientItemState();
-        // set id of new definition
-        thisState.setDefinitionId(defId);
+        getOrCreateTransientItemState();
+        // set new definition
         data.setDefinition(newDef);
     }
 
@@ -708,9 +734,9 @@
                                                                   Name nodeTypeName)
             throws ConstraintViolationException, RepositoryException {
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
-        NodeDef cnd = getEffectiveNodeType().getApplicableChildNodeDef(
+        QNodeDefinition cnd = getEffectiveNodeType().getApplicableChildNodeDef(
                 nodeName, nodeTypeName, ntMgr.getNodeTypeRegistry());
-        return ntMgr.getNodeDefinition(cnd.getId());
+        return ntMgr.getNodeDefinition(cnd);
     }
 
     /**
@@ -731,7 +757,7 @@
                                                                      boolean multiValued,
                                                                      boolean exactTypeMatch)
             throws ConstraintViolationException, RepositoryException {
-        PropDef pd;
+        QPropertyDefinition pd;
         if (exactTypeMatch || type == PropertyType.UNDEFINED) {
             pd = getEffectiveNodeType().getApplicablePropertyDef(
                     propertyName, type, multiValued);
@@ -746,7 +772,7 @@
                         propertyName, PropertyType.UNDEFINED, multiValued);
             }
         }
-        return session.getNodeTypeManager().getPropertyDefinition(pd.getId());
+        return session.getNodeTypeManager().getPropertyDefinition(pd);
     }
 
     protected void makePersistent() throws InvalidItemStateException {
@@ -779,8 +805,6 @@
             persistentState.setNodeTypeName(transientState.getNodeTypeName());
             // mixin types
             persistentState.setMixinTypeNames(transientState.getMixinTypeNames());
-            // id of definition
-            persistentState.setDefinitionId(transientState.getDefinitionId());
             // child node entries
             persistentState.setChildNodeEntries(transientState.getChildNodeEntries());
             // property entries
@@ -816,7 +840,6 @@
         thisState.setParentId(transientState.getParentId());
         thisState.setNodeTypeName(transientState.getNodeTypeName());
         thisState.setMixinTypeNames(transientState.getMixinTypeNames());
-        thisState.setDefinitionId(transientState.getDefinitionId());
         thisState.setChildNodeEntries(transientState.getChildNodeEntries());
         thisState.setPropertyNames(transientState.getPropertyNames());
         thisState.setSharedSet(transientState.getSharedSet());
@@ -902,7 +925,7 @@
                 // or existing mixin's
                 NodeTypeImpl declaringNT = (NodeTypeImpl) pd.getDeclaringNodeType();
                 if (!entExisting.includesNodeType(declaringNT.getQName())) {
-                    createChildProperty(pd.getQName(), pd.getRequiredType(), pd);
+                    createChildProperty(pd.unwrap().getName(), pd.getRequiredType(), pd);
                 }
             }
 
@@ -914,7 +937,7 @@
                 // or existing mixin's
                 NodeTypeImpl declaringNT = (NodeTypeImpl) nd.getDeclaringNodeType();
                 if (!entExisting.includesNodeType(declaringNT.getQName())) {
-                    createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+                    createChildNode(nd.unwrap().getName(), (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
                 }
             }
         } catch (RepositoryException re) {
@@ -1021,7 +1044,7 @@
             for (Name propName : set) {
                 PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(thisState.getNodeId(), propName));
                 // check if property has been defined by mixin type (or one of its supertypes)
-                PropertyDefinition def = ntMgr.getPropertyDefinition(propState.getDefinitionId());
+                PropertyDefinition def = itemMgr.getDefinition(propState);
                 NodeTypeImpl declaringNT = (NodeTypeImpl) def.getDeclaringNodeType();
                 if (!entResulting.includesNodeType(declaringNT.getQName())) {
                     // the resulting effective node type doesn't include the
@@ -1050,7 +1073,7 @@
                                                 pdi.getRequiredType(),
                                                 session.getValueFactory());
                                 // redefine property
-                                prop.onRedefine(pdi.unwrap().getId());
+                                prop.onRedefine(pdi.unwrap());
                                 // set converted values
                                 prop.setValue(values);
                             } else {
@@ -1061,13 +1084,13 @@
                                                 pdi.getRequiredType(),
                                                 session.getValueFactory());
                                 // redefine property
-                                prop.onRedefine(pdi.unwrap().getId());
+                                prop.onRedefine(pdi.unwrap());
                                 // set converted values
                                 prop.setValue(value);
                             }
                         } else {
                             // redefine property
-                            prop.onRedefine(pdi.unwrap().getId());
+                            prop.onRedefine(pdi.unwrap());
                         }
                     } catch (ValueFormatException vfe) {
                         // value conversion failed, remove it
@@ -1085,7 +1108,7 @@
             for (int i = list.size() - 1; i >= 0; i--) {
                 ChildNodeEntry entry = list.get(i);
                 NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
-                NodeDefinition def = ntMgr.getNodeDefinition(nodeState.getDefinitionId());
+                NodeDefinition def = itemMgr.getDefinition(nodeState);
                 // check if node has been defined by mixin type (or one of its supertypes)
                 NodeTypeImpl declaringNT = (NodeTypeImpl) def.getDeclaringNodeType();
                 if (!entResulting.includesNodeType(declaringNT.getQName())) {
@@ -1103,7 +1126,7 @@
                                 entry.getName(),
                                 nodeState.getNodeTypeName());
                         // redefine node
-                        node.onRedefine(ndi.unwrap().getId());
+                        node.onRedefine(ndi.unwrap());
                     } catch (ConstraintViolationException cve) {
                         // no suitable definition found for this child node,
                         // remove it
@@ -1493,7 +1516,7 @@
         session.getValidator().checkModify(this, options, Permission.NONE);
 
         // now do create the child node
-        return createChildNode(nodeName, def, nt, id);
+        return createChildNode(nodeName, nt, id);
     }
 
     /**
@@ -1513,34 +1536,18 @@
     public PropertyImpl setProperty(Name name, Value[] values)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        int type;
-        if (values == null || values.length == 0
-                || values[0] == null) {
-            type = PropertyType.UNDEFINED;
-        } else {
-            type = values[0].getType();
-        }
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, true, false, status);
-        try {
-            prop.setValue(values);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
+        int type = PropertyType.UNDEFINED;
+        if (values != null) {
+            for (Value v : values) {
+                // use the type of the first value
+                if (v != null) {
+                    type = v.getType();
+                    break;
+                }
             }
-            // rethrow
-            throw re;
         }
-        return prop;
+
+        return setProperty(name, values, type, false);
     }
 
     /**
@@ -1561,30 +1568,7 @@
     public PropertyImpl setProperty(Name name, Value[] values, int type)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, true, true, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(values, type, session.getValueFactory()));
-            } else {
-                prop.setValue(values);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        return setProperty(name, values, type, true);
     }
 
     /**
@@ -1604,30 +1588,7 @@
     public PropertyImpl setProperty(Name name, Value value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        int type = PropertyType.UNDEFINED;
-        if (value != null) {
-            type = value.getType();
-        }
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        return setProperty(name, value, false);
     }
 
     /**
@@ -2147,38 +2108,7 @@
     public Property setProperty(String name, Value[] values)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        int type;
-        if (values == null || values.length == 0
-                || values[0] == null) {
-            type = PropertyType.UNDEFINED;
-        } else {
-            type = values[0].getType();
-        }
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, true, false, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(values, type, session.getValueFactory()));
-            } else {
-                prop.setValue(values);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        return setProperty(session.getQName(name), values);
     }
 
     /**
@@ -2187,25 +2117,7 @@
     public Property setProperty(String name, Value[] values, int type)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, true, true, status);
-        try {
-            prop.setValue(values, type);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        return setProperty(session.getQName(name), values, type);
     }
 
     /**
@@ -2214,30 +2126,11 @@
     public Property setProperty(String name, String[] values)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        /**
-         * if the target property is not of type STRING then a
-         * best-effort conversion is attempted
-         */
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.STRING, true, false, status);
-        try {
-            prop.setValue(values);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value[] v = null;
+        if (values != null) {
+            v = ValueHelper.convert(values, PropertyType.STRING, session.getValueFactory());
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**
@@ -2246,30 +2139,11 @@
     public Property setProperty(String name, String[] values, int type)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, true, true, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(values, type, session.getValueFactory()));
-            } else {
-                prop.setValue(values);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value[] v = null;
+        if (values != null) {
+            v = ValueHelper.convert(values, type, session.getValueFactory());
         }
-        return prop;
+        return setProperty(session.getQName(name), v, type, true);
     }
 
     /**
@@ -2278,26 +2152,11 @@
     public Property setProperty(String name, String value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.STRING, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value v = null;
+        if (value != null) {
+            v = session.getValueFactory().createValue(value);
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**
@@ -2306,30 +2165,11 @@
     public Property setProperty(String name, String value, int type)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, false, true, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(value, type, session.getValueFactory()));
-            } else {
-                prop.setValue(value);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value v = null;
+        if (value != null) {
+            v = session.getValueFactory().createValue(value, type);
         }
-        return prop;
+        return setProperty(session.getQName(name), v, true);
     }
 
     /**
@@ -2338,30 +2178,10 @@
     public Property setProperty(String name, Value value, int type)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, false, true, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(value, type, session.getValueFactory()));
-            } else {
-                prop.setValue(value);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        if (value != null) {
+            value = ValueHelper.convert(value, type, session.getValueFactory());
         }
-        return prop;
+        return setProperty(session.getQName(name), value, true);
     }
 
     /**
@@ -2370,35 +2190,7 @@
     public Property setProperty(String name, Value value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        int type = PropertyType.UNDEFINED;
-        if (value != null) {
-            type = value.getType();
-        }
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(name, type, false, false, status);
-        try {
-            if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED
-                    && type != PropertyType.UNDEFINED) {
-                prop.setValue(ValueHelper.convert(value, type, session.getValueFactory()));
-            } else {
-                prop.setValue(value);
-            }
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        return setProperty(session.getQName(name), value);
     }
 
     /**
@@ -2407,26 +2199,11 @@
     public Property setProperty(String name, InputStream value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.BINARY, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value v = null;
+        if (value != null) {
+            v = session.getValueFactory().createValue(value);
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**
@@ -2435,26 +2212,8 @@
     public Property setProperty(String name, boolean value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.BOOLEAN, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        Value v = session.getValueFactory().createValue(value);
+        return setProperty(name, v);
     }
 
     /**
@@ -2463,26 +2222,8 @@
     public Property setProperty(String name, double value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.DOUBLE, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
-        }
-        return prop;
+        Value v = session.getValueFactory().createValue(value);
+        return setProperty(name, v);
     }
 
     /**
@@ -2491,43 +2232,98 @@
     public Property setProperty(String name, long value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
+        Value v = session.getValueFactory().createValue(value);
+        return setProperty(name, v);
+    }
 
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.LONG, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
+    /**
+     * {@inheritDoc}
+     */
+    public Property setProperty(String name, Calendar value)
+            throws ValueFormatException, VersionException, LockException,
+            ConstraintViolationException, RepositoryException {
+        Value v = null;
+        if (value != null) {
+            try {
+                v = session.getValueFactory().createValue(value);
+            } catch (IllegalArgumentException e) {
+                // thrown if calendar cannot be formatted as ISO8601
+                throw new ValueFormatException(e.getMessage());
             }
-            // rethrow
-            throw re;
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**
      * {@inheritDoc}
      */
-    public Property setProperty(String name, Calendar value)
+    public Property setProperty(String name, Node value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
+        Value v = null;
+        if (value != null) {
+            try {
+                v = session.getValueFactory().createValue(value);
+            } catch (UnsupportedRepositoryOperationException e) {
+                // happens when node is not referenceable
+                throw new ValueFormatException("node is not of type mix:referenceable");
+            }
+        }
+        return setProperty(name, v);
+    }
+
+    /**
+     * Implementation for <code>setProperty()</code> using a single {@link
+     * Value}. The type of the returned property is enforced based on the
+     * <code>enforceType</code> flag. If set to <code>true</code>, the returned
+     * property is of the passed type if it didn't exist before. If set to
+     * <code>false</code>, then the returned property may be of some other type,
+     * but still must be based on an existing property definition for the given
+     * name and single-valued flag. The resulting type is taken from that
+     * definition and the implementation tries to convert the passed value to
+     * that type. If that fails, then a {@link ValueFormatException} is thrown.
+     *
+     * @param name        the name of the property to set.
+     * @param value       the value to set. If <code>null</code> the property is
+     *                    removed.
+     * @param enforceType if the type of <code>value</code> is enforced.
+     * @return the <code>Property</code> object set, or <code>null</code> if
+     *         this method was used to remove a property (by setting its value
+     *         to <code>null</code>).
+     * @throws ValueFormatException         if <code>value</code> cannot be
+     *                                      converted to the specified type or
+     *                                      if the property already exists and
+     *                                      is multi-valued.
+     * @throws VersionException             if this node is read-only due to a
+     *                                      checked-in node and this implementation
+     *                                      performs this validation immediately.
+     * @throws LockException                if a lock prevents the setting of
+     *                                      the property and this implementation
+     *                                      performs this validation immediately.
+     * @throws ConstraintViolationException if the change would violate a
+     *                                      node-type or other constraint and
+     *                                      this implementation performs this
+     *                                      validation immediately.
+     * @throws RepositoryException          if another error occurs.
+     */
+    protected PropertyImpl setProperty(Name name,
+                                       Value value,
+                                       boolean enforceType) throws
+            ValueFormatException, VersionException, LockException,
+            ConstraintViolationException, RepositoryException {
         // check state of this instance
         sanityCheck();
 
         // check pre-conditions for setting property
         checkSetProperty();
 
+        int type = PropertyType.UNDEFINED;
+        if (value != null) {
+            type = value.getType();
+        }
+
         BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.DATE, false, false, status);
+        PropertyImpl prop = getOrCreateProperty(name, type, false, enforceType, status);
         try {
             prop.setValue(value);
         } catch (RepositoryException re) {
@@ -2542,10 +2338,45 @@
     }
 
     /**
-     * {@inheritDoc}
-     */
-    public Property setProperty(String name, Node value)
-            throws ValueFormatException, VersionException, LockException,
+     * Implementation for <code>setProperty()</code> using a {@link Value}
+     * array. The type of the returned property is enforced based on the
+     * <code>enforceType</code> flag. If set to <code>true</code>, the returned
+     * property is of the passed type if it didn't exist before. If set to
+     * <code>false</code>, then the returned property may be of some other type,
+     * but still must be based on an existing property definition for the given
+     * name and multi-valued flag. The resulting type is taken from that
+     * definition and the implementation tries to convert the passed values to
+     * that type. If that fails, then a {@link ValueFormatException} is thrown.
+     *
+     * @param name        the name of the property to set.
+     * @param values      the values to set. If <code>null</code> the property
+     *                    is removed.
+     * @param type        the target type of the values to set.
+     * @param enforceType if the target type is enforced.
+     * @return the <code>Property</code> object set, or <code>null</code> if
+     *         this method was used to remove a property (by setting its value
+     *         to <code>null</code>).
+     * @throws ValueFormatException         if a value cannot be converted to
+     *                                      the specified type or if the
+     *                                      property already exists and is not
+     *                                      multi-valued.
+     * @throws VersionException             if this node is read-only due to a
+     *                                      checked-in node and this implementation
+     *                                      performs this validation immediately.
+     * @throws LockException                if a lock prevents the setting of
+     *                                      the property and this implementation
+     *                                      performs this validation immediately.
+     * @throws ConstraintViolationException if the change would violate a
+     *                                      node-type or other constraint and
+     *                                      this implementation performs this
+     *                                      validation immediately.
+     * @throws RepositoryException          if another error occurs.
+     */
+    protected PropertyImpl setProperty(Name name,
+                                       Value[] values,
+                                       int type,
+                                       boolean enforceType) throws
+            ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
         // check state of this instance
         sanityCheck();
@@ -2554,10 +2385,9 @@
         checkSetProperty();
 
         BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.REFERENCE, false, true, status);
+        PropertyImpl prop = getOrCreateProperty(name, type, true, enforceType, status);
         try {
-            prop.setValue(value);
+            prop.setValue(values, type);
         } catch (RepositoryException re) {
             if (status.get(CREATED)) {
                 // setting value failed, get rid of newly created property
@@ -3677,26 +3507,26 @@
         }
 
         // get applicable definition for this node using new primary type
-        NodeDefId defId;
+        QNodeDefinition nodeDef;
         try {
             NodeImpl parent = (NodeImpl) getParent();
-            defId = parent.getApplicableChildNodeDefinition(getQName(), ntName).unwrap().getId();
+            nodeDef = parent.getApplicableChildNodeDefinition(getQName(), ntName).unwrap();
         } catch (RepositoryException re) {
             String msg = this + ": no applicable definition found in parent node's node type";
             log.debug(msg);
             throw new ConstraintViolationException(msg, re);
         }
 
-        if (!defId.equals(state.getDefinitionId())) {
-            onRedefine(defId);
+        if (!nodeDef.equals(itemMgr.getDefinition(state).unwrap())) {
+            onRedefine(nodeDef);
         }
 
-        Set<ItemDef> oldDefs = new HashSet<ItemDef>(Arrays.asList(entOld.getAllItemDefs()));
-        Set<ItemDef> newDefs = new HashSet<ItemDef>(Arrays.asList(entNew.getAllItemDefs()));
-        Set<ItemDef> allDefs = new HashSet<ItemDef>(Arrays.asList(entAll.getAllItemDefs()));
+        Set<QItemDefinition> oldDefs = new HashSet<QItemDefinition>(Arrays.asList(entOld.getAllItemDefs()));
+        Set<QItemDefinition> newDefs = new HashSet<QItemDefinition>(Arrays.asList(entNew.getAllItemDefs()));
+        Set<QItemDefinition> allDefs = new HashSet<QItemDefinition>(Arrays.asList(entAll.getAllItemDefs()));
 
         // added child item definitions
-        Set<ItemDef> addedDefs = new HashSet<ItemDef>(newDefs);
+        Set<QItemDefinition> addedDefs = new HashSet<QItemDefinition>(newDefs);
         addedDefs.removeAll(oldDefs);
 
         // referential integrity check
@@ -3732,7 +3562,7 @@
                 PropertyState propState =
                         (PropertyState) stateMgr.getItemState(
                                 new PropertyId(thisState.getNodeId(), propName));
-                if (!allDefs.contains(ntReg.getPropDef(propState.getDefinitionId()))) {
+                if (!allDefs.contains(itemMgr.getDefinition(propState).unwrap())) {
                     // try to find new applicable definition first and
                     // redefine property if possible
                     try {
@@ -3756,7 +3586,7 @@
                                                 pdi.getRequiredType(),
                                                 session.getValueFactory());
                                 // redefine property
-                                prop.onRedefine(pdi.unwrap().getId());
+                                prop.onRedefine(pdi.unwrap());
                                 // set converted values
                                 prop.setValue(values);
                             } else {
@@ -3767,13 +3597,13 @@
                                                 pdi.getRequiredType(),
                                                 session.getValueFactory());
                                 // redefine property
-                                prop.onRedefine(pdi.unwrap().getId());
+                                prop.onRedefine(pdi.unwrap());
                                 // set converted values
                                 prop.setValue(value);
                             }
                         } else {
                             // redefine property
-                            prop.onRedefine(pdi.unwrap().getId());
+                            prop.onRedefine(pdi.unwrap());
                         }
                         // update collection of added definitions
                         addedDefs.remove(pdi.unwrap());
@@ -3800,7 +3630,7 @@
             ChildNodeEntry entry = list.get(i);
             try {
                 NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
-                if (!allDefs.contains(ntReg.getNodeDef(nodeState.getDefinitionId()))) {
+                if (!allDefs.contains(itemMgr.getDefinition(nodeState).unwrap())) {
                     // try to find new applicable definition first and
                     // redefine node if possible
                     try {
@@ -3814,7 +3644,7 @@
                                 entry.getName(),
                                 nodeState.getNodeTypeName());
                         // redefine node
-                        node.onRedefine(ndi.unwrap().getId());
+                        node.onRedefine(ndi.unwrap());
                         // update collection of added definitions
                         addedDefs.remove(ndi.unwrap());
                     } catch (ConstraintViolationException cve) {
@@ -3832,15 +3662,14 @@
 
         // create items that are defined as auto-created by the new primary node
         // type and at the same time were not present with the old nt
-        for (Iterator<ItemDef> iter = addedDefs.iterator(); iter.hasNext();) {
-            ItemDef def = iter.next();
+        for (QItemDefinition def : addedDefs) {
             if (def.isAutoCreated()) {
                 if (def.definesNode()) {
-                    NodeDefinitionImpl ndi = ntMgr.getNodeDefinition(((NodeDef) def).getId());
-                    createChildNode(ndi.getQName(), ndi, (NodeTypeImpl) ndi.getDefaultPrimaryType(), null);
+                    NodeDefinitionImpl ndi = ntMgr.getNodeDefinition((QNodeDefinition) def);
+                    createChildNode(def.getName(), (NodeTypeImpl) ndi.getDefaultPrimaryType(), null);
                 } else {
-                    PropertyDefinitionImpl pdi = ntMgr.getPropertyDefinition(((PropDef) def).getId());
-                    createChildProperty(pdi.getQName(), pdi.getRequiredType(), pdi);
+                    PropertyDefinitionImpl pdi = ntMgr.getPropertyDefinition((QPropertyDefinition) def);
+                    createChildProperty(pdi.unwrap().getName(), pdi.getRequiredType(), pdi);
                 }
             }
         }
@@ -3852,26 +3681,11 @@
     public Property setProperty(String name, BigDecimal value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.DECIMAL, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value v = null;
+        if (value != null) {
+            v = session.getValueFactory().createValue(value);
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**
@@ -3880,26 +3694,11 @@
     public Property setProperty(String name, Binary value)
             throws ValueFormatException, VersionException, LockException,
             ConstraintViolationException, RepositoryException {
-        // check state of this instance
-        sanityCheck();
-
-        // check pre-conditions for setting property
-        checkSetProperty();
-
-        BitSet status = new BitSet();
-        PropertyImpl prop = getOrCreateProperty(
-                name, PropertyType.BINARY, false, false, status);
-        try {
-            prop.setValue(value);
-        } catch (RepositoryException re) {
-            if (status.get(CREATED)) {
-                // setting value failed, get rid of newly created property
-                removeChildProperty(name);
-            }
-            // rethrow
-            throw re;
+        Value v = null;
+        if (value != null) {
+            v = session.getValueFactory().createValue(value);
         }
-        return prop;
+        return setProperty(name, v);
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeTypeInstanceHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeTypeInstanceHandler.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeTypeInstanceHandler.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeTypeInstanceHandler.java Wed Oct 21 11:38:31 2009
@@ -19,10 +19,10 @@
 import java.util.Calendar;
 import java.util.Set;
 
-import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 
 /**
@@ -60,7 +60,7 @@
      * @return the computed values
      */
     public InternalValue[] computeSystemGeneratedPropertyValues(NodeState parent, 
-                                                                PropDef def) {
+                                                                QPropertyDefinition def) {
 
         InternalValue[] genValues = null;
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Wed Oct 21 11:38:31 2009
@@ -38,8 +38,6 @@
 import javax.jcr.version.VersionException;
 
 import org.apache.jackrabbit.core.id.PropertyId;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
-import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
@@ -47,8 +45,10 @@
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl;
 import org.apache.jackrabbit.value.ValueHelper;
 import org.apache.commons.io.input.AutoCloseInputStream;
 import org.slf4j.Logger;
@@ -137,7 +137,6 @@
                 throw new InvalidItemStateException(msg);
             }
             // copy state from transient state
-            persistentState.setDefinitionId(transientState.getDefinitionId());
             persistentState.setType(transientState.getType());
             persistentState.setMultiValued(transientState.isMultiValued());
             persistentState.setValues(transientState.getValues());
@@ -162,19 +161,14 @@
             stateMgr.disconnectTransientItemState(thisState);
         }
         // reapply transient changes
-        thisState.setDefinitionId(transientState.getDefinitionId());
         thisState.setType(transientState.getType());
         thisState.setMultiValued(transientState.isMultiValued());
         thisState.setValues(transientState.getValues());
     }
 
-    protected void onRedefine(PropDefId defId) throws RepositoryException {
+    protected void onRedefine(QPropertyDefinition def) throws RepositoryException {
         PropertyDefinitionImpl newDef =
-                session.getNodeTypeManager().getPropertyDefinition(defId);
-        // modify the state of 'this', i.e. the target property
-        PropertyState thisState = (PropertyState) getOrCreateTransientItemState();
-        // set id of new definition
-        thisState.setDefinitionId(defId);
+                session.getNodeTypeManager().getPropertyDefinition(def);
         data.setDefinition(newDef);
     }
 
@@ -433,7 +427,6 @@
      * @throws RepositoryException
      */
     public InternalValue internalGetValue() throws RepositoryException {
-        final PropertyDefinition definition = data.getPropertyDefinition();
         if (isMultiple()) {
             throw new ValueFormatException(
                     this + " is a multi-valued property,"

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java Wed Oct 21 11:38:31 2009
@@ -23,7 +23,6 @@
 import javax.jcr.Value;
 
 import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.retention.RetentionManagerImpl;
 import org.apache.jackrabbit.core.security.AccessManager;
@@ -65,12 +64,16 @@
     }
 
     protected NodeImpl addNode(NodeImpl parentImpl, Name name, Name ntName) throws RepositoryException {
+        return addNode(parentImpl, name, ntName, null);
+    }
+
+    protected NodeImpl addNode(NodeImpl parentImpl, Name name, Name ntName, NodeId nodeId) throws RepositoryException {
         checkPermission(parentImpl, name, getPermission(true, false));
         // validation: make sure Node is not locked or checked-in.
         parentImpl.checkSetProperty();
 
         NodeTypeImpl nodeType = parentImpl.session.getNodeTypeManager().getNodeType(ntName);
-        NodeDefinitionImpl def = parentImpl.getApplicableChildNodeDefinition(name, ntName);
+        org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl def = parentImpl.getApplicableChildNodeDefinition(name, ntName);
 
         // check for name collisions
         // TODO: improve. copied from NodeImpl
@@ -90,7 +93,7 @@
             }
         }
 
-        return parentImpl.createChildNode(name, def, nodeType, null);
+        return parentImpl.createChildNode(name, nodeType, nodeId);
     }
 
     protected Property setProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Wed Oct 21 11:38:31 2009
@@ -28,10 +28,10 @@
 import org.apache.commons.io.FileUtils;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.persistence.PersistenceCopier;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -229,7 +229,7 @@
         logger.info("Copying registered node types");
         Collection<Name> existing =
             Arrays.asList(targetRegistry.getRegisteredNodeTypes());
-        Collection<NodeTypeDef> register = new ArrayList<NodeTypeDef>();
+        Collection<QNodeTypeDefinition> register = new ArrayList<QNodeTypeDefinition>();
         for (Name name : sourceRegistry.getRegisteredNodeTypes()) {
             // TODO: what about modified node types?
             if (!existing.contains(name)) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryFactoryImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryFactoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryFactoryImpl.java Wed Oct 21 11:38:31 2009
@@ -16,20 +16,23 @@
  */
 package org.apache.jackrabbit.core;
 
+import java.util.HashSet;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Set;
 
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 
-import javax.jcr.RepositoryFactory;
 import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.api.JackrabbitRepositoryFactory;
+import org.apache.jackrabbit.api.management.RepositoryManager;
 
 /**
  * <code>RepositoryFactoryImpl</code> implements a repository factory that
  * creates a {@link TransientRepository} on {@link #getRepository(Map)}.
  */
-public class RepositoryFactoryImpl implements RepositoryFactory {
+public class RepositoryFactoryImpl implements JackrabbitRepositoryFactory {
 
     /**
      * Name of the repository home parameter.
@@ -49,6 +52,11 @@
      */
     private static final Map<String, JackrabbitRepository> REPOSITORY_INSTANCES = new HashMap<String, JackrabbitRepository>();
 
+    /**
+     * The repository instances that were created by this factory.
+     */
+    private final Set<TransientRepository> ownRepositories = new HashSet<TransientRepository>();
+
     public Repository getRepository(Map parameters) throws RepositoryException {
         JackrabbitRepository repo;
         synchronized (REPOSITORY_INSTANCES) {
@@ -91,8 +99,19 @@
                 tr = new TransientRepository(conf, home);
             }
             REPOSITORY_INSTANCES.put(tr.getHomeDir(), tr);
+            ownRepositories.add(tr);
             repo = tr;
         }
         return repo;
     }
+
+    public RepositoryManager getRepositoryManager(JackrabbitRepository repo) throws RepositoryException {
+        if (!(repo instanceof TransientRepository)) {
+            throw new RepositoryException("The repository was not created in this factory");
+        }
+        if (!ownRepositories.contains(repo)) {
+            throw new RepositoryException("The repository was not created in this factory");
+        }
+        return new RepositoryManagerImpl((TransientRepository) repo);
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed Oct 21 11:38:31 2009
@@ -545,12 +545,12 @@
                    rootNodeUUID = new UUID(bytes).toString();            // uuid is stored in binary format (16 bytes)
 */
                     // uuid is stored in text format (36 characters) for better readability
-                    char[] chars = new char[36];
-                    InputStreamReader reader = new InputStreamReader(in);
+
+                    char[] chars;
                     try {
-                        reader.read(chars);
+                        chars = IOUtils.toCharArray(in);
                     } finally {
-                        IOUtils.closeQuietly(reader);
+                        IOUtils.closeQuietly(in);
                     }
                     return NodeId.valueOf(new String(chars));
                 } catch (Exception e) {
@@ -665,10 +665,12 @@
     private SearchManager getSystemSearchManager(String wspName)
             throws RepositoryException {
         if (systemSearchMgr == null) {
-            if (repConfig.getSearchConfig() != null) {
-                systemSearchMgr = new SearchManager(repConfig.getSearchConfig(),
-                        nsReg, ntReg, getWorkspaceInfo(wspName).itemStateMgr,
-                        vMgr.getPersistenceManager(), SYSTEM_ROOT_NODE_ID, null, null);
+            if (repConfig.isSearchEnabled()) {
+                systemSearchMgr = new SearchManager(
+                        repConfig, nsReg, ntReg,
+                        getWorkspaceInfo(wspName).itemStateMgr,
+                        vMgr.getPersistenceManager(), SYSTEM_ROOT_NODE_ID,
+                        null, null, executor);
 
                 SystemSession defSysSession = getSystemSession(wspName);
                 ObservationManager obsMgr = defSysSession.getWorkspace().getObservationManager();
@@ -1101,10 +1103,10 @@
     }
 
     /**
-     * Private method that performs the actual shutdown after the shutdown
+     * Protected method that performs the actual shutdown after the shutdown
      * lock has been acquired by the {@link #shutdown()} method.
      */
-    private synchronized void doShutdown() {
+    protected synchronized void doShutdown() {
         log.info("Shutting down repository...");
 
         // stop optional cluster node
@@ -1179,7 +1181,7 @@
         // wake up threads waiting on this instance's monitor (e.g. workspace janitor)
         notifyAll();
 
-        // Shut down the executor service 
+        // Shut down the executor service
         executor.shutdown();
         try {
             // Wait for all remaining background threads to terminate
@@ -1832,21 +1834,13 @@
             }
 
             synchronized (this) {
-                if (searchMgr == null) {
-                    if (config.getSearchConfig() == null) {
-                        // no search index configured
-                        return null;
-                    }
+                if (searchMgr == null && config.isSearchEnabled()) {
                     // search manager is lazily instantiated in order to avoid
                     // 'chicken & egg' bootstrap problems
-                    searchMgr = new SearchManager(config.getSearchConfig(),
-                            nsReg,
-                            ntReg,
-                            itemStateMgr,
-                            persistMgr,
-                            rootNodeId,
+                    searchMgr = new SearchManager(config,
+                            nsReg, ntReg, itemStateMgr, persistMgr, rootNodeId,
                             getSystemSearchManager(getName()),
-                            SYSTEM_ROOT_NODE_ID);
+                            SYSTEM_ROOT_NODE_ID, executor);
                 }
                 return searchMgr;
             }