You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2005/02/03 12:23:28 UTC

svn commit: r151144 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: ./ nodetype/ version/ version/persistence/

Author: tripod
Date: Thu Feb  3 03:23:20 2005
New Revision: 151144

URL: http://svn.apache.org/viewcvs?view=rev&rev=151144
Log:
- fixing verisoning issues (version labels still missing)

Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java Thu Feb  3 03:23:20 2005
@@ -2432,52 +2432,42 @@
         // check state of this instance
         sanityCheck();
 
-        if (isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
-            String uuid = ((NodeState) state).getUUID();
-        }
-/*
+        // aquire session of other workspace (throws NoSuchWorkspaceException)
         // @todo FIXME need to get session with same credentials as current
-        SessionImpl srcSession = rep.getSystemSession(srcWorkspaceName);
-        Node root = session.getRootNode();
-        // if (isRepositoryRoot()) [don't know, if this works correctly with workspaces]
-        if (isSame(root)) {
-            return (NodeImpl) srcSession.getRootNode();
-        }
-
-        // if this node is referenceable, return the corresponding one
-        if (isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
-            try {
-                return (NodeImpl) srcSession.getNodeByUUID(getUUID());
-            } catch (ItemNotFoundException e) {
-                return null;
-            }
-        }
+        SessionImpl srcSession = rep.getSystemSession(workspaceName);
 
         // search nearest ancestor that is referenceable
         NodeImpl m1 = this;
-        while (!m1.isSame(root) && !m1.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+        while (!m1.isRepositoryRoot() && !m1.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
             m1 = (NodeImpl) m1.getParent();
         }
-        // special treatment for root
-        if (m1.isSame(root)) {
-            return (NodeImpl) srcSession.getItem(getPath());
+
+        // if root is common ancestor, corresponding path is same as ours
+        if (m1.isRepositoryRoot()) {
+            return getPath();
         }
 
-        // calculate relative path. please note, that this cannot be done
+        // get corresponding ancestor
+        Node m2 = srcSession.getNodeByUUID(m1.getUUID());
+
+        // return path of m2, if m1 == n1
+        if (m1 == this) {
+            return m2.getPath();
+        }
+
+        // calculate relative path from the referenceable ancestor to this node.
+        // please note, that this cannot be done
         // iteratively in the 'while' loop above, since getName() does not
         // return the relative path, but just the name (without path indices)
         // n1.getPath() = /foo/bar/something[1]
         // m1.getPath() = /foo
         //      relpath = bar/something[1]
+
+        // @todo: replace as soon as implemented
+        // Path relPath = m1.getPrimaryPath().getRelativePath(getPrimaryPath());
+
         String relPath = getPath().substring(m1.getPath().length() + 1);
-        try {
-            return (NodeImpl) srcSession.getNodeByUUID(m1.getUUID()).getNode(relPath);
-        } catch (ItemNotFoundException e) {
-            return null;
-        }
-*/
-        // @todo implement Node#getCorrespondingNodePath
-        throw new RepositoryException("not yet implemented");
+        return m2.getNode(relPath).getPath();
     }
 
     /**
@@ -2506,8 +2496,7 @@
         checkVersionable();
 
         // check if checked out
-        // @todo FIXME semantics of isCheckedOut() have changed!
-        if (!isCheckedOut()) {
+        if (!internalIsCheckedOut()) {
             String msg = safeGetJCRPath() + ": Node is already checked-in. ignoring.";
             log.debug(msg);
             return getBaseVersion();
@@ -2522,7 +2511,7 @@
 
         // check if not merge failed
         if (hasProperty(ItemImpl.PROPNAME_MERGE_FAILED) && getProperty(ItemImpl.PROPNAME_MERGE_FAILED).getValues().length>0) {
-            String msg = "Unable to checkin node. Clear 'jcr:mergeFailed' first. " + safeGetJCRPath();
+            String msg = "Unable to checkin node. Node has unresolved merge operation. " + safeGetJCRPath();
             log.debug(msg);
             throw new VersionException(msg);
         }
@@ -2581,7 +2570,10 @@
             throw new InvalidItemStateException(msg);
         }
 
-        NodeImpl srcNode = getCorrespondingNode(srcWorkspaceName);
+        // @todo FIXME need to get session with same credentials as current
+        SessionImpl srcSession = rep.getSystemSession(srcWorkspaceName);
+
+        NodeImpl srcNode = getCorrespondingNode(srcSession);
         if (srcNode == null) {
             throw new ItemNotFoundException("No corresponding node for " + safeGetJCRPath());
         }
@@ -2606,7 +2598,15 @@
             throw new InvalidItemStateException(msg);
         }
 
-        NodeImpl srcNode = doMergeTest(srcWorkspace, bestEffort);
+        // if same workspace, ignore
+        if (srcWorkspace.equals(session.getWorkspace().getName())) {
+            return;
+        }
+
+        // @todo FIXME need to get session with same credentials as current
+        SessionImpl srcSession = rep.getSystemSession(srcWorkspace);
+
+        NodeImpl srcNode = doMergeTest(srcSession, bestEffort);
         if (srcNode != null) {
             // remove properties
             PropertyIterator pi = getProperties();
@@ -2716,6 +2716,7 @@
             throws VersionException, ItemExistsException,
             UnsupportedRepositoryOperationException, LockException,
             InvalidItemStateException, RepositoryException {
+
         // check state of this instance
         sanityCheck();
 
@@ -2729,7 +2730,7 @@
         GenericVersionSelector gvs = new GenericVersionSelector();
         gvs.setName(versionName);
         internalRestore(getVersionHistory().getVersion(versionName), gvs, removeExisting);
-        save();
+        // session.save/revert is done in internal restore
     }
 
     /**
@@ -2750,11 +2751,13 @@
         }
 
         // check if 'own' version
-        if (!version.getParent().getUUID().equals(getVersionHistory().getUUID())) {
+        // TODO: change if Version.getContainingVersionHistory() is introduced
+        if (!version.getParent().isSame(getVersionHistory())) {
             throw new VersionException("Unable to restore version. Not same version history.");
         }
+
         internalRestore(version, new GenericVersionSelector(version.getCreated()), removeExisting);
-        save();
+        // session.save/revert is done in internal restore
     }
 
     /**
@@ -2781,7 +2784,7 @@
             // recreate node from frozen state
             NodeImpl node = addNode(relPath, ((VersionImpl) version).getFrozenNode());
             node.internalRestore(version, new GenericVersionSelector(version.getCreated()), removeExisting);
-            node.getParent().save();
+            // session.save/revert is done in internal restore
         }
     }
 
@@ -2849,10 +2852,8 @@
             throw new UnsupportedRepositoryOperationException(msg);
         }
     }
-
-    /**
-     * Returns the corresponding node in the <code>scrWorkspaceName</code> of
-     * this node.
+/**
+     * Returns the corresponding node in the workspace of the given session.
      * <p/>
      * Given a node N1 in workspace W1, its corresponding node N2 in workspace
      * W2 is defined as follows:
@@ -2867,57 +2868,49 @@
      * from M2 as N1 has from M1.
      * </ul>
      *
-     * @param srcWorkspaceName
+     * @param srcSession
      * @return the corresponding node or <code>null</code> if no corresponding
      *         node exists.
      * @throws NoSuchWorkspaceException If <code>srcWorkspace</code> does not exist.
      * @throws AccessDeniedException    If the current session does not have sufficient rights to perform the operation.
      * @throws RepositoryException      If another error occurs.
      */
-    private NodeImpl getCorrespondingNode(String srcWorkspaceName)
-            throws NoSuchWorkspaceException, AccessDeniedException,
-            RepositoryException {
+    private NodeImpl getCorrespondingNode(Session srcSession)
+            throws AccessDeniedException, RepositoryException {
 
-        // @todo FIXME need to get session with same credentials as current
-        SessionImpl srcSession = rep.getSystemSession(srcWorkspaceName);
-        Node root = session.getRootNode();
-        // if (isRepositoryRoot()) [don't know, if this works correctly with workspaces]
-        if (isSame(root)) {
-            return (NodeImpl) srcSession.getRootNode();
-        }
+    // search nearest ancestor that is referenceable
+    NodeImpl m1 = this;
+    while (!m1.isRepositoryRoot() && !m1.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+        m1 = (NodeImpl) m1.getParent();
+    }
 
-        // if this node is referenceable, return the corresponding one
-        if (isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
-            try {
-                return (NodeImpl) srcSession.getNodeByUUID(getUUID());
-            } catch (ItemNotFoundException e) {
-                return null;
-            }
-        }
+    try {
+        // get corresponding ancestor
+        NodeImpl m2 = (NodeImpl) srcSession.getNodeByUUID(m1.getUUID());
 
-        // search nearest ancestor that is referenceable
-        NodeImpl m1 = this;
-        while (!m1.isSame(root) && !m1.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
-            m1 = (NodeImpl) m1.getParent();
-        }
-        // special treatment for root
-        if (m1.isSame(root)) {
-            return (NodeImpl) srcSession.getItem(getPath());
+        // return path of m2, if m1 == n1
+        if (m1 == this) {
+            return m2;
         }
 
-        // calculate relative path. please note, that this cannot be done
+        // calculate relative path from the referenceable ancestor to this node.
+        // please note, that this cannot be done
         // iteratively in the 'while' loop above, since getName() does not
         // return the relative path, but just the name (without path indices)
         // n1.getPath() = /foo/bar/something[1]
         // m1.getPath() = /foo
         //      relpath = bar/something[1]
+
+        // @todo: replace as soon as implemented
+        // Path relPath = m1.getPrimaryPath().getRelativePath(getPrimaryPath());
+
         String relPath = getPath().substring(m1.getPath().length() + 1);
-        try {
-            return (NodeImpl) srcSession.getNodeByUUID(m1.getUUID()).getNode(relPath);
-        } catch (ItemNotFoundException e) {
-            return null;
-        }
+        return (NodeImpl) m2.getNode(relPath);
+
+    } catch (ItemNotFoundException e) {
+        return null;
     }
+}
 
     /**
      * Performs the merge test. If the result is 'update', then the corresponding
@@ -2926,17 +2919,17 @@
      * 'fail' with bestEffort set to <code>false</code> a MergeException is
      * thrown.
      *
-     * @param srcWorkspace
+     * @param srcSession
      * @param bestEffort
      * @return
      * @throws RepositoryException
      * @throws AccessDeniedException
      */
-    private NodeImpl doMergeTest(String srcWorkspace, boolean bestEffort)
+    private NodeImpl doMergeTest(Session srcSession, boolean bestEffort)
             throws RepositoryException, AccessDeniedException {
 
         // If N does not have a corresponding node then the merge result for N is leave.
-        NodeImpl srcNode = getCorrespondingNode(srcWorkspace);
+        NodeImpl srcNode = getCorrespondingNode(srcSession);
         if (srcNode == null) {
             return null;
         }
@@ -3115,52 +3108,19 @@
      */
     private void internalRestore(Version version, VersionSelector vsel, boolean removeExisting)
             throws UnsupportedRepositoryOperationException, RepositoryException {
-        internalRestore(((VersionImpl) version).getInternalVersion(), vsel, removeExisting);
-    }
-
-    /**
-     * Checks if any frozen uuid in the given frozen node or its descendants
-     * collides with the one in the workspace. if 'removeExisting' is true,
-     * collisions will be removed, otherwise an ItemExistsException is thrown.
-     * If a frozen version history is already restored outside this nodes
-     * subtree, a exception is thrown, too, if the removeExisting is true.
-     * @param f
-     * @param removeExisting
-     * @throws RepositoryException
-     */
-    private void checkUUIDCollisions(InternalFrozenNode f, boolean removeExisting)
-            throws RepositoryException {
-
-        if (itemMgr.itemExists(new NodeId(f.getFrozenUUID()))) {
-            NodeImpl node = (NodeImpl) session.getNodeByUUID(f.getFrozenUUID());
-            if (removeExisting) {
-                node.remove();
-            } else {
-                throw new ItemExistsException("Unable to restore. UUID collides with " + node.safeGetJCRPath());
-            }
-        }
-        InternalFreeze[] fs = f.getFrozenChildNodes();
-        for (int i=0; i<fs.length; i++) {
-            if (fs[i] instanceof InternalFrozenNode) {
-                checkUUIDCollisions((InternalFrozenNode) fs[i], removeExisting);
-            } else if (!removeExisting) {
-                InternalFrozenVersionHistory fh = (InternalFrozenVersionHistory) fs[i];
-                VersionHistoryImpl history = (VersionHistoryImpl) session.getNodeByUUID(fh.getVersionHistoryId());
-                String nodeId = history.getVersionedUUID();
-
-                // check if representing vh already exists somewhere
-                if (itemMgr.itemExists(new NodeId(nodeId))) {
-                    NodeImpl n = (NodeImpl) session.getNodeByUUID(nodeId);
-                    try {
-                        if (!n.getPrimaryPath().isDescendantOf(getPrimaryPath())) {
-                            throw new ItemExistsException("Unable to restore. Same node already restored at " + n.safeGetJCRPath());
-                        }
-                    } catch (MalformedPathException e) {
-                        throw new RepositoryException(e);
-                    }
-                }
+        try {
+            internalRestore(((VersionImpl) version).getInternalVersion(), vsel, removeExisting);
+        } catch (RepositoryException e) {
+            // revert session
+            try {
+                log.error("reverting changes applied during restore...");
+                session.refresh(false);
+            } catch (RepositoryException e1) {
+                // ignore this
             }
+            throw e;
         }
+        session.save();
     }
 
     /**
@@ -3173,12 +3133,10 @@
      *
      * @throws RepositoryException
      */
-    private void internalRestore(InternalVersion version, VersionSelector vsel, boolean removeExisting)
+    private void internalRestore(InternalVersion version, VersionSelector vsel,
+                                 boolean removeExisting)
             throws RepositoryException {
 
-        // first check, if any uuid conflicts would occurr
-        checkUUIDCollisions(version.getFrozenNode(), removeExisting);
-
         // set jcr:isCheckedOut property to true, in order to avoid any conflicts
         internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
 
@@ -3191,20 +3149,23 @@
         internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(version.getId())));
 
         // 4. N's jcr:predecessor property is set to null
-        internalSetProperty(VersionManager.PROPNAME_PREDECESSORS, new InternalValue[0]);
+        internalSetProperty(VersionManager.PROPNAME_PREDECESSORS, new InternalValue[0], PropertyType.REFERENCE);
 
         // 3. N’s jcr:isCheckedOut property is set to false.
         internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(false));
     }
 
     /**
-     * Creates the frozen state from a node
+     * Restores the properties and child nodes from the frozen state.
      *
      * @param freeze
+     * @param vsel
+     * @param removeExisting
      * @throws RepositoryException
      */
     void restoreFrozenState(InternalFrozenNode freeze, VersionSelector vsel, boolean removeExisting)
             throws RepositoryException {
+
         // check uuid
         if (isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
             String uuid = freeze.getFrozenUUID();
@@ -3212,11 +3173,13 @@
                 throw new ItemExistsException("Unable to restore version of " + safeGetJCRPath() + ". UUID changed.");
             }
         }
+
         // check primarty type
         if (!freeze.getFrozenPrimaryType().equals(nodeType.getQName())) {
             // todo: check with spec what should happen here
             throw new ItemExistsException("Unable to restore version of " + safeGetJCRPath() + ". PrimaryType changed.");
         }
+
         // adjust mixins
         QName[] values = freeze.getFrozenMixinTypes();
         NodeType[] mixins = getMixinNodeTypes();
@@ -3240,7 +3203,7 @@
                 }
             }
         }
-        // remove additional
+        // remove additional mixins
         for (int i = 0; i < mixins.length; i++) {
             if (mixins[i] != null) {
                 removeMixin(mixins[i].getName());
@@ -3280,42 +3243,49 @@
         // restore the frozen nodes
         InternalFreeze[] frozenNodes = freeze.getFrozenChildNodes();
 
-        // first delete all non frozen version histories
+        // first delete all non frozen version histories, ie. all OPV!=Version
         NodeIterator iter = getNodes();
         while (iter.hasNext()) {
             NodeImpl n = (NodeImpl) iter.nextNode();
-            // this is a bit lousy
-            boolean found = false;
-            for (int i=0; i<frozenNodes.length; i++) {
-                InternalFreeze child = frozenNodes[i];
-                if (child instanceof InternalFrozenVersionHistory) {
-                    if (n.internalGetUUID().equals(child.getId())) {
-                        found = true;
-                        break;
-                    }
-                }
-            }
-            if (!found) {
+            if (n.getDefinition().getOnParentVersion()==OnParentVersionAction.COPY) {
                 n.remove();
             }
         }
+
+        // now restore the frozen ones
         for (int i = 0; i < frozenNodes.length; i++) {
             InternalFreeze child = frozenNodes[i];
             if (child instanceof InternalFrozenNode) {
                 InternalFrozenNode f = (InternalFrozenNode) child;
+                // check for existing
+                if (f.getFrozenUUID()!=null) {
+                    try {
+                        NodeImpl existing = (NodeImpl) session.getNodeByUUID(f.getFrozenUUID());
+                        if (removeExisting) {
+                            existing.remove();
+                        } else {
+                            // since we delete the OPV=Copy children beforehand, all
+                            // found nodes must be outside of this tree
+                            throw new ItemExistsException("Unable to restore node, item already exists outside of restored tree: " + existing.safeGetJCRPath());
+                        }
+                    } catch (ItemNotFoundException e) {
+                        // ignore, item with uuid does not exist
+                    }
+                }
                 NodeImpl n = addNode(f.getName(), f);
                 n.restoreFrozenState(f, vsel, removeExisting);
+
             } else if (child instanceof InternalFrozenVersionHistory) {
                 InternalFrozenVersionHistory f = (InternalFrozenVersionHistory) child;
                 VersionHistoryImpl history = (VersionHistoryImpl) session.getNodeByUUID(f.getVersionHistoryId());
-                String nodeId = history.getVersionedUUID();
+                String nodeId = history.getVersionableUUID();
 
                 // check if representing vh already exists somewhere
                 if (itemMgr.itemExists(new NodeId(nodeId))) {
                     NodeImpl n = (NodeImpl) session.getNodeByUUID(nodeId);
                     if (hasNode(n.getQName())) {
                         // so order at end
-                        orderBefore(n.getName(), "");
+                        // orderBefore(n.getName(), "");
                     } else {
                         session.move(n.getPath(), getPath()+ "/" + n.getName());
                     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java Thu Feb  3 03:23:20 2005
@@ -619,8 +619,8 @@
      * @return the workspace persistence manager
      * @throws RepositoryException if the persistence manager could not be instantiated/initialized
      */
-    private static PersistenceManager createPersistenceManager(File homeDir, 
-                                                              FileSystem fs, 
+    private static PersistenceManager createPersistenceManager(File homeDir,
+                                                              FileSystem fs,
                                                               PersistenceManagerConfig pmConfig,
                                                               String rootNodeUUID,
                                                               NamespaceRegistry nsReg,

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Thu Feb  3 03:23:20 2005
@@ -79,9 +79,15 @@
     // nt:version
     public static final QName NT_VERSION =
             new QName(NamespaceRegistryImpl.NS_NT_URI, "version");
-    // nt:frozenVersionableChild
-    public static final QName NT_FROZEN_VERSIONABLE_CHILD =
-            new QName(NamespaceRegistryImpl.NS_NT_URI, "frozenVersionableChild");
+    // nt:versionLabels
+    public static final QName NT_VERSION_LABELS =
+            new QName(NamespaceRegistryImpl.NS_NT_URI, "versionLabels");
+    // nt:versionedChild
+    public static final QName NT_VERSIONED_CHILD =
+            new QName(NamespaceRegistryImpl.NS_NT_URI, "versionedChild");
+    // nt:frozenNode
+    public static final QName NT_FROZEN_NODE =
+            new QName(NamespaceRegistryImpl.NS_NT_URI, "frozenNode");
     // jcr:primaryType
     public static final QName JCR_PRIMARY_TYPE =
             new QName(NamespaceRegistryImpl.NS_JCR_URI, "primaryType");

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml Thu Feb  3 03:23:20 2005
@@ -234,7 +234,7 @@
         </supertypes>
         <propertyDef name="jcr:frozenPrimaryType" requiredType="Name" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" multiple="false"/>
         <propertyDef name="jcr:frozenMixinTypes" requiredType="Name" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" multiple="true"/>
-        <propertyDef name="jcr:frozenUuid" requiredType="String" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" multiple="false"/>
+        <propertyDef name="jcr:frozenUUID" requiredType="String" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" multiple="false"/>
         <propertyDef name="*" requiredType="undefined" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" multiple="false"/>
         <propertyDef name="*" requiredType="undefined" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" multiple="true"/>
         <childNodeDef name="*" defaultPrimaryType="" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" sameNameSibs="true">
@@ -273,12 +273,12 @@
         <supertypes>
             <supertype>mix:referenceable</supertype>
         </supertypes>
-        <propertyDef name="jcr:versionHistory" requiredType="Reference" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="true" multiple="false">
+        <propertyDef name="jcr:versionHistory" requiredType="Reference" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="false">
             <valueConstraints>
                 <valueConstraint>nt:versionHistory</valueConstraint>
             </valueConstraints>
         </propertyDef>
-        <propertyDef name="jcr:baseVersion" requiredType="Reference" autoCreate="true" mandatory="true" onParentVersion="IGNORE" protected="true" multiple="false">
+        <propertyDef name="jcr:baseVersion" requiredType="Reference" autoCreate="false" mandatory="true" onParentVersion="IGNORE" protected="true" multiple="false">
             <valueConstraints>
                 <valueConstraint>nt:version</valueConstraint>
             </valueConstraints>
@@ -288,12 +288,12 @@
                 <defaultValue>true</defaultValue>
             </defaultValues>
         </propertyDef>
-        <propertyDef name="jcr:predecessors" requiredType="Reference" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="true" multiple="true">
+        <propertyDef name="jcr:predecessors" requiredType="Reference" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="true" multiple="true">
             <valueConstraints>
                 <valueConstraint>nt:version</valueConstraint>
             </valueConstraints>
         </propertyDef>
-        <propertyDef name="jcr:mergeFailed" requiredType="Reference" autoCreate="true" mandatory="false" onParentVersion="COPY" protected="true" multiple="true" />
+        <propertyDef name="jcr:mergeFailed" requiredType="Reference" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" multiple="true" />
     </nodeType>
 
     <!-- internal node types -->

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java Thu Feb  3 03:23:20 2005
@@ -131,4 +131,10 @@
     public int getNumVersions();
 
 
+    /**
+     * Returns the UUID of the versionable node that this history belongs to.
+     * 
+     * @return the UUID of the versionable node.
+     */
+    public String getVersionableUUID();
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java Thu Feb  3 03:23:20 2005
@@ -183,7 +183,7 @@
      * Returns the UUID of the node that was versioned.
      * @return
      */
-    public String getVersionedUUID() throws RepositoryException {
-        return getName();
+    public String getVersionableUUID() throws RepositoryException {
+        return history.getVersionableUUID();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java Thu Feb  3 03:23:20 2005
@@ -17,6 +17,8 @@
 package org.apache.jackrabbit.core.version;
 
 import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.virtual.VirtualNodeState;
 
@@ -48,6 +50,10 @@
                                       String parentUUID)
             throws RepositoryException {
         super(vm, parentUUID, vh.getId(), NodeTypeRegistry.NT_VERSION_HISTORY, new QName[0]);
+
+        // version history is referenceable
+        setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(vh.getId()));
+
         this.vh = vh;
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java Thu Feb  3 03:23:20 2005
@@ -184,21 +184,23 @@
                     state.setDefinitionId(NDEF_VERSION);
                     state.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(v.getCreated()));
                     // todo: do not read frozen stuff from frozen node instance here, rather put to version
-                    state.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(v.getFrozenNode().getFrozenUUID()));
-                    state.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, InternalValue.create(v.getFrozenNode().getFrozenPrimaryType()));
-                    state.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, InternalValue.create(v.getFrozenNode().getFrozenMixinTypes()));
-                    state.setPropertyValues(VersionManager.PROPNAME_VERSION_LABELS, PropertyType.STRING, InternalValue.create(v.getLabels()));
+                    //state.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(v.getFrozenNode().getFrozenUUID()));
+                    //state.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, InternalValue.create(v.getFrozenNode().getFrozenPrimaryType()));
+                    //state.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, InternalValue.create(v.getFrozenNode().getFrozenMixinTypes()));
+                    //state.setPropertyValues(VersionManager.PROPNAME_VERSION_LABELS, PropertyType.STRING, InternalValue.create(v.getLabels()));
                     state.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, new InternalValue[0]);
                     state.setPropertyValues(VersionManager.PROPNAME_SUCCESSORS, PropertyType.REFERENCE, new InternalValue[0]);
 
                 } else if (vi instanceof InternalFrozenNode) {
                     InternalFrozenNode fn = (InternalFrozenNode) vi;
                     VirtualNodeState parent = getNodeState(new NodeId(fn.getParent().getId()));
+                    boolean mimicFrozen = !(parent instanceof VersionNodeState);
                     state = createNodeState(parent,
                             VersionManager.NODENAME_FROZEN,
                             id.getUUID(),
-                            fn.getFrozenPrimaryType());
-                    mapFrozenNode(state, fn);
+                            mimicFrozen ? fn.getFrozenPrimaryType() :
+                            NodeTypeRegistry.NT_FROZEN_NODE);
+                    mapFrozenNode(state, fn, mimicFrozen);
 
                 } else if (vi instanceof InternalFrozenVersionHistory) {
                     InternalFrozenVersionHistory fn = (InternalFrozenVersionHistory) vi;
@@ -206,9 +208,10 @@
                     state = createNodeState(parent,
                             fn.getName(),
                             id.getUUID(),
-                            NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
-                    state.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(UUID.fromString(fn.getBaseVersionId())));
-                    state.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY, InternalValue.create(UUID.fromString(fn.getVersionHistoryId())));
+                            NodeTypeRegistry.NT_VERSIONED_CHILD);
+                    // IMO, this should be exposed aswell
+                    // state.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(UUID.fromString(fn.getBaseVersionId())));
+                    state.setPropertyValue(VersionManager.PROPNAME_CHILD, InternalValue.create(UUID.fromString(fn.getVersionHistoryId())));
                 } else {
                     // not found, throw
                     throw new NoSuchItemStateException(id.toString());
@@ -330,13 +333,22 @@
      * @throws RepositoryException
      */
     private VirtualNodeState mapFrozenNode(VirtualNodeState state,
-                                           InternalFrozenNode node)
+                                           InternalFrozenNode node,
+                                           boolean mimicFrozen)
             throws RepositoryException {
 
-        // map native stuff
-        state.setMixinNodeTypes(node.getFrozenMixinTypes());
-        if (node.getFrozenUUID() != null) {
-            state.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(node.getFrozenUUID()));
+        if (mimicFrozen) {
+            if (node.getFrozenUUID() != null) {
+                state.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(node.getFrozenUUID()));
+            }
+            state.setPropertyValues(ItemImpl.PROPNAME_MIXINTYPES, PropertyType.NAME, InternalValue.create(node.getFrozenMixinTypes()));
+        } else {
+            state.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(node.getId()));
+            if (node.getFrozenUUID() != null) {
+                state.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(node.getFrozenUUID()));
+            }
+            state.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, InternalValue.create(node.getFrozenPrimaryType()));
+            state.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, InternalValue.create(node.getFrozenMixinTypes()));
         }
 
         // map properties

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java Thu Feb  3 03:23:20 2005
@@ -40,7 +40,7 @@
     /**
      * the name of the frozen node
      */
-    public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozen");
+    public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenNode");
     /**
      * name of the 'jcr:frozenUUID' property
      */
@@ -77,6 +77,10 @@
      * name of the 'jcr:baseVersion' property
      */
     public static final QName PROPNAME_BASE_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "baseVersion");
+    /**
+     * name of the 'jcr:child' property
+     */
+    public static final QName PROPNAME_CHILD = new QName(NamespaceRegistryImpl.NS_JCR_URI, "child");
     /**
      * name of the 'jcr:created' property
      */

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java Thu Feb  3 03:23:20 2005
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.ItemImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.util.uuid.UUID;
@@ -51,6 +52,9 @@
             throws RepositoryException {
         super(vm, parentUUID, v.getId(), NodeTypeRegistry.NT_VERSION, new QName[0]);
         this.v = v;
+
+        // version is referenceable
+        setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(v.getId()));
 
         // add the frozen node id if not root version
         if (!v.isRootVersion()) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java Thu Feb  3 03:23:20 2005
@@ -79,6 +79,11 @@
     private String historyId;
 
     /**
+     * the if of the versionable node
+     */
+    private String versionableId;
+
+    /**
      * Creates a new VersionHistory object for the given node state.
      */
     InternalVersionHistoryImpl(PersistentVersionManager vMgr, PersistentNode node) throws RepositoryException {
@@ -99,6 +104,9 @@
         // get id
         historyId = (String) node.getPropertyValue(NativePVM.PROPNAME_HISTORY_ID).internalValue();
 
+        // get versionable id
+        versionableId = (String) node.getPropertyValue(NativePVM.PROPNAME_VERSIONABLE_ID).internalValue();
+
         // get entries
         PersistentNode[] children = node.getChildNodes();
         for (int i = 0; i < children.length; i++) {
@@ -417,6 +425,13 @@
         return versionCache.size();
     }
 
+    /**
+     * @see org.apache.jackrabbit.core.version.InternalVersionHistory#getVersionableUUID()
+     */
+    public String getVersionableUUID() {
+        return versionableId;
+    }
+
     protected String getUUID() {
         return node.getUUID();
     }
@@ -441,6 +456,9 @@
         PersistentNode pNode = parent.addNode(upd, name, NativePVM.NT_REP_VERSION_HISTORY);
         pNode.setPropertyValue(upd, NativePVM.PROPNAME_HISTORY_ID, InternalValue.create(historyId));
 
+        // set the versionable uuid
+        pNode.setPropertyValue(upd, NativePVM.PROPNAME_VERSIONABLE_ID, InternalValue.create(src.internalGetUUID()));
+        
         // create label node
         pNode.addNode(upd, NativePVM.NODENAME_VERSION_LABELS, NodeTypeRegistry.NT_UNSTRUCTURED);
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java Thu Feb  3 03:23:20 2005
@@ -144,7 +144,7 @@
         try {
             NodeState.ChildNodeEntry entry = node.getState().getChildNodeEntry(VersionManager.NODENAME_FROZEN, 1);
             if (entry == null) {
-                throw new IllegalStateException("version has no frozen node: " + getId());
+                throw new InternalError("version has no frozen node: " + getId());
             }
             return (InternalFrozenNode) getVersionManager().getItemByInternal(entry.getUUID());
         } catch (RepositoryException e) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java?view=diff&r1=151143&r2=151144
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java Thu Feb  3 03:23:20 2005
@@ -60,12 +60,15 @@
      * root path for version storage
      */
     public static final QName VERSION_HISTORY_ROOT_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "persistentVersionStorage");
-
     /**
      * name of the 'jcr:historyId' property
      */
     public static final QName PROPNAME_HISTORY_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "historyId");
     /**
+     * name of the 'jcr:versionableId' property
+     */
+    public static final QName PROPNAME_VERSIONABLE_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionableId");
+    /**
      * name of the 'jcr:versionId' property
      */
     public static final QName PROPNAME_VERSION_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionId");
@@ -152,11 +155,13 @@
      */
     public NativePVM(PersistenceManager pMgr, NodeTypeRegistry ntReg) throws RepositoryException {
         try {
+            long t1 = System.currentTimeMillis();
             this.stateMgr = new NativeItemStateManager(pMgr, PERSISTENT_ROOT_ID.getUUID(), ntReg);
             NodeState nodeState = (NodeState) stateMgr.getItemState(PERSISTENT_ROOT_ID);
             historyRoot = new PersistentNode(stateMgr, nodeState);
             initVirtualIds(historyRoot.getState());
-            log.info("loaded " + idsByExternal.size() + " virtual ids.");
+            long t2 = System.currentTimeMillis();
+            log.info("loaded " + idsByExternal.size() + " virtual ids in " + (t2-t1) + "ms.");
         } catch (ItemStateException e) {
             throw new RepositoryException("Unable to initialize PersistentVersionManager: " + e.toString(), e);
         }
@@ -235,6 +240,17 @@
     }
 
     /**
+     * Retrusn the version history that corresponds to the versionable node of
+     * the given uuid.
+     * @param uuid
+     * @return
+     */
+    private InternalVersionHistoryImpl getHistoryByVersionableUUID(String uuid) {
+        // @TODO: implement
+        return null;
+    }
+
+    /**
      * Creates a new Version History.
      *
      * @param node the node for which the version history is to be initialized
@@ -245,7 +261,7 @@
             throws RepositoryException {
 
         // check if version history for that node already exists
-        InternalVersionHistoryImpl hist = (InternalVersionHistoryImpl) getVersionHistory(node.internalGetUUID());
+        InternalVersionHistoryImpl hist = getHistoryByVersionableUUID(node.internalGetUUID());
         if (hist!=null) {
             return hist;
         }
@@ -588,32 +604,4 @@
             return type == TYPE_FROZEN;
         }
     }
-
-    private class Update implements UpdateOperation {
-
-        public NodeState createNew(String uuid, QName nodeTypeName, String parentUUID) {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public PropertyState createNew(QName propName, String parentUUID) {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public void store(ItemState state) {
-            //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public void store(NodeReferences refs) {
-            //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public void destroy(ItemState state) {
-            //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public void end() throws ItemStateException {
-            //To change body of implemented methods use File | Settings | File Templates.
-        }
-    }
-
 }