jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r126221 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: . observation search search/lucene state state/mem state/obj state/xml version version/persistence virtual xml
Date Sun, 23 Jan 2005 17:11:22 GMT
Author: stefan
Date: Sun Jan 23 09:11:20 2005
New Revision: 126221

URL: http://svn.apache.org/viewcvs?view=rev&rev=126221
Log:
redesigned transaction support & PersistenceManager

orginal code contributed by dominique pfister, required a lot of tweaking to make it run & work; not thoroughly tested
Added:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/XASessionImpl.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/AbstractPersistenceManager.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateManager.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionContext.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionException.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionListener.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/UpdateOperation.java   (contents, props changed)
Removed:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateProvider.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistableItemState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateProvider.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentNodeState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentPropertyState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ReferenceManager.java
Modified:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.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/VersionImpl.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/VersionManagerImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.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/InternalVersionItemImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java	Sun Jan 23 09:11:20 2005
@@ -32,13 +32,26 @@
     private static Logger log = Logger.getLogger(HierarchyManagerImpl.class);
 
     private final NodeId rootNodeId;
-    private final ItemStateProvider provider;
+    private final ItemStateManager provider;
+    private final ItemStateManager attic;
     // used for outputting user-friendly paths and names
     private final NamespaceResolver nsResolver;
 
-    public HierarchyManagerImpl(String rootNodeUUID, ItemStateProvider provider, NamespaceResolver nsResolver) {
-        rootNodeId = new NodeId(rootNodeUUID);
+    public HierarchyManagerImpl(String rootNodeUUID,
+                                ItemStateManager provider,
+                                NamespaceResolver nsResolver) {
+
+        this(rootNodeUUID, provider, nsResolver, null);
+    }
+
+    public HierarchyManagerImpl(String rootNodeUUID,
+                                ItemStateManager provider,
+                                NamespaceResolver nsResolver,
+                                ItemStateManager attic) {
+
+        this.rootNodeId = new NodeId(rootNodeUUID);
         this.provider = provider;
+        this.attic = attic;
         this.nsResolver = nsResolver;
     }
 
@@ -85,13 +98,13 @@
         ArrayList list = new ArrayList();
         try {
             if (id.denotesNode()) {
-                NodeState state = (NodeState) getItemState(id, false);
+                NodeState state = (NodeState) getItemState(id);
                 Iterator iter = state.getParentUUIDs().iterator();
                 while (iter.hasNext()) {
                     list.add(new NodeId((String) iter.next()));
                 }
             } else {
-                PropertyState state = (PropertyState) getItemState(id, false);
+                PropertyState state = (PropertyState) getItemState(id);
                 list.add(new NodeId(state.getParentUUID()));
             }
         } catch (NoSuchItemStateException e) {
@@ -112,7 +125,7 @@
     public ItemId[] listChildren(NodeId id) throws ItemNotFoundException, RepositoryException {
         NodeState parentState;
         try {
-            parentState = (NodeState) getItemState(id, false);
+            parentState = (NodeState) getItemState(id);
         } catch (NoSuchItemStateException e) {
             String msg = "failed to retrieve state of parent node " + id;
             log.error(msg, e);
@@ -191,7 +204,7 @@
 
         NodeState parentState;
         try {
-            parentState = (NodeState) getItemState(rootNodeId, false);
+            parentState = (NodeState) getItemState(rootNodeId);
         } catch (ItemStateException e) {
             String msg = "failed to retrieve state of root node";
             log.error(msg, e);
@@ -211,7 +224,7 @@
                     return new NodeId(nodeEntry.getUUID());
                 }
                 try {
-                    parentState = (NodeState) getItemState(new NodeId(nodeEntry.getUUID()), false);
+                    parentState = (NodeState) getItemState(new NodeId(nodeEntry.getUUID()));
                 } catch (ItemStateException e) {
                     String msg = "failed to retrieve state of intermediary node";
                     log.error(msg, e);
@@ -246,7 +259,7 @@
         try {
             Path.PathBuilder builder = new Path.PathBuilder();
 
-            ItemState state = getItemState(id, false);
+            ItemState state = getItemState(id);
             String parentUUID = state.getParentUUID();
             if (parentUUID == null) {
                 // specified id denotes the root node
@@ -254,7 +267,7 @@
                 return builder.getPath();
             }
 
-            NodeState parent = (NodeState) getItemState(new NodeId(parentUUID), false);
+            NodeState parent = (NodeState) getItemState(new NodeId(parentUUID));
             do {
                 if (state.isNode()) {
                     NodeState nodeState = (NodeState) state;
@@ -279,7 +292,7 @@
                 parentUUID = parent.getParentUUID();
                 if (parentUUID != null) {
                     state = parent;
-                    parent = (NodeState) getItemState(new NodeId(parentUUID), false);
+                    parent = (NodeState) getItemState(new NodeId(parentUUID));
                 } else {
                     parent = null;
                     state = null;
@@ -317,14 +330,14 @@
                 throw new ItemNotFoundException(nodeId.toString());
             }
             try {
-                NodeState nodeState = (NodeState) getItemState(nodeId, false);
+                NodeState nodeState = (NodeState) getItemState(nodeId);
                 String parentUUID = nodeState.getParentUUID();
                 if (parentUUID == null) {
                     // this is the root or an orphaned node
                     // FIXME
                     return new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, "");
                 }
-                parentState = (NodeState) getItemState(new NodeId(parentUUID), true);
+                parentState = (NodeState) getItemState(new NodeId(parentUUID));
             } catch (ItemStateException ise) {
                 String msg = "failed to resolve name of " + nodeId;
                 log.error(msg, ise);
@@ -403,6 +416,18 @@
 
     /**
      * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
+     */
+    private ItemState getItemState(ItemId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        return provider.getItemState(id);
+    }
+
+    /**
+     * @param id
      * @param includeZombies
      * @return
      * @throws NoSuchItemStateException
@@ -410,14 +435,14 @@
      */
     private ItemState getItemState(ItemId id, boolean includeZombies)
             throws NoSuchItemStateException, ItemStateException {
-        if (!includeZombies) {
+        if (!includeZombies || attic == null) {
             // get transient/persistent state
             return provider.getItemState(id);
         }
 
         try {
             // try attic first
-            return provider.getItemStateInAttic(id);
+            return attic.getItemState(id);
         } catch (NoSuchItemStateException e) {
             // fallback: get transient/persistent state
             return provider.getItemState(id);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java	Sun Jan 23 09:11:20 2005
@@ -95,7 +95,7 @@
     /**
      * <code>SessionItemStateManager</code> associated with this <code>Item</code>
      */
-    protected final SessionItemStateManager itemStateMgr;
+    protected final SessionItemStateManager stateMgr;
 
     /**
      * Listeners (weak references)
@@ -116,7 +116,7 @@
              ItemLifeCycleListener[] listeners) {
         this.session = session;
         rep = (RepositoryImpl) session.getRepository();
-        itemStateMgr = session.getItemStateManager();
+        stateMgr = session.getItemStateManager();
         this.id = id;
         this.itemMgr = itemMgr;
         this.state = state;
@@ -171,7 +171,7 @@
 
     protected abstract ItemState getOrCreateTransientItemState() throws RepositoryException;
 
-    protected abstract void makePersistent() throws RepositoryException;
+    protected abstract void makePersistent(UpdateOperation update);
 
     /**
      * Marks this instance as 'removed' and notifies its listeners.
@@ -191,13 +191,13 @@
             // this is a 'new' item, simply dispose the transient state
             // (it is no longer used); this will indirectly (through
             // stateDiscarded listener method) invalidate this instance permanently
-            itemStateMgr.disposeTransientItemState(transientState);
+            stateMgr.disposeTransientItemState(transientState);
         } else {
             // this is an 'existing' item (i.e. it is backed by persistent
             // state), mark it as 'removed'
             transientState.setStatus(ItemState.STATUS_EXISTING_REMOVED);
             // transfer the transient state to the attic
-            itemStateMgr.moveTransientItemStateToAttic(transientState);
+            stateMgr.moveTransientItemStateToAttic(transientState);
 
             // set state of this instance to 'invalid'
             status = STATUS_INVALIDATED;
@@ -382,7 +382,7 @@
 
         if (isNode()) {
             // build list of 'new' or 'modified' descendents
-            Iterator iter = itemStateMgr.getDescendantTransientItemStates(id);
+            Iterator iter = stateMgr.getDescendantTransientItemStates(id);
             while (iter.hasNext()) {
                 transientState = (ItemState) iter.next();
                 switch (transientState.getStatus()) {
@@ -431,7 +431,7 @@
         ItemState transientState;
 
         if (isNode()) {
-            Iterator iter = itemStateMgr.getDescendantTransientItemStatesInAttic(id);
+            Iterator iter = stateMgr.getDescendantTransientItemStatesInAttic(id);
             while (iter.hasNext()) {
                 transientState = (ItemState) iter.next();
                 // check if stale
@@ -658,9 +658,9 @@
         }
     }
 
-    private void checkReferences(Iterator iterDirty, Iterator iterRemoved,
-                                 ReferenceManager refMgr)
+    private Collection checkReferences(Iterator iterDirty, Iterator iterRemoved)
             throws ReferentialIntegrityException, RepositoryException {
+
         // map of target (node) id's and modified NodeReferences objects
         HashMap dirtyNodeRefs = new HashMap();
 
@@ -685,7 +685,14 @@
                             if (dirtyNodeRefs.containsKey(targetId)) {
                                 refs = (NodeReferences) dirtyNodeRefs.get(targetId);
                             } else {
-                                refs = refMgr.get(targetId);
+                                try {
+                                    refs = stateMgr.getNodeReferences(targetId);
+                                } catch (ItemStateException e) {
+                                    String msg = itemMgr.safeGetJCRPath(targetId)
+                                            + ": failed to load node references";
+                                    log.error(msg, e);
+                                    throw new RepositoryException(msg, e);
+                                }
                                 dirtyNodeRefs.put(targetId, refs);
                             }
                             // remove reference from target node
@@ -728,7 +735,14 @@
                         if (dirtyNodeRefs.containsKey(targetId)) {
                             refs = (NodeReferences) dirtyNodeRefs.get(targetId);
                         } else {
-                            refs = refMgr.get(targetId);
+                            try {
+                                refs = stateMgr.getNodeReferences(targetId);
+                            } catch (ItemStateException e) {
+                                String msg = itemMgr.safeGetJCRPath(targetId)
+                                        + ": failed to load node references";
+                                log.error(msg, e);
+                                throw new RepositoryException(msg, e);
+                            }
                             dirtyNodeRefs.put(targetId, refs);
                         }
                         // add reference to target node
@@ -761,7 +775,14 @@
                         if (dirtyNodeRefs.containsKey(targetId)) {
                             refs = (NodeReferences) dirtyNodeRefs.get(targetId);
                         } else {
-                            refs = refMgr.get(targetId);
+                            try {
+                                refs = stateMgr.getNodeReferences(targetId);
+                            } catch (ItemStateException e) {
+                                String msg = itemMgr.safeGetJCRPath(targetId)
+                                        + ": failed to load node references";
+                                log.error(msg, e);
+                                throw new RepositoryException(msg, e);
+                            }
                             dirtyNodeRefs.put(targetId, refs);
                         }
                         // remove reference to target node
@@ -783,7 +804,14 @@
             if (dirtyNodeRefs.containsKey(targetId)) {
                 refs = (NodeReferences) dirtyNodeRefs.get(targetId);
             } else {
-                refs = refMgr.get(targetId);
+                try {
+                    refs = stateMgr.getNodeReferences(targetId);
+                } catch (ItemStateException e) {
+                    String msg = itemMgr.safeGetJCRPath(targetId)
+                            + ": failed to load node references";
+                    log.error(msg, e);
+                    throw new RepositoryException(msg, e);
+                }
             }
             if (refs.hasReferences()) {
                 String msg = nodeState.getId()
@@ -793,45 +821,40 @@
             }
         }
 
-        // persist dirty NodeReferences objects
-        iter = dirtyNodeRefs.values().iterator();
-        while (iter.hasNext()) {
-            NodeReferences refs = (NodeReferences) iter.next();
-            refMgr.save(refs);
-        }
+        // return dirty NodeReferences objects
+        return dirtyNodeRefs.values();
     }
 
-    private void removeTransientItems(Iterator iter) throws RepositoryException {
+    private void removeTransientItems(UpdateOperation update,
+                                      Iterator iter) {
+
         /**
          * walk through list of transient items marked 'removed' and
          * definitively remove each one
          */
         while (iter.hasNext()) {
             ItemState transientState = (ItemState) iter.next();
-            PersistableItemState persistentState = (PersistableItemState) transientState.getOverlayedState();
+            ItemState persistentState = transientState.getOverlayedState();
             /**
-             * remove persistent state (incl. descendents, if there are any)
+             * remove persistent state
              *
              * this will indirectly (through stateDestroyed listener method)
              * permanently invalidate all Item instances wrapping it
              */
-            try {
-                persistentState.destroy();
-            } catch (ItemStateException ise) {
-                String msg = "failed to remove item " + transientState.getId();
-                log.error(msg, ise);
-                throw new RepositoryException(msg, ise);
-            }
+            update.destroy(persistentState);
         }
     }
 
-    private void persistTransientItems(Iterator iter) throws RepositoryException {
+    private void persistTransientItems(UpdateOperation update,
+                                       Iterator iter)
+            throws RepositoryException {
+
         // walk through list of transient items and persist each one
         while (iter.hasNext()) {
             ItemState itemState = (ItemState) iter.next();
             ItemImpl item = itemMgr.getItem(itemState.getId());
             // persist state of transient item
-            item.makePersistent();
+            item.makePersistent(update);
         }
     }
 
@@ -1126,7 +1149,7 @@
                  * turn on temporary path caching for better performance
                  * (assuming that the paths won't change during this save() call)
                  */
-                itemStateMgr.enablePathCaching(true);
+                stateMgr.enablePathCaching(true);
 
                 // build list of transient states that should be persisted
                 Collection dirty = getTransientStates();
@@ -1157,7 +1180,7 @@
                             NodeId id = new NodeId((String) parentsIter.next());
                             NodeState parentState = null;
                             try {
-                                parentState = (NodeState) itemStateMgr.getTransientItemState(id);
+                                parentState = (NodeState) stateMgr.getTransientItemState(id);
                             } catch (ItemStateException ise) {
                                 // should never get here...
                                 String msg = "inconsistency: failed to retrieve transient state for " + itemMgr.safeGetJCRPath(id);
@@ -1189,49 +1212,36 @@
                         session.getItemStateManager(), session.getHierarchyManager());
 
                 /**
-                 * we need to make sure that we are not interrupted while
-                 * verifying/persisting node references
+                 * build list of transient descendents in the attic
+                 * (i.e. those marked as 'removed')
                  */
-                ReferenceManager refMgr = wsp.getReferenceManager();
-                synchronized (refMgr) {
-                    /**
-                     * build list of transient descendents in the attic
-                     * (i.e. those marked as 'removed')
-                     */
-                    Collection removed = getRemovedStates();
+                Collection removed = getRemovedStates();
 
-                    /**
-                     * referential integrity checks:
-                     * make sure that a referenced node cannot be removed and
-                     * that all references are updated and persisted
-                     */
-                    checkReferences(dirty.iterator(), removed.iterator(), refMgr);
+                /**
+                 * referential integrity checks:
+                 * make sure that a referenced node cannot be removed and
+                 * that all references are updated and persisted
+                 */
+                Collection dirtyRefs =
+                        checkReferences(dirty.iterator(), removed.iterator());
 
-                    /**
-                     * create event states for the affected item states and
-                     * prepare them for event dispatch (this step is necessary in order
-                     * to check access rights on items that will be removed)
-                     *
-                     * todo consolidate event generating and dispatching code (ideally one method call after save has succeeded)
-                     */
-                    events.createEventStates(dirty);
-                    events.createEventStates(removed);
-                    events.prepare();
-
-                    // definitively remove transient items marked as 'removed'
-                    removeTransientItems(removed.iterator());
-
-                    // dispose the transient states marked 'removed'
-                    iter = removed.iterator();
-                    while (iter.hasNext()) {
-                        transientState = (ItemState) iter.next();
-                        /**
-                         * dispose the transient state, it is no longer used
-                         * this will indirectly (through stateDiscarded listener method)
-                         * permanently invalidate the wrapping Item instance
-                         */
-                        itemStateMgr.disposeTransientItemStateInAttic(transientState);
-                    }
+                /**
+                 * create event states for the affected item states and
+                 * prepare them for event dispatch (this step is necessary in order
+                 * to check access rights on items that will be removed)
+                 *
+                 * todo consolidate event generating and dispatching code (ideally one method call after save has succeeded)
+                 */
+                events.createEventStates(removed);
+                events.createEventStates(dirty);
+                events.prepare();
+
+                try {
+                    // start the update operation
+                    UpdateOperation update = stateMgr.beginUpdate();
+
+                    // process transient items marked as 'removed'
+                    removeTransientItems(update, removed.iterator());
 
                     // initialize version histories for new nodes (might generate new transient state)
                     if (initVersionHistories(dirty.iterator())) {
@@ -1242,16 +1252,39 @@
                         dirty = getTransientStates();
                     }
 
-                    // persist 'new' or 'modified' transient states
-                    persistTransientItems(dirty.iterator());
-                } // synchronized(refMgr)
+                    // process 'new' or 'modified' transient states
+                    persistTransientItems(update, dirty.iterator());
+
+                    // store the references calculated above
+                    for (Iterator it = dirtyRefs.iterator(); it.hasNext();) {
+                        update.store((NodeReferences) it.next());
+                    }
+
+                    // end update operation
+                    update.end();
 
-                // now it is safe to dispose the transient states
+                } catch (ItemStateException e) {
+
+                    String msg = safeGetJCRPath() + ": unable to update item.";
+                    log.error(msg);
+                    throw new RepositoryException(msg, e);
+
+                }
+
+                // now it is safe to dispose the transient states:
+                // dispose the transient states marked 'removed'
+                iter = removed.iterator();
+                while (iter.hasNext()) {
+                    transientState = (ItemState) iter.next();
+                    // dispose the transient state, it is no longer used
+                    stateMgr.disposeTransientItemStateInAttic(transientState);
+                }
+                // dispose the transient states marked 'new' or 'modified'
                 iter = dirty.iterator();
                 while (iter.hasNext()) {
                     transientState = (ItemState) iter.next();
                     // dispose the transient state, it is no longer used
-                    itemStateMgr.disposeTransientItemState(transientState);
+                    stateMgr.disposeTransientItemState(transientState);
                 }
 
                 /**
@@ -1261,9 +1294,10 @@
                  * transactional support
                  */
                 session.dispatch(events);
+
             } finally {
                 // turn off temporary path caching
-                itemStateMgr.enablePathCaching(false);
+                stateMgr.enablePathCaching(false);
             }
         }
     }
@@ -1287,7 +1321,7 @@
             // check if this is the repository root node
             if (((NodeImpl) this).isRepositoryRoot()) {
                 // optimization
-                itemStateMgr.disposeAllTransientItemStates();
+                stateMgr.disposeAllTransientItemStates();
                 return;
             }
         }
@@ -1298,7 +1332,7 @@
 
         // check status of this item's state
         if (isTransient()) {
-            transientState = (ItemState) state;
+            transientState = state;
             switch (transientState.getStatus()) {
                 case ItemState.STATUS_STALE_MODIFIED:
                 case ItemState.STATUS_STALE_DESTROYED:
@@ -1323,7 +1357,7 @@
 
         if (isNode()) {
             // build list of 'new', 'modified' or 'stale' descendents
-            Iterator iter = itemStateMgr.getDescendantTransientItemStates(id);
+            Iterator iter = stateMgr.getDescendantTransientItemStates(id);
             while (iter.hasNext()) {
                 transientState = (ItemState) iter.next();
                 switch (transientState.getStatus()) {
@@ -1350,17 +1384,17 @@
             // dispose the transient state, it is no longer used;
             // this will indirectly (through stateDiscarded listener method)
             // either restore or permanently invalidate the wrapping Item instances
-            itemStateMgr.disposeTransientItemState(transientState);
+            stateMgr.disposeTransientItemState(transientState);
         }
 
         // discard all transient descendents in the attic (i.e. those marked
         // as 'removed'); this will resurrect the removed items
-        iter = itemStateMgr.getDescendantTransientItemStatesInAttic(id);
+        iter = stateMgr.getDescendantTransientItemStatesInAttic(id);
         while (iter.hasNext()) {
             transientState = (ItemState) iter.next();
             // dispose the transient state; this will indirectly (through
             // stateDiscarded listener method) resurrect the wrapping Item instances
-            itemStateMgr.disposeTransientItemStateInAttic(transientState);
+            stateMgr.disposeTransientItemStateInAttic(transientState);
         }
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java	Sun Jan 23 09:11:20 2005
@@ -65,7 +65,7 @@
 
     private final SessionImpl session;
 
-    private final ItemStateProvider itemStateProvider;
+    private final ItemStateManager itemStateProvider;
     private final HierarchyManager hierMgr;
 
     private NodeImpl root;
@@ -84,7 +84,7 @@
      * @param rootNodeDef       the definition of the root node
      * @param rootNodeUUID      the UUID of the root node
      */
-    ItemManager(ItemStateProvider itemStateProvider, HierarchyManager hierMgr,
+    ItemManager(ItemStateManager itemStateProvider, HierarchyManager hierMgr,
                 SessionImpl session, NodeDef rootNodeDef, String rootNodeUUID) {
         this.itemStateProvider = itemStateProvider;
         this.hierMgr = hierMgr;
@@ -138,7 +138,6 @@
             ps.print(item.isTransient() ? "transient " : "          ");
             ps.println(id + "\t" + item.getPath() + " (" + item + ")");
         }
-        ps.println();
     }
 
     /**
@@ -329,7 +328,7 @@
         }
 
         // shortcut
-        if (id.denotesNode() && ((NodeId) id).equals(rootNodeId)) {
+        if (id.denotesNode() && id.equals(rootNodeId)) {
             return getRoot();
         }
 

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java	Sun Jan 23 09:11:20 2005
@@ -194,7 +194,7 @@
             try {
                 // make transient (copy-on-write)
                 NodeState transientState =
-                        itemStateMgr.createTransientNodeState((NodeState) state, ItemState.STATUS_EXISTING_MODIFIED);
+                        stateMgr.createTransientNodeState((NodeState) state, ItemState.STATUS_EXISTING_MODIFIED);
                 // remove listener on persistent state
                 state.removeListener(this);
                 // add listener on transient state
@@ -308,10 +308,15 @@
             throws RepositoryException {
         status.clear();
 
-        PropertyId propId = new PropertyId(((NodeState) state).getUUID(), name);
-        if (itemMgr.itemExists(propId)) {
+        NodeState thisState = (NodeState) state;
+        if (thisState.hasPropertyEntry(name)) {
+            /**
+             * the following call will throw ItemNotFoundException if the
+             * current session doesn't have read access
+             */
             return getProperty(name);
         }
+
         // does not exist yet:
         // find definition for the specified property and create property
         PropertyDefImpl def = getApplicablePropertyDef(name, type, multiValued);
@@ -328,7 +333,7 @@
             log.error(msg);
             throw new RepositoryException(msg);
         }
-        // check if versioning allows write (only cheep call)
+        // check if versioning allows write (only cheap call)
         if (!isCheckedOut(false)) {
             String msg = "Cannot set the value of a property of a checked-in node " + safeGetJCRPath() + "/" + name.toString();
             log.error(msg);
@@ -340,7 +345,7 @@
         // create a new property state
         PropertyState propState = null;
         try {
-            propState = itemStateMgr.createTransientPropertyState(parentUUID, name, ItemState.STATUS_NEW);
+            propState = stateMgr.createTransientPropertyState(parentUUID, name, ItemState.STATUS_NEW);
             propState.setType(type);
             propState.setMultiValued(def.isMultiple());
             propState.setDefinitionId(new PropDefId(def.unwrap()));
@@ -386,7 +391,7 @@
             if (uuid == null) {
                 uuid = UUID.randomUUID().toString();	// version 4 uuid
             }
-            nodeState = itemStateMgr.createTransientNodeState(uuid, nodeType.getQName(), parentUUID, ItemState.STATUS_NEW);
+            nodeState = stateMgr.createTransientNodeState(uuid, nodeType.getQName(), parentUUID, ItemState.STATUS_NEW);
             nodeState.setDefinitionId(new NodeDefId(def.unwrap()));
         } catch (ItemStateException ise) {
             String msg = "failed to add child node " + name + " to " + safeGetJCRPath();
@@ -400,7 +405,7 @@
             node = itemMgr.createNodeInstance(nodeState, def);
         } catch (RepositoryException re) {
             // something went wrong
-            itemStateMgr.disposeTransientItemState(nodeState);
+            stateMgr.disposeTransientItemState(nodeState);
             // re-throw
             throw re;
         }
@@ -663,7 +668,7 @@
             }
         }
 
-        // check if versioning allows write (only cheep call)
+        // check if versioning allows write (only cheap call)
         if (!isCheckedOut(false)) {
             String msg = safeGetJCRPath() + ": cannot add a child to a checked-in node";
             log.error(msg);
@@ -767,48 +772,43 @@
         return session.getNodeTypeManager().getPropDef(new PropDefId(pd));
     }
 
-    protected void makePersistent() throws RepositoryException {
+    protected void makePersistent(UpdateOperation update) {
         if (!isTransient()) {
             log.debug(safeGetJCRPath() + " (" + id + "): there's no transient state to persist");
             return;
         }
 
-        try {
-            NodeState transientState = (NodeState) state;
+        NodeState transientState = (NodeState) state;
 
-            PersistentNodeState persistentState = (PersistentNodeState) transientState.getOverlayedState();
-            if (persistentState == null) {
-                // this node is 'new'
-                persistentState = itemStateMgr.createPersistentNodeState(transientState.getUUID(), transientState.getNodeTypeName(), transientState.getParentUUID());
-            }
-            // copy state from transient state:
-            // parent uuid's
-            persistentState.setParentUUID(transientState.getParentUUID());
-            persistentState.setParentUUIDs(transientState.getParentUUIDs());
-            // mixin types
-            persistentState.setMixinTypeNames(transientState.getMixinTypeNames());
-            // id of definition
-            persistentState.setDefinitionId(transientState.getDefinitionId());
-            // child node entries
-            persistentState.setChildNodeEntries(transientState.getChildNodeEntries());
-            // property entries
-            persistentState.setPropertyEntries(transientState.getPropertyEntries());
-
-            // make state persistent
-            persistentState.store();
-            // remove listener from transient state
-            transientState.removeListener(this);
-            // add listener to persistent state
-            persistentState.addListener(this);
-            // swap transient state with persistent state
-            state = persistentState;
-            // reset status
-            status = STATUS_NORMAL;
-        } catch (ItemStateException ise) {
-            String msg = "failed to persist transient state of " + safeGetJCRPath() + " (" + id + ")";
-            log.error(msg, ise);
-            throw new RepositoryException(msg, ise);
-        }
+        NodeState persistentState = (NodeState) transientState.getOverlayedState();
+        if (persistentState == null) {
+            // this node is 'new'
+            persistentState = update.createNew(transientState.getUUID(),
+                    transientState.getNodeTypeName(), transientState.getParentUUID());
+        }
+        // copy state from transient state:
+        // parent uuid's
+        persistentState.setParentUUID(transientState.getParentUUID());
+        persistentState.setParentUUIDs(transientState.getParentUUIDs());
+        // mixin types
+        persistentState.setMixinTypeNames(transientState.getMixinTypeNames());
+        // id of definition
+        persistentState.setDefinitionId(transientState.getDefinitionId());
+        // child node entries
+        persistentState.setChildNodeEntries(transientState.getChildNodeEntries());
+        // property entries
+        persistentState.setPropertyEntries(transientState.getPropertyEntries());
+
+        // make state persistent
+        update.store(persistentState);
+        // remove listener from transient state
+        transientState.removeListener(this);
+        // add listener to persistent state
+        persistentState.addListener(this);
+        // swap transient state with persistent state
+        state = persistentState;
+        // reset status
+        status = STATUS_NORMAL;
     }
 
     /**
@@ -850,7 +850,7 @@
         PropertyImpl prop = getOrCreateProperty(name, type, false, status);
         try {
             if (value == null) {
-                prop.internalSetValue((InternalValue[]) null, type);
+                prop.internalSetValue(null, type);
             } else {
                 prop.internalSetValue(new InternalValue[]{value}, type);
             }
@@ -1334,7 +1334,7 @@
             throw new ItemNotFoundException(safeGetJCRPath() + " has no child node with name " + destName);
         }
 
-        // check if versioning allows write (only cheep call)
+        // check if versioning allows write (only cheap call)
         if (!isCheckedOut(false)) {
             String msg = safeGetJCRPath() + ": cannot change child node ordering of a checked-in node";
             log.error(msg);
@@ -2209,13 +2209,15 @@
      * @see Node#getReferences()
      */
     public PropertyIterator getReferences() throws RepositoryException {
-        WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace();
-        ReferenceManager refMgr = wsp.getReferenceManager();
-        synchronized (refMgr) {
-            NodeReferences refs = refMgr.get((NodeId) id);
+        try {
+            NodeReferences refs = stateMgr.getNodeReferences((NodeId) id);
             // refs.getReferences returns a list of PropertyId's
             List idList = refs.getReferences();
             return new LazyItemIterator(itemMgr, idList);
+        } catch (ItemStateException e) {
+            String msg = "Unable to retrieve node references for: " + id;
+            log.error(msg);
+            throw new RepositoryException(msg, e);
         }
     }
 
@@ -2840,7 +2842,7 @@
 
         // get frozen node type
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
-        NodeTypeImpl nt = (NodeTypeImpl) ntMgr.getNodeType(frozen.getFrozenPrimaryType());
+        NodeTypeImpl nt = ntMgr.getNodeType(frozen.getFrozenPrimaryType());
 
         // get frozen uuid
         String uuid = frozen.getFrozenUUID();
@@ -2888,7 +2890,7 @@
 
         // get frozen node type
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
-        NodeTypeImpl nt = (NodeTypeImpl) ntMgr.getNodeType(frozen.getFrozenPrimaryType());
+        NodeTypeImpl nt = ntMgr.getNodeType(frozen.getFrozenPrimaryType());
 
         // get frozen uuid
         String uuid = frozen.getFrozenUUID();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Path.java	Sun Jan 23 09:11:20 2005
@@ -23,55 +23,55 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
-import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * The <code>Path</code> utility class provides misc. methods to resolve and
  * nornalize JCR-style item paths. <br>
  * Each path consistnes of path elements and is immutable. it has the following
  * properties:<br>
- * <code>isAbsolute()</code>:<br>
+ * <code>absolute()</code>:<br>
  * A path is absolute, if the first path element denotes the root element '/'.
- * <p>
+ * <p/>
  * <code>isRelative()</code>:<br>
  * A path is relative, if the first path element does not denote the root element.
- * I.e. is always the opposite of <code>isAbsolute</code>.
- * <p>
- * <code>isNormalized()</code>:<br>
+ * I.e. is always the opposite of <code>absolute</code>.
+ * <p/>
+ * <code>normalized()</code>:<br>
  * A path is normalized, if all '.' and '..' path elements are resolved as much
  * as possible. If the path is absolute, it is normalized if it contains
  * no such elements. for example the path '../../a' is normalized where as
  * '../../b/../a/.' is not. Normalized path never have '.' elements.
  * absolte normalilzed paths have no and relative normalized paths have no or
  * only leading '..' elements.<br>
- * <p>
+ * <p/>
  * <code>isCanonical()</code>:<br>
  * A path is canonical, if its absolute and normalized.
- * <p>
- *
+ * <p/>
+ * <p/>
  * the external string representation of a path has the following format:
- *
+ * <p/>
  * <xmp>
- *           path ::= properpath ['/']
- *     properpath ::= abspath | relpath
- *        abspath ::= '/' relpath
- *        relpath ::= [relpath '/'] pathelement
- *    pathelement ::= name ['[' number ']']
- *         number ::= << An integer > 0 >>
- *
- *           name ::= [prefix ':'] simplename
- *         prefix ::= << Any valid XML Name >>
- *     simplename ::= nonspacestring [[string] nonspacestring]
- *         string ::= [string] char
- *           char ::= nonspace | space
+ * path ::= properpath ['/']
+ * properpath ::= abspath | relpath
+ * abspath ::= '/' relpath
+ * relpath ::= [relpath '/'] pathelement
+ * pathelement ::= name ['[' number ']']
+ * number ::= << An integer > 0 >>
+ * <p/>
+ * name ::= [prefix ':'] simplename
+ * prefix ::= << Any valid XML Name >>
+ * simplename ::= nonspacestring [[string] nonspacestring]
+ * string ::= [string] char
+ * char ::= nonspace | space
  * nonspacestring ::= [nonspacestring] nonspace
- *          space ::= << ' ' (the space character) >>
- *       nonspace ::= << Any Unicode character except
- *                    '/', ':', '[', ']', '*',
- *                    '''(the single quote),
- *                    '"'(the double quote),
- *                    any whitespace character >>
+ * space ::= << ' ' (the space character) >>
+ * nonspace ::= << Any Unicode character except
+ * '/', ':', '[', ']', '*',
+ * '''(the single quote),
+ * '"'(the double quote),
+ * any whitespace character >>
  * </xmp>
  */
 public final class Path {
@@ -118,12 +118,12 @@
     /**
      * flag indicating if this path is normalized
      */
-    private final boolean isNormalized;
+    private final boolean normalized;
 
     /**
      * flag indicating if this path is absolute
      */
-    private final boolean isAbsolute;
+    private final boolean absolute;
 
     /**
      * the cached hashcode of this path
@@ -142,12 +142,12 @@
      * @param isNormalized
      */
     private Path(PathElement[] elements, boolean isNormalized) {
-        if (elements==null || elements.length==0) {
+        if (elements == null || elements.length == 0) {
             throw new IllegalArgumentException("Empty paths are not allowed");
         }
         this.elements = elements;
-        this.isAbsolute = elements[0].denotesRoot();
-        this.isNormalized = isNormalized;
+        this.absolute = elements[0].denotesRoot();
+        this.normalized = isNormalized;
     }
 
     //----------------------------------------------------< factory methods >---
@@ -166,8 +166,8 @@
                               boolean normalize)
             throws MalformedPathException {
         return normalize
-            ? parse(jcrPath, null, resolver).getNormalizedPath()
-            : parse(jcrPath, null, resolver);
+                ? parse(jcrPath, null, resolver).getNormalizedPath()
+                : parse(jcrPath, null, resolver);
     }
 
     /**
@@ -212,8 +212,8 @@
         pb.addAll(relPath.getElements());
 
         return normalize
-            ? pb.getPath().getNormalizedPath()
-            : pb.getPath();
+                ? pb.getPath().getNormalizedPath()
+                : pb.getPath();
     }
 
     /**
@@ -302,7 +302,7 @@
      * @return true if this path represents the root path; false otherwise.
      */
     public boolean denotesRoot() {
-        return isAbsolute && elements.length == 1;
+        return absolute && elements.length == 1;
     }
 
     /**
@@ -311,7 +311,7 @@
      * @return true if this path is absolute; false otherwise.
      */
     public boolean isAbsolute() {
-        return isAbsolute;
+        return absolute;
     }
 
     /**
@@ -322,7 +322,7 @@
      * @see #isAbsolute()
      */
     public boolean isCanonical() {
-        return isAbsolute && isNormalized;
+        return absolute && normalized;
     }
 
     /**
@@ -338,7 +338,7 @@
      * @see #getNormalizedPath()
      */
     public boolean isNormalized() {
-        return isNormalized;
+        return normalized;
     }
 
     /**
@@ -346,14 +346,14 @@
      * involves removing/resolving redundant elements such as "." and ".." from
      * the path, e.g. "/a/./b/.." will be normalized to "/a", "../../a/b/c/.."
      * will be normalized to "../../a/b", and so on.
-     * <p>
+     * <p/>
      * If the normalized path results in an empty path (eg: 'a/..') or if an
      * absolute path is normalized that would result in a 'negative' path
      * (eg: /a/../../) a MalformedPathException is thrown.
      *
      * @return a normailzed path representation of this path
-     * @see #isNormalized()
      * @throws MalformedPathException if the path cannot be normalized.
+     * @see #isNormalized()
      */
     public Path getNormalizedPath() throws MalformedPathException {
         if (isNormalized()) {
@@ -365,7 +365,7 @@
             PathElement elem = elements[i];
             if (elem.denotesCurrent()) {
                 continue;
-            } else if (elem.denotesParent() && last!=null && !last.denotesParent()) {
+            } else if (elem.denotesParent() && last != null && !last.denotesParent()) {
                 if (last.denotesRoot()) {
                     // the first element is the root element;
                     // ".." would refer to the parent of root
@@ -374,7 +374,7 @@
                 queue.removeLast();
                 last = queue.isEmpty() ? null : (PathElement) queue.getLast();
             } else {
-                queue.add(last=elem);
+                queue.add(last = elem);
             }
         }
         if (queue.isEmpty()) {
@@ -439,7 +439,7 @@
         for (int i = 0; i < length; i++) {
             elements[i] = this.elements[i];
         }
-        return new Path(elements, isNormalized);
+        return new Path(elements, normalized);
     }
 
     /**
@@ -746,6 +746,7 @@
 
         /**
          * Adds the given elemenets
+         *
          * @param elements
          */
         void addAll(PathElement[] elements) {
@@ -756,6 +757,7 @@
 
         /**
          * Inserts the element at the beginning of the path to be built.
+         *
          * @param elem
          */
         public void addFirst(PathElement elem) {
@@ -771,6 +773,7 @@
 
         /**
          * Inserts the element at the beginning of the path to be built.
+         *
          * @param name
          */
         void addFirst(QName name) {
@@ -779,6 +782,7 @@
 
         /**
          * Inserts the element at the beginning of the path to be built.
+         *
          * @param name
          * @param index
          */
@@ -788,6 +792,7 @@
 
         /**
          * Inserts the element at the end of the path to be built.
+         *
          * @param elem
          */
         public void addLast(PathElement elem) {
@@ -798,6 +803,7 @@
 
         /**
          * Inserts the element at the end of the path to be built.
+         *
          * @param name
          */
         void addLast(QName name) {
@@ -806,6 +812,7 @@
 
         /**
          * Inserts the element at the end of the path to be built.
+         *
          * @param name
          * @param index
          */
@@ -815,6 +822,7 @@
 
         /**
          * Assembles the built path and returns a new {@link Path}.
+         *
          * @return
          * @throws MalformedPathException if the internal path element queue is empty.
          */
@@ -1057,7 +1065,8 @@
             sb.append(name.toJCRName(resolver));
             // index
             int index = getIndex();
-            /** FIXME the [1] subscript should only be suppressed if the item
+            /**
+             * FIXME the [1] subscript should only be suppressed if the item
              * in question can't have same-name siblings.
              */
             //if (index > 0) {
@@ -1169,7 +1178,7 @@
         boolean isNormalized = true;
         boolean leadingParent = true;
         if (master != null) {
-            isNormalized = master.isNormalized;
+            isNormalized = master.normalized;
             // a master path was specified; the 'path' argument is assumed
             // to be a relative path
             for (int i = 0; i < master.elements.length; i++) {
@@ -1196,7 +1205,7 @@
             }
             Matcher matcher = PATH_ELEMENT_PATTERN.matcher(elem);
             if (matcher.matches()) {
-                if (resolver==null) {
+                if (resolver == null) {
                     // check only
                     continue;
                 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PropertyImpl.java	Sun Jan 23 09:11:20 2005
@@ -17,10 +17,7 @@
 package org.apache.jackrabbit.core;
 
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.state.ItemState;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.PersistentPropertyState;
-import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.*;
 import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.log4j.Logger;
 
@@ -66,7 +63,7 @@
             // make transient (copy-on-write)
             try {
                 PropertyState transientState =
-                        itemStateMgr.createTransientPropertyState((PropertyState) state, ItemState.STATUS_EXISTING_MODIFIED);
+                        stateMgr.createTransientPropertyState((PropertyState) state, ItemState.STATUS_EXISTING_MODIFIED);
                 // remove listener on persistent state
                 state.removeListener(this);
                 // add listener on transient state
@@ -82,40 +79,35 @@
         return state;
     }
 
-    protected void makePersistent() throws RepositoryException {
+    protected void makePersistent(UpdateOperation update) {
         if (!isTransient()) {
-            String msg = "there's no transient state to persist";
-            log.error(msg);
-            throw new RepositoryException(msg);
+            log.debug(safeGetJCRPath() + " (" + id + "): there's no transient state to persist");
+            return;
         }
 
-        try {
-            PropertyState transientState = (PropertyState) state;
-            PersistentPropertyState persistentState = (PersistentPropertyState) transientState.getOverlayedState();
-            if (persistentState == null) {
-                // this property is 'new'
-                persistentState = itemStateMgr.createPersistentPropertyState(transientState.getParentUUID(), transientState.getName());
-            }
-            // copy state from transient state
-            persistentState.setDefinitionId(transientState.getDefinitionId());
-            persistentState.setType(transientState.getType());
-            persistentState.setMultiValued(transientState.isMultiValued());
-            persistentState.setValues(transientState.getValues());
-            // make state persistent
-            persistentState.store();
-            // remove listener from transient state
-            transientState.removeListener(this);
-            // add listener to persistent state
-            persistentState.addListener(this);
-            // swap transient state with persistent state
-            state = persistentState;
-            // reset status
-            status = STATUS_NORMAL;
-        } catch (ItemStateException ise) {
-            String msg = "failed to persist transient state of " + safeGetJCRPath();
-            log.error(msg, ise);
-            throw new RepositoryException(msg, ise);
-        }
+        PropertyState transientState = (PropertyState) state;
+        PropertyState persistentState = (PropertyState) transientState.getOverlayedState();
+        if (persistentState == null) {
+            // this property is 'new'
+            persistentState = update.createNew(
+                    transientState.getName(),
+                    transientState.getParentUUID());
+        }
+        // copy state from transient state
+        persistentState.setDefinitionId(transientState.getDefinitionId());
+        persistentState.setType(transientState.getType());
+        persistentState.setMultiValued(transientState.isMultiValued());
+        persistentState.setValues(transientState.getValues());
+        // make state persistent
+        update.store(persistentState);
+        // remove listener from transient state
+        transientState.removeListener(this);
+        // add listener to persistent state
+        persistentState.addListener(this);
+        // swap transient state with persistent state
+        state = persistentState;
+        // reset status
+        status = STATUS_NORMAL;
     }
 
     /**
@@ -190,7 +182,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -243,7 +235,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -533,7 +525,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -578,7 +570,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -618,7 +610,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -669,7 +661,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -713,7 +705,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -764,7 +756,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -804,7 +796,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -856,7 +848,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 
@@ -896,7 +888,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             String msg = "Cannot alter the value of a property of a checked-in node " + safeGetJCRPath();
             log.error(msg);
             throw new VersionException(msg);
@@ -942,7 +934,7 @@
         sanityCheck();
 
         // check if versioning allows write
-        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheep call yet
+        if (!((NodeImpl) getParent()).isCheckedOut(false)) { // only cheap call yet
             throw new VersionException("Cannot alter the value of a property of a checked-in node " + safeGetJCRPath());
         }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/QName.java	Sun Jan 23 09:11:20 2005
@@ -18,29 +18,28 @@
 
 import javax.jcr.NamespaceException;
 import java.io.Serializable;
-import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * <code>QName</code> represents the qualified name of a repository item
  * (i.e. <code>Node</code> or <code>Property</code>) or a node type.
- * <p>
+ * <p/>
  * The external string representation is specified as follows:
  * <xmp>
- *           name ::= [prefix ':'] simplename
- *         prefix ::= << Any valid XML Name >>
- *     simplename ::= nonspacestring [[string] nonspacestring]
- *         string ::= [string] char
- *           char ::= nonspace | space
+ * name ::= [prefix ':'] simplename
+ * prefix ::= << Any valid XML Name >>
+ * simplename ::= nonspacestring [[string] nonspacestring]
+ * string ::= [string] char
+ * char ::= nonspace | space
  * nonspacestring ::= [nonspacestring] nonspace
- *          space ::= << ' ' (the space character) >>
- *       nonspace ::= << Any Unicode character except
- *                    '/', ':', '[', ']', '*',
- *                    '''(the single quote),
- *                    '"'(the double quote),
- *                    any whitespace character >>
+ * space ::= << ' ' (the space character) >>
+ * nonspace ::= << Any Unicode character except
+ * '/', ':', '[', ']', '*',
+ * '''(the single quote),
+ * '"'(the double quote),
+ * any whitespace character >>
  * </xmp>
- *
  */
 public class QName implements Cloneable, Comparable, Serializable {
 
@@ -93,7 +92,7 @@
      */
     public static QName fromJCRName(String rawName, NamespaceResolver resolver)
             throws IllegalNameException, UnknownPrefixException {
-        if (resolver==null) {
+        if (resolver == null) {
             throw new NullPointerException("resolver must not be null");
         }
         return internalFromJCRName(rawName, resolver);
@@ -157,7 +156,7 @@
      * internally just to check the format of the given string by passing a
      * <code>null</code> value as <code>resolver</code>
      *
-     * @param rawName the jcr name to parse
+     * @param rawName  the jcr name to parse
      * @param resolver the namespace resolver or <code>null</code>
      * @return a new resolved QName
      * @throws IllegalNameException
@@ -192,7 +191,7 @@
             throw new IllegalNameException("'" + rawName + "' is not a valid name");
         }
 
-        if (resolver==null) {
+        if (resolver == null) {
             return null;
         } else {
             String uri;

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	Sun Jan 23 09:11:20 2005
@@ -27,10 +27,10 @@
 import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.observation.ObservationManagerFactory;
-import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.state.xml.XMLPersistenceManager;
-import org.apache.jackrabbit.core.state.tx.TransactionManager;
-import org.apache.jackrabbit.core.state.tx.XASessionImpl;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.PMContext;
+import org.apache.jackrabbit.core.state.PersistenceManager;
+import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.jackrabbit.core.version.PersistentVersionManager;
 import org.apache.jackrabbit.core.version.VersionManager;
@@ -58,7 +58,7 @@
     /**
      * hardcoded uuid of the repository root node
      */
-    private static final String ROOT_NODE_UUID = "ac3b5c25-613d-4798-8494-ffbcca9c5c6c";
+    private static final String ROOT_NODE_UUID = "cafebabe-cafe-babe-cafe-babecafebabe";
 
     private static final String ANONYMOUS_USER = "anonymous";
 
@@ -90,7 +90,6 @@
     private final NodeTypeRegistry ntReg;
     private final PersistentVersionManager pvMgr;
     private final VersionManager vMgr;
-    private final TransactionManager txMgr;
 
     // configuration of the repository
     private final RepositoryConfig repConfig;
@@ -153,7 +152,6 @@
         }
         versionStore = new BasedFileSystem(repStore, fsRootPath);
 
-
         FileSystemResource uuidFile = new FileSystemResource(metaDataStore, "rootUUID");
         try {
             if (uuidFile.exists()) {
@@ -249,17 +247,6 @@
         nodesCount = Long.parseLong(repProps.getProperty(STATS_NODE_COUNT_PROPERTY, "0"));
         propsCount = Long.parseLong(repProps.getProperty(STATS_PROP_COUNT_PROPERTY, "0"));
 
-        // setup internal transaction manager
-        // @todo rewrite to use file system abstraction (FileSystem interface)
-        try {
-            File txRootDir = new File(repConfig.getHomeDir(), "tx");
-            txMgr = new TransactionManager(txRootDir);
-        } catch (IOException ioe) {
-            String msg = "failed to initialize internal transaction manager";
-            log.error(msg, ioe);
-            throw new RepositoryException(msg, ioe);
-        }
-
         // workspaces
         Iterator iter = repConfig.getWorkspaceConfigs().iterator();
         while (iter.hasNext()) {
@@ -280,14 +267,9 @@
         }
 
         // init version manager
-        // todo: improve configurability
-        XMLPersistenceManager pm = new XMLPersistenceManager();
-        try {
-            pm.init(versionStore, repConfig.getHomeDir()+"/versions");
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-        pvMgr = new NativePVM(pm, getNodeTypeRegistry());
+        // todo: as soon as dynamic workspaces are available, base on system ws
+        SessionImpl verSession = getSystemSession(repConfig.getDefaultWorkspaceName());
+        pvMgr = new NativePVM(verSession);
         vMgr = new VersionManagerImpl(pvMgr);
 
         // finally register shutdown hook
@@ -415,7 +397,7 @@
      *                             already exists or if another error occurs
      * @see SessionImpl#createWorkspace(String)
      */
-     synchronized void createWorkspace(String workspaceName) throws RepositoryException {
+    synchronized void createWorkspace(String workspaceName) throws RepositoryException {
         if (wspInfos.containsKey(workspaceName)) {
             throw new RepositoryException("workspace '" + workspaceName + "' already exists.");
         }
@@ -429,7 +411,7 @@
         initWorkspace(workspaceName);
     }
 
-    PersistentItemStateProvider getWorkspaceStateManager(String workspaceName)
+    SharedItemStateManager getWorkspaceStateManager(String workspaceName)
             throws NoSuchWorkspaceException, RepositoryException {
         // check state
         if (disposed) {
@@ -443,20 +425,6 @@
         return wspInfo.getItemStateProvider();
     }
 
-    ReferenceManager getWorkspaceReferenceManager(String workspaceName)
-            throws NoSuchWorkspaceException, RepositoryException {
-        // check state
-        if (disposed) {
-            throw new IllegalStateException("repository instance has been shut down");
-        }
-
-        WorkspaceInfo wspInfo = (WorkspaceInfo) wspInfos.get(workspaceName);
-        if (wspInfo == null) {
-            throw new NoSuchWorkspaceException(workspaceName);
-        }
-        return wspInfo.getReferenceManager();
-    }
-
     ObservationManagerFactory getObservationManagerFactory(String workspaceName)
             throws NoSuchWorkspaceException {
         // check state
@@ -674,13 +642,13 @@
         }
         if (credentials == null) {
             // anonymous login
-            SessionImpl ses = new XASessionImpl(this, ANONYMOUS_CREDENTIALS, wspInfo.getConfig(), txMgr);
+            SessionImpl ses = new XASessionImpl(this, ANONYMOUS_CREDENTIALS, wspInfo.getConfig());
             activeSessions.put(ses, ses);
             return ses;
         } else if (credentials instanceof SimpleCredentials) {
             // username/password credentials
             // @todo implement authentication/authorization
-            Session ses = new XASessionImpl(this, credentials, wspInfo.getConfig(), txMgr);
+            Session ses = new XASessionImpl(this, credentials, wspInfo.getConfig());
             activeSessions.put(ses, ses);
             return ses;
         } else {
@@ -764,12 +732,7 @@
         /**
          * item state provider
          */
-        private PersistentItemStateManager itemStateMgr;
-
-        /**
-         * reference manager
-         */
-        private ReferenceManager refMgr;
+        private SharedItemStateManager itemStateMgr;
 
         /**
          * system session
@@ -873,32 +836,17 @@
         }
 
         /**
-         * Returns the reference manager for this workspace
-         *
-         * @return the reference manager for this workspace
-         * @throws RepositoryException if the reference manager could not be created
-         */
-        synchronized ReferenceManager getReferenceManager()
-                throws RepositoryException {
-            if (refMgr == null) {
-                // create reference mgr that uses this workspace's perstistence mgr
-                refMgr = new ReferenceManager(getPersistenceManager());
-            }
-            return refMgr;
-        }
-
-        /**
          * Returns the workspace item state provider
          *
          * @return the workspace item state provider
          * @throws RepositoryException if the workspace item state provider could not be created
          */
-        synchronized PersistentItemStateProvider getItemStateProvider()
+        synchronized SharedItemStateManager getItemStateProvider()
                 throws RepositoryException {
             if (itemStateMgr == null) {
                 // create item state manager
                 try {
-                    itemStateMgr = new PersistentItemStateManager(getPersistenceManager(), rootNodeUUID, ntReg);
+                    itemStateMgr = new SharedItemStateManager(getPersistenceManager(), rootNodeUUID, ntReg);
                 } catch (ItemStateException ise) {
                     String msg = "failed to instantiate persistent item state manager";
                     log.error(msg, ise);
@@ -974,12 +922,6 @@
                     log.error("error while closing persistence manager of workspace " + config.getName(), e);
                 }
                 persistMgr = null;
-            }
-
-            // dispose reference manager
-            if (refMgr != null) {
-                //refMgr.dispose();
-                refMgr = null;
             }
 
             // close workspace file system

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	Sun Jan 23 09:11:20 2005
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core;
 
+import org.apache.commons.collections.BeanMap;
+import org.apache.jackrabbit.core.config.SearchConfig;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.observation.EventImpl;
@@ -23,20 +25,20 @@
 import org.apache.jackrabbit.core.search.QueryHandler;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.config.SearchConfig;
 import org.apache.log4j.Logger;
-import org.apache.commons.collections.BeanMap;
 
-import javax.jcr.RepositoryException;
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.NamespaceException;
 import javax.jcr.NamespaceRegistry;
-import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.query.Query;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.Event;
 import java.io.IOException;
-import java.util.*;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 /**
  * Acts as a global entry point to execute queries and index nodes.
@@ -50,15 +52,21 @@
  */
 public class SearchManager implements SynchronousEventListener {
 
-    /** Logger instance for this class */
+    /**
+     * Logger instance for this class
+     */
     private static final Logger log = Logger.getLogger(SearchManager.class);
 
-    /** Namespace URI for xpath functions */
+    /**
+     * Namespace URI for xpath functions
+     */
     // @todo this is not final! What should we use?
     private static final String NS_FN_PREFIX = "fn";
     public static final String NS_FN_URI = "http://www.w3.org/2004/10/xpath-functions";
 
-    /** Namespace URI for XML schema */
+    /**
+     * Namespace URI for XML schema
+     */
     private static final String NS_XS_PREFIX = "xs";
     public static final String NS_XS_URI = "http://www.w3.org/2001/XMLSchema";
 
@@ -67,16 +75,24 @@
     private static final String NS_JCRFN_PREFIX = "jcrfn";
     public static final String NS_JCRFN_URI = "http://www.jcp.org/jcr/xpath-functions/1.0";
 
-    /** HierarchyManager for path resolution */
+    /**
+     * HierarchyManager for path resolution
+     */
     private final HierarchyManager hmgr;
 
-    /** Session for accessing Nodes */
+    /**
+     * Session for accessing Nodes
+     */
     private final SessionImpl session;
 
-    /** Storage for search index */
+    /**
+     * Storage for search index
+     */
     private final FileSystem fs;
 
-    /** QueryHandler where query execution is delegated to */
+    /**
+     * QueryHandler where query execution is delegated to
+     */
     private final QueryHandler handler;
 
     public SearchManager(SessionImpl session, SearchConfig config)
@@ -126,10 +142,11 @@
 
     /**
      * Adds a <code>Node</code> to the search index.
+     *
      * @param node the NodeState to add.
      * @param path the path of the node.
      * @throws RepositoryException if an error occurs while indexing the node.
-     * @throws IOException if an error occurs while adding the node to the index.
+     * @throws IOException         if an error occurs while adding the node to the index.
      */
     public void addNode(NodeState node, Path path)
             throws RepositoryException, IOException {
@@ -141,6 +158,7 @@
 
     /**
      * Deletes the Node with <code>UUID</code> from the search index.
+     *
      * @param path the path of the node to delete.
      * @param uuid the <code>UUID</code> of the node to delete.
      * @throws IOException if an error occurs while deleting the node.
@@ -154,8 +172,7 @@
 
     /**
      * Closes this <code>SearchManager</code> and also closes the
-     * {@link org.apache.jackrabbit.core.fs.FileSystem} configured in
-     * {@link org.apache.jackrabbit.core.config.SearchConfig}.
+     * {@link FileSystem} configured in {@link SearchConfig}.
      */
     public void close() {
         try {
@@ -171,16 +188,15 @@
     /**
      * Creates a query object that can be executed on the workspace.
      *
-     * @param session the session of the user executing the query.
-     * @param itemMgr the item manager of the user executing the query. Needed
-     *   to return <code>Node</code> instances in the result set.
+     * @param session   the session of the user executing the query.
+     * @param itemMgr   the item manager of the user executing the query. Needed
+     *                  to return <code>Node</code> instances in the result set.
      * @param statement the actual query statement.
-     * @param language the syntax of the query statement.
+     * @param language  the syntax of the query statement.
      * @return a <code>Query</code> instance to execute.
-     *
      * @throws InvalidQueryException if the query is malformed or the
-     *   <code>language</code> is unknown.
-     * @throws RepositoryException if any other error occurs.
+     *                               <code>language</code> is unknown.
+     * @throws RepositoryException   if any other error occurs.
      */
     public Query createQuery(SessionImpl session,
                              ItemManager itemMgr,
@@ -189,20 +205,19 @@
             throws InvalidQueryException, RepositoryException {
         return handler.createQuery(session, itemMgr, statement, language);
     }
-    
+
     /**
      * Creates a query object from a node that can be executed on the workspace.
      *
      * @param session the session of the user executing the query.
      * @param itemMgr the item manager of the user executing the query. Needed
-     *   to return <code>Node</code> instances in the result set.
+     *                to return <code>Node</code> instances in the result set.
      * @param absPath absolute path to a node of type nt:query.
      * @return a <code>Query</code> instance to execute.
-     *
      * @throws InvalidQueryException if <code>absPath</code> is not a valid
-     *   persisted query (that is, a node of type nt:query)
+     *                               persisted query (that is, a node of type nt:query)
      * @throws ItemNotFoundException if there is no node at <code>absPath</code>.
-     * @throws RepositoryException if any other error occurs.
+     * @throws RepositoryException   if any other error occurs.
      */
     public Query createQuery(SessionImpl session,
                              ItemManager itemMgr,

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java	Sun Jan 23 09:11:20 2005
@@ -21,7 +21,7 @@
 import org.apache.jackrabbit.core.nodetype.*;
 import org.apache.jackrabbit.core.observation.EventStateCollection;
 import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.SessionItemStateManager;
 import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.xml.ImportHandler;
@@ -154,8 +154,8 @@
         ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
         String wspName = wspConfig.getName();
         wsp = new WorkspaceImpl(wspConfig, rep.getWorkspaceStateManager(wspName),
-                rep.getWorkspaceReferenceManager(wspName), rep, this);
-        itemStateMgr = createSessionItemStateManager(wsp.getPersistentStateManager());
+                rep, this);
+        itemStateMgr = createSessionItemStateManager(wsp.getItemStateManager());
         hierMgr = itemStateMgr.getHierarchyMgr();
         itemMgr = createItemManager(itemStateMgr, hierMgr);
         accessMgr = createAccessManager(credentials, hierMgr);
@@ -187,8 +187,8 @@
         ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
         String wspName = wspConfig.getName();
         wsp = new WorkspaceImpl(wspConfig, rep.getWorkspaceStateManager(wspName),
-                rep.getWorkspaceReferenceManager(wspName), rep, this);
-        itemStateMgr = new SessionItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
+                rep, this);
+        itemStateMgr = createSessionItemStateManager(wsp.getItemStateManager());
         hierMgr = itemStateMgr.getHierarchyMgr();
         itemMgr = createItemManager(itemStateMgr, hierMgr);
         versionMgr = rep.getVersionManager();
@@ -208,8 +208,9 @@
      *
      * @return session item state manager
      */
-    protected SessionItemStateManager createSessionItemStateManager(PersistentItemStateProvider provider) {
-        return new SessionItemStateManager(rep.getRootNodeUUID(), provider, getNamespaceResolver());
+    protected SessionItemStateManager createSessionItemStateManager(ItemStateManager manager) {
+        return new SessionItemStateManager(rep.getRootNodeUUID(),
+                manager, getNamespaceResolver());
     }
 
     /**
@@ -318,10 +319,12 @@
      * @param ps
      * @throws RepositoryException
      */
-    void dump(PrintStream ps) throws RepositoryException {
+    public void dump(PrintStream ps) throws RepositoryException {
         ps.println("Session: " + (userId == null ? "unknown" : userId) + " (" + this + ")");
         ps.println();
-        getItemManager().dump(ps);
+        itemMgr.dump(ps);
+        ps.println();
+        itemStateMgr.dump(ps);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	Sun Jan 23 09:11:20 2005
@@ -23,12 +23,15 @@
 import org.apache.log4j.PropertyConfigurator;
 
 import javax.jcr.*;
+import javax.jcr.xa.XASession;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeIterator;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.util.TraversingItemVisitor;
 import javax.naming.Context;
 import javax.naming.InitialContext;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
 import java.io.*;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -64,75 +67,16 @@
         RegistryHelper.registerRepository(ctx, "repo", configFile, repHomeDir, true);
         Repository r = (Repository) ctx.lookup("repo");
         Session session = r.login(new SimpleCredentials("anonymous", "".toCharArray()), null);
-/*
-        XASession session = (XASession) r.login(new SimpleCredentials("anonymous", "".toCharArray()), null);
-        XAResource xares = session.getXAResource();
-
-        Xid xid = new Xid() {
-            public byte[] getBranchQualifier() {
-                return new byte[0];
-            }
-
-            public int getFormatId() {
-                return 0;
-            }
-
-            public byte[] getGlobalTransactionId() {
-                return new byte[0];
-            }
-        };
-
-        xares.start(xid, XAResource.TMNOFLAGS);
-
-        // ....
-
-        xares.end(xid, XAResource.TMSUCCESS);
 
-        xares.prepare(xid);
-        xares.commit(xid, false);
-*/
         Workspace wsp = session.getWorkspace();
 
-        NodeTypeManager ntMgr = wsp.getNodeTypeManager();
-        NodeTypeIterator ntIter = ntMgr.getAllNodeTypes();
-        while (ntIter.hasNext()) {
-            NodeType nt = ntIter.nextNodeType();
-            System.out.println("built-in nodetype: " + nt.getName());
-        }
-
-        System.out.println();
-        ((NodeTypeManagerImpl) ntMgr).dump(System.out);
-        System.out.println();
-
         Node root = session.getRootNode();
-/*
-	String svExportFilePath = "d:/temp/sv_export0.xml";
-	String dvExportFilePath = "d:/temp/dv_export0.xml";
-	String importTargetName = "sandbox";
-
-	//wsp.exportSysView("/", new FileOutputStream(svExportFilePath), true, false);
-	//wsp.exportDocView("/", new FileOutputStream(dvExportFilePath), true, false);
-	if (!root.hasNode(importTargetName)) {
-	    root.addNode(importTargetName, "nt:unstructured");
-	}
-	//FileInputStream fin = new FileInputStream(svExportFilePath);
-        FileInputStream fin = new FileInputStream("d:/temp/test.xml");
-	session.importXML("/" + importTargetName, fin);
-	session.save();
-*/
-        String ntName = root.getProperty("jcr:primaryType").getString();
-        session.setNamespacePrefix("bla", "http://www.jcp.org/jcr/nt/1.0");
-        ntName = root.getProperty("jcr:primaryType").getString();
-        session.setNamespacePrefix("nt", "http://www.jcp.org/jcr/nt/1.0");
 
         System.out.println("initial...");
         System.out.println();
         dumpTree(root, System.out);
-
-        System.out.println("after move...");
-        System.out.println();
-        dumpTree(root, System.out);
-
+        ((SessionImpl)session).dump(System.out);
+/*
         if (root.canAddMixin("mix:versionable")) {
             root.addMixin("mix:versionable");
             if (root.canAddMixin("mix:accessControllable")) {
@@ -141,18 +85,36 @@
             dumpTree(root, System.out);
             boolean accessControllable = root.isNodeType("mix:accessControllable");
             root.removeMixin("mix:versionable");
-            dumpTree(root, System.out);
             root.save();
         }
-
+*/
         //root.setProperty("blob", new FileInputStream(new File("d:/temp/jackrabbit.zip")));
 
         if (root.hasProperty("blah")) {
+            Property p = root.getProperty("blah");
             root.getProperty("blah").remove();
+            System.out.println("before save()...");
+            System.out.println();
+            dumpTree(root, System.out);
+            ((SessionImpl)session).dump(System.out);
+            root.save();
+            System.out.println("after save()...");
+            System.out.println();
+            dumpTree(root, System.out);
+            ((SessionImpl)session).dump(System.out);
+            if (root.hasProperty("blah")) {
+                p = root.getProperty("blah");
+            }
         }
-        root.setProperty("blah", 1);
+
+        Property p1 = root.setProperty("blah", 1);
         root.setProperty("blah", 1.4);
         root.setProperty("blah", "blahblah");
+
+//        root.save();
+//        if (true) return;
+
+/*
         Node file = root.addNode("blu", "nt:file");
         file.addNode("jcr:content", "nt:unstructured");
         root.addNode("blu", "nt:folder");
@@ -171,9 +133,15 @@
         System.out.println("before save()...");
         System.out.println();
         dumpTree(root, System.out);
-
+        ((SessionImpl)session).dump(System.out);
+*/
         root.save();
 
+        System.out.println("after save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+
         if (root.hasProperty("blah")) {
             root.setProperty("blah", (String) null);
         }
@@ -187,11 +155,7 @@
             }
             System.out.println(list);
         }
-
-        System.out.println("after save()...");
-        System.out.println();
-        dumpTree(root, System.out);
-
+/*
         if (root.hasProperty("blob")) {
             Property blob = root.getProperty("blob");
             InputStream in = blob.getStream();
@@ -212,18 +176,47 @@
         Node misc = root.addNode("misc", "nt:unstructured");
         misc.addMixin("mix:referenceable");
         Property link = misc.setProperty("link", PathValue.valueOf("../blu[2]"));
+*/
+        System.out.println("before save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+
         root.save();
+
+        System.out.println("after save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+/*
         Node linkTarget = link.getParent().getNode(link.getValue().getString());
         System.out.println(link.getPath() + " refers to " + linkTarget.getPath());
 
         root.setProperty("ref", new ReferenceValue(misc));
+*/
+        boolean mult = root.getProperty("blah").getDefinition().isMultiple();
+
+        System.out.println("before save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+
         root.save();
+
+        mult = root.getProperty("blah").getDefinition().isMultiple();
+
+        System.out.println("after save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+/*
         PropertyIterator pi = misc.getReferences();
         while (pi.hasNext()) {
             Property prop = pi.nextProperty();
             Node target = prop.getNode();
             System.out.println(prop.getPath() + " is a reference to " + target.getPath());
         }
+*/
 /*
 	misc.remove();
 	try {
@@ -233,6 +226,7 @@
 	    root.save();
 	}
 */
+/*
         root.setProperty("date", DateValue.valueOf("2003-07-28T06:18:57.848+01:00"));
         Property p = root.getProperty("date");
         Value val = p.getValue();
@@ -245,7 +239,7 @@
             imported = root.getNode("imported");
         }
 
-        importNode(new File("d:/dev/jackrabbit/src/test"), imported);
+        //importNode(new File("d:/dev/jackrabbit/src/test"), imported);
 
         if (root.hasNode("foo")) {
             root.getNode("foo").remove();
@@ -260,15 +254,22 @@
         System.out.println("before save()...");
         System.out.println();
         dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
 
         root.save();
 
+        System.out.println("after save()...");
+        System.out.println();
+        dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
+
         session.getWorkspace().copy("/imported", "/misc/blah");
         session.getWorkspace().move("/misc/blah", "/misc/blahblah");
 
-        System.out.println("after save()...");
+        System.out.println("after Workspace.copy/move()...");
         System.out.println();
         dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
 
         prop1.remove();
 
@@ -278,12 +279,14 @@
         System.out.println("before refresh()...");
         System.out.println();
         dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
 
         root.refresh(false);
 
         System.out.println("after refresh()...");
         System.out.println();
         dumpTree(root, System.out);
+        ((SessionImpl)session).dump(System.out);
 
         System.out.println("exiting...");
         System.out.println();
@@ -295,7 +298,7 @@
         repProps = r.getProperties();
         System.out.println("repository properties:");
         System.out.println(repProps);
-
+*/
         //((RepositoryImpl) r).shutdown();
     }
 
@@ -323,7 +326,8 @@
                 while (i-- > 0) {
                     System.out.print('\t');
                 }
-                ps.println("[node] " + node.getName());
+                String status = node.isModified() ? "*" : (node.isNew() ? "+" : " ");
+                ps.println("[node] " + status + " " + node.getName());
 
                 super.entering(node, i);
             }
@@ -354,7 +358,8 @@
                         sb.append(val.getString());
                     }
                 }
-                ps.println("[prop] " + property.getName() + " " + sb.toString());
+                String status = property.isModified() ? "*" : (property.isNew() ? "+" : " ");
+                ps.println("[prop] " + status + " " + property.getName() + " " + sb.toString());
 
                 super.entering(property, i);
             }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java	Sun Jan 23 09:11:20 2005
@@ -65,13 +65,7 @@
      * The persistent state mgr associated with the workspace represented by <i>this</i>
      * <code>Workspace</code> instance.
      */
-    protected final PersistentItemStateProvider persistentStateMgr;
-
-    /**
-     * The reference mgr associated with the workspace represented by <i>this</i>
-     * <code>Workspace</code> instance.
-     */
-    protected final ReferenceManager refMgr;
+    protected final LocalItemStateManager stateMgr;
 
     /**
      * The hierarchy mgr that reflects persistent state only
@@ -99,17 +93,17 @@
      * Package private constructor.
      *
      * @param wspConfig
-     * @param persistentStateMgr
+     * @param stateMgr
      * @param rep
      * @param session
      */
-    WorkspaceImpl(WorkspaceConfig wspConfig, PersistentItemStateProvider persistentStateMgr,
-                  ReferenceManager refMgr, RepositoryImpl rep, SessionImpl session) {
+    WorkspaceImpl(WorkspaceConfig wspConfig, SharedItemStateManager stateMgr,
+                  RepositoryImpl rep, SessionImpl session) {
         this.wspConfig = wspConfig;
         this.rep = rep;
-        this.persistentStateMgr = persistentStateMgr;
-        this.refMgr = refMgr;
-        hierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), persistentStateMgr, session.getNamespaceResolver());
+        this.stateMgr = new LocalItemStateManager(stateMgr);
+        this.hierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(),
+                this.stateMgr, session.getNamespaceResolver());
         this.session = session;
     }
 
@@ -117,12 +111,8 @@
         return rep;
     }
 
-    public PersistentItemStateProvider getPersistentStateManager() {
-        return persistentStateMgr;
-    }
-
-    ReferenceManager getReferenceManager() {
-        return refMgr;
+    public LocalItemStateManager getItemStateManager() {
+        return stateMgr;
     }
 
     /**
@@ -175,10 +165,10 @@
      * @throws PathNotFoundException
      * @throws RepositoryException
      */
-    protected static PersistentNodeState getNodeState(String nodePath,
-                                                      NamespaceResolver nsResolver,
-                                                      HierarchyManagerImpl hierMgr,
-                                                      PersistentItemStateProvider stateMgr)
+    protected static NodeState getNodeState(String nodePath,
+                                            NamespaceResolver nsResolver,
+                                            HierarchyManagerImpl hierMgr,
+                                            ItemStateManager stateMgr)
             throws PathNotFoundException, RepositoryException {
         try {
             return getNodeState(Path.create(nodePath, nsResolver, true), hierMgr, stateMgr);
@@ -198,10 +188,10 @@
      * @throws PathNotFoundException
      * @throws RepositoryException
      */
-    protected static PersistentNodeState getParentNodeState(String path,
-                                                            NamespaceResolver nsResolver,
-                                                            HierarchyManagerImpl hierMgr,
-                                                            PersistentItemStateProvider stateMgr)
+    protected static NodeState getParentNodeState(String path,
+                                                  NamespaceResolver nsResolver,
+                                                  HierarchyManagerImpl hierMgr,
+                                                  ItemStateManager stateMgr)
 
             throws PathNotFoundException, RepositoryException {
         try {
@@ -221,9 +211,9 @@
      * @throws PathNotFoundException
      * @throws RepositoryException
      */
-    protected static PersistentNodeState getNodeState(Path nodePath,
-                                                      HierarchyManagerImpl hierMgr,
-                                                      PersistentItemStateProvider stateMgr)
+    protected static NodeState getNodeState(Path nodePath,
+                                            HierarchyManagerImpl hierMgr,
+                                            ItemStateManager stateMgr)
             throws PathNotFoundException, RepositoryException {
         try {
             ItemId id = hierMgr.resolvePath(nodePath);
@@ -247,10 +237,10 @@
      * @throws NoSuchItemStateException
      * @throws ItemStateException
      */
-    protected static PersistentNodeState getNodeState(NodeId id,
-                                                      PersistentItemStateProvider stateMgr)
+    protected static NodeState getNodeState(NodeId id,
+                                            ItemStateManager stateMgr)
             throws NoSuchItemStateException, ItemStateException {
-        return (PersistentNodeState) stateMgr.getItemState(id);
+        return (NodeState) stateMgr.getItemState(id);
     }
 
     /**
@@ -270,12 +260,12 @@
                                        NodeTypeRegistry ntReg,
                                        AccessManagerImpl accessMgr,
                                        HierarchyManagerImpl hierMgr,
-                                       PersistentItemStateProvider stateMgr)
+                                       ItemStateManager stateMgr)
             throws ConstraintViolationException, AccessDeniedException,
             PathNotFoundException, ItemExistsException, RepositoryException {
 
         Path parentPath = nodePath.getAncestor(1);
-        PersistentNodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
+        NodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
 
         // 1. check path & access rights
 
@@ -348,13 +338,13 @@
                                           NodeTypeRegistry ntReg,
                                           AccessManagerImpl accessMgr,
                                           HierarchyManagerImpl hierMgr,
-                                          PersistentItemStateProvider stateMgr)
+                                          ItemStateManager stateMgr)
             throws ConstraintViolationException, AccessDeniedException,
             PathNotFoundException, RepositoryException {
 
-        PersistentNodeState targetState = getNodeState(nodePath, hierMgr, stateMgr);
+        NodeState targetState = getNodeState(nodePath, hierMgr, stateMgr);
         Path parentPath = nodePath.getAncestor(1);
-        PersistentNodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
+        NodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
 
         // 1. check path & access rights
 
@@ -402,7 +392,7 @@
             throws RepositoryException {
         // build effective node type of mixins & primary type:
         // existing mixin's
-        HashSet set = new HashSet(((NodeState) state).getMixinTypeNames());
+        HashSet set = new HashSet((state).getMixinTypeNames());
         // primary type
         set.add(state.getNodeTypeName());
         try {
@@ -437,15 +427,17 @@
         return entParent.getApplicableChildNodeDef(name, nodeTypeName);
     }
 
-    private static PersistentNodeState copyNodeState(NodeState srcState,
-                                                     String parentUUID,
-                                                     NodeTypeRegistry ntReg,
-                                                     HierarchyManagerImpl srcHierMgr,
-                                                     PersistentItemStateProvider srcStateMgr,
-                                                     PersistentItemStateProvider destStateMgr,
-                                                     boolean clone)
+    private static NodeState copyNodeState(NodeState srcState,
+                                           String parentUUID,
+                                           NodeTypeRegistry ntReg,
+                                           HierarchyManagerImpl srcHierMgr,
+                                           ItemStateManager srcStateMgr,
+                                           ItemStateManager destStateMgr,
+                                           boolean clone,
+                                           UpdateOperation update)
             throws RepositoryException {
-        PersistentNodeState newState;
+
+        NodeState newState;
         try {
             String uuid;
             if (clone) {
@@ -453,7 +445,7 @@
             } else {
                 uuid = UUID.randomUUID().toString();	// create new version 4 uuid
             }
-            newState = destStateMgr.createNodeState(uuid, srcState.getNodeTypeName(), parentUUID);
+            newState = update.createNew(uuid, srcState.getNodeTypeName(), parentUUID);
             // copy node state
             // @todo special handling required for nodes with special semantics (e.g. those defined by mix:versionable, et.al.)
             // FIXME delegate to 'node type instance handler'
@@ -465,10 +457,10 @@
                 NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
                 NodeState srcChildState = (NodeState) srcStateMgr.getItemState(new NodeId(entry.getUUID()));
                 // recursive copying of child node
-                PersistentNodeState newChildState = copyNodeState(srcChildState, uuid,
-                        ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone);
+                NodeState newChildState = copyNodeState(srcChildState, uuid,
+                        ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone, update);
                 // persist new child node
-                newChildState.store();
+                update.store(newChildState);
                 // add new child node entry to new node
                 newState.addChildNodeEntry(entry.getName(), newChildState.getUUID());
             }
@@ -477,10 +469,10 @@
             while (iter.hasNext()) {
                 NodeState.PropertyEntry entry = (NodeState.PropertyEntry) iter.next();
                 PropertyState srcChildState = (PropertyState) srcStateMgr.getItemState(new PropertyId(srcState.getUUID(), entry.getName()));
-                PersistentPropertyState newChildState = copyPropertyState(srcChildState, uuid, entry.getName(),
-                        ntReg, srcHierMgr, srcStateMgr, destStateMgr);
+                PropertyState newChildState = copyPropertyState(srcChildState, uuid, entry.getName(),
+                        ntReg, srcHierMgr, srcStateMgr, destStateMgr, update);
                 // persist new property
-                newChildState.store();
+                update.store(newChildState);
                 // add new property entry to new node
                 newState.addPropertyEntry(entry.getName());
             }
@@ -492,53 +484,48 @@
         }
     }
 
-    private static PersistentPropertyState copyPropertyState(PropertyState srcState,
-                                                             String parentUUID,
-                                                             QName propName,
-                                                             NodeTypeRegistry ntReg,
-                                                             HierarchyManagerImpl srcHierMgr,
-                                                             PersistentItemStateProvider srcStateMgr,
-                                                             PersistentItemStateProvider destStateMgr)
+    private static PropertyState copyPropertyState(PropertyState srcState,
+                                                   String parentUUID,
+                                                   QName propName,
+                                                   NodeTypeRegistry ntReg,
+                                                   HierarchyManagerImpl srcHierMgr,
+                                                   ItemStateManager srcStateMgr,
+                                                   ItemStateManager destStateMgr,
+                                                   UpdateOperation update)
             throws RepositoryException {
+
         // @todo special handling required for properties with special semantics (e.g. those defined by mix:versionable, mix:lockable, et.al.)
-        PersistentPropertyState newState;
-        try {
-            newState = destStateMgr.createPropertyState(parentUUID, propName);
-            PropDefId defId = srcState.getDefinitionId();
-            newState.setDefinitionId(defId);
-            newState.setType(srcState.getType());
-            newState.setMultiValued(srcState.isMultiValued());
-            InternalValue[] values = srcState.getValues();
-            if (values != null) {
-                InternalValue[] newValues = new InternalValue[values.length];
-                for (int i = 0; i < values.length; i++) {
-                    newValues[i] = values[i] != null ? values[i].createCopy() : null;
-                }
-                newState.setValues(values);
-                // FIXME delegate to 'node type instance handler'
-                if (defId != null) {
-                    PropDef def = ntReg.getPropDef(defId);
-                    if (def.getDeclaringNodeType().equals(NodeTypeRegistry.MIX_REFERENCEABLE)) {
-                        if (propName.equals(ItemImpl.PROPNAME_UUID)) {
-                            // set correct value of jcr:uuid property
-                            newState.setValues(new InternalValue[]{InternalValue.create(parentUUID)});
-                        }
+        PropertyState newState = update.createNew(propName, parentUUID);
+        PropDefId defId = srcState.getDefinitionId();
+        newState.setDefinitionId(defId);
+        newState.setType(srcState.getType());
+        newState.setMultiValued(srcState.isMultiValued());
+        InternalValue[] values = srcState.getValues();
+        if (values != null) {
+            InternalValue[] newValues = new InternalValue[values.length];
+            for (int i = 0; i < values.length; i++) {
+                newValues[i] = values[i] != null ? values[i].createCopy() : null;
+            }
+            newState.setValues(values);
+            // FIXME delegate to 'node type instance handler'
+            if (defId != null) {
+                PropDef def = ntReg.getPropDef(defId);
+                if (def.getDeclaringNodeType().equals(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+                    if (propName.equals(ItemImpl.PROPNAME_UUID)) {
+                        // set correct value of jcr:uuid property
+                        newState.setValues(new InternalValue[]{InternalValue.create(parentUUID)});
                     }
                 }
             }
-            return newState;
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to copy state of " + srcHierMgr.safeGetJCRPath(srcState.getId());
-            log.error(msg, ise);
-            throw new RepositoryException(msg, ise);
         }
+        return newState;
     }
 
     private static void internalCopy(String srcAbsPath,
-                                     PersistentItemStateProvider srcStateMgr,
+                                     ItemStateManager srcStateMgr,
                                      HierarchyManagerImpl srcHierMgr,
                                      String destAbsPath,
-                                     PersistentItemStateProvider destStateMgr,
+                                     ItemStateManager destStateMgr,
                                      HierarchyManagerImpl destHierMgr,
                                      AccessManagerImpl accessMgr,
                                      NamespaceResolver nsResolver,
@@ -550,7 +537,7 @@
         // 1. check paths & retrieve state
 
         Path srcPath;
-        PersistentNodeState srcState;
+        NodeState srcState;
         try {
             srcPath = Path.create(srcAbsPath, nsResolver, true);
             srcState = getNodeState(srcPath, srcHierMgr, srcStateMgr);
@@ -563,7 +550,7 @@
         Path destPath;
         Path.PathElement destName;
         Path destParentPath;
-        PersistentNodeState destParentState;
+        NodeState destParentState;
         try {
             destPath = Path.create(destAbsPath, nsResolver, true);
             destName = destPath.getNameElement();
@@ -596,62 +583,28 @@
         }
         // check node type constraints
         checkAddNode(destPath, srcState.getNodeTypeName(), ntReg, accessMgr, destHierMgr, destStateMgr);
-/*
-	// check if target node needs to be inserted at specific location in child node entries list
-	boolean insertTargetEntry = false;
-	int ind = destName.getIndex();
-	if (ind > 0) {
-	    // target name contains subscript:
-	    // validate subscript
-	    List sameNameSibs = destParentState.getChildNodeEntries(destName.getName());
-	    if (ind > sameNameSibs.size() + 1) {
-		String msg = "invalid subscript in name: " + destAbsPath;
-		log.error(msg);
-		throw new RepositoryException(msg);
-	    }
-	    insertTargetEntry = (ind < sameNameSibs.size() + 1) ? true : false;
-	}
-	if (insertTargetEntry) {
-	    // check hasOrderableChildNodes flag
-	    if (!ntReg.getNodeTypeDef(destParentState.getNodeTypeName()).hasOrderableChildNodes()) {
-		throw new ConstraintViolationException(destAbsPath + ": parent node's node type does not allow explicit ordering of child nodes");
-	    }
-	}
-*/
+
         // 3. do copy operation (modify and persist affected states)
+        try {
+            UpdateOperation update = destStateMgr.beginUpdate();
 
-        // create deep copy of source node state
-        PersistentNodeState newState = copyNodeState(srcState, destParentState.getUUID(),
-                ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone);
-
-        // add to new parent
-        destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
-/*
-	if (!insertTargetEntry) {
-	    // append target entry
-	    destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
-	} else {
-	    // insert target entry at specified position
-	    Iterator iter = new ArrayList(destParentState.getChildNodeEntries()).iterator();
-	    destParentState.removeAllChildNodeEntries();
-	    while (iter.hasNext()) {
-		NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
-		if (entry.getName().equals(destName.getName()) &&
-			entry.getIndex() == destName.getIndex()) {
-		    destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
-		}
-		destParentState.addChildNodeEntry(entry.getName(), entry.getUUID());
-	    }
-	}
-*/
-        // change definition (id) of new node
-        ChildNodeDef newNodeDef = findApplicableDefinition(destName.getName(), srcState.getNodeTypeName(), destParentState, ntReg);
-        newState.setDefinitionId(new NodeDefId(newNodeDef));
+            // create deep copy of source node state
+            NodeState newState = copyNodeState(srcState, destParentState.getUUID(),
+                    ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone, update);
 
-        // persist states
-        try {
-            newState.store();
-            destParentState.store();
+            // add to new parent
+            destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
+
+            // change definition (id) of new node
+            ChildNodeDef newNodeDef = findApplicableDefinition(destName.getName(), srcState.getNodeTypeName(), destParentState, ntReg);
+            newState.setDefinitionId(new NodeDefId(newNodeDef));
+
+            // persist states
+            update.store(newState);
+            update.store(destParentState);
+
+            // finish update operations
+            update.end();
         } catch (ItemStateException ise) {
             String msg = "internal error: failed to persist state of " + destAbsPath;
             log.error(msg, ise);
@@ -697,12 +650,12 @@
             ItemExistsException, RepositoryException {
         // clone (i.e. pull) subtree at srcAbsPath from srcWorkspace
         // to 'this' workspace at destAbsPath
-        PersistentItemStateProvider srcStateMgr = rep.getWorkspaceStateManager(srcWorkspace);
+        ItemStateManager srcStateMgr = rep.getWorkspaceStateManager(srcWorkspace);
         // FIXME need to setup a hierarchy manager for source workspace
         HierarchyManagerImpl srcHierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), srcStateMgr, session.getNamespaceResolver());
         // do cross-workspace copy
         internalCopy(srcAbsPath, srcStateMgr, srcHierMgr,
-                destAbsPath, persistentStateMgr, hierMgr,
+                destAbsPath, stateMgr, hierMgr,
                 session.getAccessManager(), session.getNamespaceResolver(),
                 rep.getNodeTypeRegistry(), true);
     }
@@ -714,8 +667,8 @@
             throws ConstraintViolationException, AccessDeniedException,
             PathNotFoundException, ItemExistsException, RepositoryException {
         // do intra-workspace copy
-        internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
-                destAbsPath, persistentStateMgr, hierMgr,
+        internalCopy(srcAbsPath, stateMgr, hierMgr,
+                destAbsPath, stateMgr, hierMgr,
                 session.getAccessManager(), session.getNamespaceResolver(),
                 rep.getNodeTypeRegistry(), false);
     }
@@ -729,12 +682,12 @@
             RepositoryException {
         // copy (i.e. pull) subtree at srcAbsPath from srcWorkspace
         // to 'this' workspace at destAbsPath
-        PersistentItemStateProvider srcStateMgr = rep.getWorkspaceStateManager(srcWorkspace);
+        ItemStateManager srcStateMgr = rep.getWorkspaceStateManager(srcWorkspace);
         // FIXME need to setup a hierarchy manager for source workspace
         HierarchyManagerImpl srcHierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), srcStateMgr, session.getNamespaceResolver());
         // do cross-workspace copy
         internalCopy(srcAbsPath, srcStateMgr, srcHierMgr,
-                destAbsPath, persistentStateMgr, hierMgr,
+                destAbsPath, stateMgr, hierMgr,
                 session.getAccessManager(), session.getNamespaceResolver(),
                 rep.getNodeTypeRegistry(), false);
     }
@@ -749,18 +702,18 @@
         // intra-workspace move...
 
         // 1. check paths & retrieve state
-
         Path srcPath;
         Path.PathElement srcName;
         Path srcParentPath;
-        PersistentNodeState targetState;
-        PersistentNodeState srcParentState;
+        NodeState targetState;
+        NodeState srcParentState;
+
         try {
             srcPath = Path.create(srcAbsPath, session.getNamespaceResolver(), true);
             srcName = srcPath.getNameElement();
             srcParentPath = srcPath.getAncestor(1);
-            targetState = getNodeState(srcPath, hierMgr, persistentStateMgr);
-            srcParentState = getNodeState(srcParentPath, hierMgr, persistentStateMgr);
+            targetState = getNodeState(srcPath, hierMgr, stateMgr);
+            srcParentState = getNodeState(srcParentPath, hierMgr, stateMgr);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + srcAbsPath;
             log.error(msg, mpe);
@@ -770,17 +723,19 @@
         Path destPath;
         Path.PathElement destName;
         Path destParentPath;
-        PersistentNodeState destParentState;
+        NodeState destParentState;
+
         try {
             destPath = Path.create(destAbsPath, session.getNamespaceResolver(), true);
             destName = destPath.getNameElement();
             destParentPath = destPath.getAncestor(1);
-            destParentState = getNodeState(destParentPath, hierMgr, persistentStateMgr);
+            destParentState = getNodeState(destParentPath, hierMgr, stateMgr);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + destAbsPath;
             log.error(msg, mpe);
             throw new RepositoryException(msg, mpe);
         }
+
         int ind = destName.getIndex();
         if (ind > 0) {
             // subscript in name element
@@ -791,88 +746,46 @@
 
         // 2. check node type constraints & access rights
 
-        checkRemoveNode(srcPath, rep.getNodeTypeRegistry(), session.getAccessManager(), hierMgr, persistentStateMgr);
+        checkRemoveNode(srcPath, rep.getNodeTypeRegistry(),
+                session.getAccessManager(), hierMgr, stateMgr);
         checkAddNode(destPath, targetState.getNodeTypeName(),
                 rep.getNodeTypeRegistry(), session.getAccessManager(),
-                hierMgr, persistentStateMgr);
-/*
-	// check if target node needs to be inserted at specific location in child node entries list
-	boolean insertTargetEntry = false;
-	int ind = destName.getIndex();
-	if (ind > 0) {
-	    // target name contains subscript:
-	    // validate subscript
-	    List sameNameSibs = destParentState.getChildNodeEntries(destName.getName());
-	    if (ind > sameNameSibs.size() + 1) {
-		String msg = "invalid subscript in name: " + destAbsPath;
-		log.error(msg);
-		throw new RepositoryException(msg);
-	    }
-	    insertTargetEntry = (ind < sameNameSibs.size() + 1) ? true : false;
-	}
-	if (insertTargetEntry) {
-	    // check hasOrderableChildNodes flag
-	    if (!rep.getNodeTypeRegistry().getNodeTypeDef(destParentState.getNodeTypeName()).hasOrderableChildNodes()) {
-		throw new ConstraintViolationException(destAbsPath + ": parent node's node type does not allow explicit ordering of child nodes");
-	    }
-	}
-*/
+                hierMgr, stateMgr);
+
         // 3. do move operation (modify and persist affected states)
+        try {
+            UpdateOperation update = stateMgr.beginUpdate();
+            boolean renameOnly = srcParentState.getUUID().equals(destParentState.getUUID());
 
-        boolean renameOnly = srcParentState.getUUID().equals(destParentState.getUUID());
+            // add to new parent
+            if (!renameOnly) {
+                targetState.addParentUUID(destParentState.getUUID());
+            }
+            destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
 
-        // add to new parent
-        if (!renameOnly) {
-            targetState.addParentUUID(destParentState.getUUID());
-        }
-        destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
-/*
-	if (!insertTargetEntry) {
-	    // append target entry
-	    destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
-	} else {
-	    // insert target entry at specified position
-	    Iterator iter = new ArrayList(destParentState.getChildNodeEntries()).iterator();
-	    destParentState.removeAllChildNodeEntries();
-	    while (iter.hasNext()) {
-		NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
-		if (entry.getName().equals(destName.getName()) &&
-			entry.getIndex() == destName.getIndex()) {
-		    destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
-		}
-		destParentState.addChildNodeEntry(entry.getName(), entry.getUUID());
-	    }
-	}
-*/
-        // change definition (id) of target node
-        ChildNodeDef newTargetDef = findApplicableDefinition(destName.getName(), targetState.getNodeTypeName(), destParentState, rep.getNodeTypeRegistry());
-        targetState.setDefinitionId(new NodeDefId(newTargetDef));
-
-        // remove from old parent
-        if (!renameOnly) {
-            targetState.removeParentUUID(srcParentState.getUUID());
-        }
-        int srcNameIndex = srcName.getIndex() == 0 ? 1 : srcName.getIndex();
-/*
-	// if the net result of the move is changing the position of a child node
-	// among its same-same siblings, the subscript of the child node entry
-	// to be removed might need adjustment
-	if (renameOnly && srcName.getName().equals(destName.getName()) &&
-		insertTargetEntry && destName.getIndex() <= srcNameIndex) {
-	    srcNameIndex++;
-	}
-*/
-        srcParentState.removeChildNodeEntry(srcName.getName(), srcNameIndex);
+            // change definition (id) of target node
+            ChildNodeDef newTargetDef = findApplicableDefinition(destName.getName(), targetState.getNodeTypeName(), destParentState, rep.getNodeTypeRegistry());
+            targetState.setDefinitionId(new NodeDefId(newTargetDef));
 
-        // persist states
-        try {
-            targetState.store();
+            // remove from old parent
+            if (!renameOnly) {
+                targetState.removeParentUUID(srcParentState.getUUID());
+            }
+
+            int srcNameIndex = srcName.getIndex() == 0 ? 1 : srcName.getIndex();
+            srcParentState.removeChildNodeEntry(srcName.getName(), srcNameIndex);
+
+            // persist states
+            update.store(targetState);
             if (renameOnly) {
-                srcParentState.store();
+                update.store(srcParentState);
             } else {
-                destParentState.store();
-                srcParentState.store();
+                update.store(destParentState);
+                update.store(srcParentState);
             }
+
+            // finish update
+            update.end();
         } catch (ItemStateException ise) {
             String msg = "internal error: failed to persist state of " + destAbsPath;
             log.error(msg, ise);
@@ -938,11 +851,11 @@
         // check path & retrieve state
         Path path;
         Path.PathElement name;
-        PersistentNodeState state;
+        NodeState state;
         try {
             path = Path.create(absPath, session.getNamespaceResolver(), true);
             name = path.getNameElement();
-            state = getNodeState(path, hierMgr, persistentStateMgr);
+            state = getNodeState(path, hierMgr, stateMgr);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + absPath;
             log.error(msg, mpe);
@@ -955,7 +868,7 @@
         }
 
         new DocViewSAXEventGenerator(state, name.getName(), noRecurse, binaryAsLink,
-                persistentStateMgr, (NamespaceRegistryImpl) rep.getNamespaceRegistry(),
+                stateMgr, rep.getNamespaceRegistry(),
                 session.getAccessManager(), hierMgr, contentHandler).serialize();
     }
 
@@ -981,11 +894,11 @@
         // check path & retrieve state
         Path path;
         Path.PathElement name;
-        PersistentNodeState state;
+        NodeState state;
         try {
             path = Path.create(absPath, session.getNamespaceResolver(), true);
             name = path.getNameElement();
-            state = getNodeState(path, hierMgr, persistentStateMgr);
+            state = getNodeState(path, hierMgr, stateMgr);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + absPath;
             log.error(msg, mpe);
@@ -998,7 +911,7 @@
         }
 
         new SysViewSAXEventGenerator(state, name.getName(), noRecurse, binaryAsLink,
-                persistentStateMgr, (NamespaceRegistryImpl) rep.getNamespaceRegistry(),
+                stateMgr, rep.getNamespaceRegistry(),
                 session.getAccessManager(), hierMgr, contentHandler).serialize();
     }
 

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/XASessionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/XASessionImpl.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/XASessionImpl.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.state.TransactionContext;
+import org.apache.jackrabbit.core.state.TransactionException;
+import org.apache.jackrabbit.core.state.TransactionListener;
+import org.apache.jackrabbit.core.config.WorkspaceConfig;
+import org.apache.jackrabbit.core.observation.EventStateCollection;
+import org.apache.log4j.Logger;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.xa.XASession;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Session extension that provides XA support.
+ */
+public class XASessionImpl extends SessionImpl
+        implements XASession, XAResource {
+
+    /**
+     * Logger instance
+     */
+    private static final Logger log = Logger.getLogger(XASessionImpl.class);
+
+    /**
+     * Global transactions
+     */
+    private static final Map txGlobal = new HashMap();
+
+    /**
+     * Currently associated transaction
+     */
+    private TransactionContext tx;
+
+    /**
+     * Transaction timeout, in seconds
+     */
+    private int txTimeout;
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param rep         repository
+     * @param credentials credentials
+     * @param wspConfig   workspace configuration
+     * @throws javax.jcr.RepositoryException if an error occurs
+     */
+    public XASessionImpl(RepositoryImpl rep, Credentials credentials,
+                         WorkspaceConfig wspConfig)
+            throws RepositoryException {
+
+        super(rep, credentials, wspConfig);
+    }
+
+    //-------------------------------------------------------------< XASession >
+
+    /**
+     * @see javax.jcr.xa.XASession#getXAResource
+     */
+    public XAResource getXAResource() {
+        return this;
+    }
+
+    //------------------------------------------------------------< XAResource >
+
+    /**
+     * @see javax.transaction.xa.XAResource#getTransactionTimeout
+     */
+    public int getTransactionTimeout() throws XAException {
+        return txTimeout;
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#setTransactionTimeout
+     */
+    public boolean setTransactionTimeout(int seconds) throws XAException {
+        txTimeout = seconds;
+        return true;
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#isSameRM
+     *      <p/>
+     *      Two resources belong to the same resource manager if both connections
+     *      (i.e. sessions) have the same credentials.
+     */
+    public boolean isSameRM(XAResource xares) throws XAException {
+        if (xares instanceof XASessionImpl) {
+            XASessionImpl xases = (XASessionImpl) xares;
+            return stringsEqual(userId, xases.userId);
+        }
+        return false;
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#start
+     *      <p/>
+     *      If <code>TMNOFLAGS</code> is specified, we create a new transaction
+     *      context and associate it with this resource.
+     *      If <code>TMJOIN</code> is specified, this resource should use the
+     *      same transaction context as another, already known transaction.
+     *      If <code>TMRESUME</code> is specified, we should resume work on
+     *      a transaction context that was suspended earlier.
+     *      All other flags generate an <code>XAException</code> of type
+     *      <code>XAER_INVAL</code>
+     */
+    public void start(Xid xid, int flags) throws XAException {
+        if (isAssociated()) {
+            log.error("Resource already associated with a transaction.");
+            throw new XAException(XAException.XAER_PROTO);
+        }
+
+        TransactionContext tx = null;
+        if (flags == TMNOFLAGS) {
+            tx = (TransactionContext) txGlobal.get(xid);
+            if (tx != null) {
+                throw new XAException(XAException.XAER_DUPID);
+            }
+            tx = createTransaction(xid);
+        } else if (flags == TMJOIN) {
+            tx = (TransactionContext) txGlobal.get(xid);
+            if (tx == null) {
+                throw new XAException(XAException.XAER_NOTA);
+            }
+        } else if (flags == TMRESUME) {
+            tx = (TransactionContext) txGlobal.get(xid);
+            if (tx == null) {
+                throw new XAException(XAException.XAER_NOTA);
+            }
+        } else {
+            throw new XAException(XAException.XAER_INVAL);
+        }
+
+        associate(tx);
+    }
+
+    /**
+     * Create a global transaction.
+     *
+     * @param xid xid of global transaction.
+     * @return transaction
+     */
+    private TransactionContext createTransaction(Xid xid) {
+        TransactionContext tx = new TransactionContext();
+        txGlobal.put(xid, tx);
+        return tx;
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#end
+     *      <p/>
+     *      If <code>TMSUCCESS</code> is specified, we disassociate this session
+     *      from the transaction specified.
+     *      If <code>TMFAIL</code> is specified, we disassociate this session from
+     *      the transaction specified and mark the transaction rollback only.
+     *      If <code>TMSUSPEND</code> is specified, we disassociate this session
+     *      from the transaction specified.
+     *      All other flags generate an <code>XAException</code> of type
+     *      <code>XAER_INVAL</code>
+     */
+    public void end(Xid xid, int flags) throws XAException {
+        if (!isAssociated()) {
+            log.error("Resource not associated with a transaction.");
+            throw new XAException(XAException.XAER_PROTO);
+        }
+
+        TransactionContext tx = (TransactionContext) txGlobal.get(xid);
+        if (tx == null) {
+            throw new XAException(XAException.XAER_NOTA);
+        }
+        if (flags == TMSUCCESS) {
+            disassociate();
+        } else if (flags == TMFAIL) {
+            disassociate();
+            tx.setRollbackOnly();
+        } else if (flags == TMSUSPEND) {
+            disassociate();
+        } else {
+            throw new XAException(XAException.XAER_INVAL);
+        }
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#prepare
+     */
+    public synchronized int prepare(Xid xid) throws XAException {
+        TransactionContext tx = (TransactionContext) txGlobal.get(xid);
+        if (tx == null) {
+            throw new XAException(XAException.XAER_NOTA);
+        }
+        return XA_OK;
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#rollback
+     */
+    public void rollback(Xid xid) throws XAException {
+        TransactionContext tx = (TransactionContext) txGlobal.get(xid);
+        if (tx == null) {
+            throw new XAException(XAException.XAER_NOTA);
+        }
+        try {
+            tx.rollback();
+        } catch (TransactionException e) {
+            log.error("Unable to rollback transaction.", e);
+            throw new XAException(XAException.XAER_RMERR);
+        }
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#commit
+     */
+    public void commit(Xid xid, boolean onePhase) throws XAException {
+        TransactionContext tx = (TransactionContext) txGlobal.get(xid);
+        if (tx == null) {
+            throw new XAException(XAException.XAER_NOTA);
+        }
+
+        try {
+            tx.commit();
+        } catch (TransactionException e) {
+            log.error("Unable to commit transaction.", e);
+            throw new XAException(XAException.XAER_RMERR);
+        }
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#recover
+     *      <p/>
+     *      No recovery support yet.
+     */
+    public Xid[] recover(int flags) throws XAException {
+        return new Xid[0];
+    }
+
+    /**
+     * @see javax.transaction.xa.XAResource#recover
+     *      <p/>
+     *      No recovery support yet.
+     */
+    public void forget(Xid xid) throws XAException {
+    }
+
+    /**
+     * Associate this session with a global transaction. Internally, set
+     * the transaction containing all transaction-local objects to be
+     * used when performing item retrieval and store.
+     */
+    void associate(TransactionContext tx) {
+        this.tx = tx;
+
+        wsp.getItemStateManager().setTransactionContext(tx);
+    }
+
+    /**
+     * Return a flag indicating whether this resource is associated
+     * with a transaction.
+     *
+     * @return <code>true</code> if this resource is associated
+     *         with a transaction; otherwise <code>false</code>
+     */
+    boolean isAssociated() {
+        return tx != null;
+    }
+
+    /**
+     * Disassociate this session from a global transaction. Internally,
+     * clear the transaction object.
+     */
+    void disassociate() {
+        tx = null;
+
+        wsp.getItemStateManager().setTransactionContext(null);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.core.SessionImpl#dispatch
+     *      <p/>
+     *      If we are currently associated with a transaction, the dispatch operation
+     *      will be postponed until commit.
+     */
+    protected void dispatch(EventStateCollection events) {
+        if (tx != null) {
+            tx.addListener(new EventDispatcher(events));
+            return;
+        }
+        super.dispatch(events);
+    }
+
+    /**
+     * Internal {@link org.apache.jackrabbit.core.state.TransactionListener} implementation that will dispatch
+     * events only when a transaction has actually been committed.
+     */
+    static class EventDispatcher implements TransactionListener {
+
+        /**
+         * Events to dispatch if transaction is committed
+         */
+        private final EventStateCollection events;
+
+        /**
+         * Create a new instance of this class.
+         *
+         * @param events events to dispatch on commit
+         */
+        public EventDispatcher(EventStateCollection events) {
+            this.events = events;
+        }
+
+        /**
+         * @see org.apache.jackrabbit.core.state.TransactionListener#transactionCommitted
+         *      <p/>
+         *      Dispatch events.
+         */
+        public void transactionCommitted(TransactionContext tx) {
+            events.dispatch();
+        }
+
+        /**
+         * @see org.apache.jackrabbit.core.state.TransactionListener#transactionCommitted
+         *      <p/>
+         *      Nothing to do.
+         */
+        public void transactionRolledBack(TransactionContext tx) {
+        }
+    }
+
+    /**
+     * Compare two strings for equality. If both are <code>null</code>, this
+     * is also considered to be equal.
+     */
+    private static boolean stringsEqual(String s1, String s2) {
+        return s1 == null ? s2 == null : s1.equals(s2);
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java	Sun Jan 23 09:11:20 2005
@@ -57,7 +57,7 @@
     /**
      * The ItemStateProvider of the session that creates the events.
      */
-    private final ItemStateProvider provider;
+    private final ItemStateManager provider;
 
     /**
      * The HierarchyManager of the session that creates the events.
@@ -71,7 +71,7 @@
      */
     EventStateCollection(ObservationManagerFactory dispatcher,
                          SessionImpl session,
-                         ItemStateProvider provider,
+                         ItemStateManager provider,
                          HierarchyManager hmgr) {
         this.dispatcher = dispatcher;
         this.session = session;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java	Sun Jan 23 09:11:20 2005
@@ -22,7 +22,7 @@
 import org.apache.jackrabbit.core.*;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.log4j.Logger;
 
 import javax.jcr.RepositoryException;
@@ -151,7 +151,7 @@
     }
 
     public EventStateCollection createEventStateCollection(SessionImpl session,
-                                                           ItemStateProvider provider,
+                                                           ItemStateManager provider,
                                                            HierarchyManager hmgr) {
         return new EventStateCollection(this, session, provider, hmgr);
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java	Sun Jan 23 09:11:20 2005
@@ -16,8 +16,8 @@
  */
 package org.apache.jackrabbit.core.search;
 
-import org.apache.jackrabbit.core.state.ItemStateProvider;
 import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 
 import java.io.IOException;
 
@@ -26,21 +26,25 @@
  */
 public abstract class AbstractQueryHandler implements QueryHandler {
 
-    /** A <code>FileSystem</code> to store the search index */
+    /**
+     * A <code>FileSystem</code> to store the search index
+     */
     private FileSystem fs;
 
-    /** The persistent <code>ItemStateProvider</code> */
-    private ItemStateProvider stateProvider;
+    /**
+     * The persistent <code>ItemStateManager</code>
+     */
+    private ItemStateManager stateProvider;
 
     /**
      * Initializes this query handler by setting all properties in this class
      * with appropriate parameter values.
      *
-     * @param fs a {@link org.apache.jackrabbit.core.fs.FileSystem} this
-     *  <code>QueryHandler</code> may use to store its index.
+     * @param fs            a {@link FileSystem} this
+     *                      <code>QueryHandler</code> may use to store its index.
      * @param stateProvider provides persistent item states.
      */
-    public final void init(FileSystem fs, ItemStateProvider stateProvider)
+    public final void init(FileSystem fs, ItemStateManager stateProvider)
             throws IOException {
         this.fs = fs;
         this.stateProvider = stateProvider;
@@ -54,21 +58,22 @@
     protected abstract void doInit() throws IOException;
 
     /**
-     * Returns the persistent {@link org.apache.jackrabbit.core.state.ItemStateProvider}
+     * Returns the persistent {@link ItemStateManager}
      * of the workspace this <code>QueryHandler</code> is based on.
      *
      * @return the persistent <code>ItemStateProvider</code> of the current
-     *   workspace.
+     *         workspace.
      */
-    protected ItemStateProvider getItemStateProvider() {
+    protected ItemStateManager getItemStateProvider() {
         return stateProvider;
     }
 
     /**
      * Returns the {@link org.apache.jackrabbit.core.fs.FileSystem} instance
      * this <code>QueryHandler</code> may use to store its index.
+     *
      * @return the <code>FileSystem</code> instance for this
-     *   <code>QueryHandler</code>.
+     *         <code>QueryHandler</code>.
      */
     protected FileSystem getFileSystem() {
         return fs;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java	Sun Jan 23 09:11:20 2005
@@ -17,7 +17,7 @@
 package org.apache.jackrabbit.core.search;
 
 import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.fs.FileSystem;
@@ -40,12 +40,12 @@
      * Initializes this query handler. This method is called after the
      * <code>QueryHandler</code> is instantiated.
      *
-     * @param fs a {@link org.apache.jackrabbit.core.fs.FileSystem} this
+     * @param fs a {@link FileSystem} this
      *  <code>QueryHandler</code> may use to store its index.
      * @param stateProvider provides persistent item states.
      * @throws IOException if an error occurs during initialization.
      */
-    public void init(FileSystem fs, ItemStateProvider stateProvider) throws IOException;
+    public void init(FileSystem fs, ItemStateManager stateProvider) throws IOException;
 
     /**
      * Adds a <code>Node</code> to the search index.

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	Sun Jan 23 09:11:20 2005
@@ -16,18 +16,8 @@
  */
 package org.apache.jackrabbit.core.search.lucene;
 
-import org.apache.jackrabbit.core.util.uuid.UUID;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
-import org.apache.jackrabbit.core.state.NoSuchItemStateException;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.NoPrefixDeclaredException;
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.InternalValue;
-import org.apache.jackrabbit.core.Path;
-import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.state.*;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 
@@ -45,11 +35,14 @@
  */
 class NodeIndexer {
 
-    /** The <code>NodeState</code> of the node to index */
+    /**
+     * The <code>NodeState</code> of the node to index
+     */
     private final NodeState node;
-
-    /** The persistent item state provider */
-    private final ItemStateProvider stateProvider;
+    /**
+     * The persistent item state provider
+     */
+    private final ItemStateManager stateProvider;
 
     /**
      * Namespace mappings to use for indexing. This is the internal
@@ -59,12 +52,13 @@
 
     /**
      * Creates a new node indexer.
-     * @param node the node state to index.
+     *
+     * @param node          the node state to index.
      * @param stateProvider the persistent item state manager to retrieve properties.
-     * @param mappings internal namespace mappings.
+     * @param mappings      internal namespace mappings.
      */
     private NodeIndexer(NodeState node,
-                        ItemStateProvider stateProvider,
+                        ItemStateManager stateProvider,
                         NamespaceMappings mappings) {
         this.node = node;
         this.stateProvider = stateProvider;
@@ -73,15 +67,16 @@
 
     /**
      * Creates a lucene Document from a node.
-     * @param node the node state to index.
+     *
+     * @param node          the node state to index.
      * @param stateProvider the state provider to retrieve property values.
-     * @param mappings internal namespace mappings.
+     * @param mappings      internal namespace mappings.
      * @return the lucene Document.
      * @throws RepositoryException if an error occurs while reading property
-     *   values from the <code>ItemStateProvider</code>.
+     *                             values from the <code>ItemStateProvider</code>.
      */
     public static Document createDocument(NodeState node,
-                                          ItemStateProvider stateProvider,
+                                          ItemStateManager stateProvider,
                                           NamespaceMappings mappings)
             throws RepositoryException {
         NodeIndexer indexer = new NodeIndexer(node, stateProvider, mappings);
@@ -90,9 +85,10 @@
 
     /**
      * Creates a lucene Document.
+     *
      * @return the lucene Document with the index layout.
      * @throws RepositoryException if an error occurs while reading property
-     *   values from the <code>ItemStateProvider</code>.
+     *                             values from the <code>ItemStateProvider</code>.
      */
     private Document createDoc() throws RepositoryException {
         Document doc = new Document();
@@ -108,8 +104,7 @@
                 doc.add(new Field(FieldNames.LABEL, "", false, true, false));
             } else {
                 doc.add(new Field(FieldNames.PARENT, node.getParentUUID(), true, true, false));
-                NodeState parent = (NodeState) stateProvider.getItemState(
-                        new NodeId(node.getParentUUID()));
+                NodeState parent = (NodeState) stateProvider.getItemState(new NodeId(node.getParentUUID()));
                 List entries = parent.getChildNodeEntries(node.getUUID());
                 for (Iterator it = entries.iterator(); it.hasNext();) {
                     NodeState.ChildNodeEntry child = (NodeState.ChildNodeEntry) it.next();
@@ -147,9 +142,10 @@
 
     /**
      * Adds a value to the lucene Document.
-     * @param doc the document.
+     *
+     * @param doc   the document.
      * @param value the internal jackrabbit value.
-     * @param name the name of the property.
+     * @param name  the name of the property.
      */
     private void addValue(Document doc, InternalValue value, QName name) {
         String fieldName = name.toString();
@@ -195,7 +191,7 @@
                         false));
                 break;
             case PropertyType.REFERENCE:
-                String uuid = ((UUID) internalValue).toString();
+                String uuid = internalValue.toString();
                 doc.add(new Field(fieldName,
                         uuid,
                         false,
@@ -203,7 +199,7 @@
                         false));
                 break;
             case PropertyType.PATH:
-                String path = ((Path) internalValue).toString();
+                String path = internalValue.toString();
                 doc.add(new Field(fieldName,
                         path,
                         false,

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/AbstractPersistenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/AbstractPersistenceManager.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/AbstractPersistenceManager.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.QName;
+
+import java.util.Iterator;
+
+/**
+ * Implementation <code>PersistenceManager</code> that handles some
+ * concepts.
+ */
+public abstract class AbstractPersistenceManager implements PersistenceManager {
+
+    /**
+     * @see PersistenceManager#createNew
+     */
+    public NodeState createNew(String uuid, QName nodeTypeName,
+                               String parentUUID) {
+        return new NodeState(uuid, nodeTypeName, parentUUID,
+                NodeState.STATUS_NEW, false);
+    }
+
+    /**
+     * @see PersistenceManager#createNew
+     */
+    public PropertyState createNew(QName name, String parentUUID) {
+        return new PropertyState(name, parentUUID,
+                PropertyState.STATUS_NEW, false);
+    }
+
+    /**
+     * Store modified states and node references, atomically.
+     *
+     * @param states       states that have been modified
+     * @param refsIterator refs to store
+     * @throws ItemStateException if an error occurs
+     */
+    public void store(Iterator states, Iterator refsIterator)
+            throws ItemStateException {
+        while (states.hasNext()) {
+            ItemState state = (ItemState) states.next();
+            if (state.isNode()) {
+                NodeState ns = (NodeState) state;
+                switch (state.getStatus()) {
+                    case NodeState.STATUS_EXISTING_REMOVED:
+                        destroy(ns);
+                        break;
+                    default:
+                        store(ns);
+                        break;
+                }
+            } else {
+                PropertyState ps = (PropertyState) state;
+                switch (state.getStatus()) {
+                    case PropertyState.STATUS_EXISTING_REMOVED:
+                        destroy(ps);
+                        break;
+                    default:
+                        store(ps);
+                        break;
+                }
+            }
+        }
+
+        while (refsIterator.hasNext()) {
+            NodeReferences refs = (NodeReferences) refsIterator.next();
+            switch (refs.getStatus()) {
+                case NodeReferences.STATUS_DESTROYED:
+                    destroy(refs);
+                    break;
+                default:
+                    store(refs);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Store a node state. Subclass responsibility.
+     *
+     * @param state node state to store
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void store(NodeState state) throws ItemStateException;
+
+    /**
+     * Store a property state. Subclass responsibility.
+     *
+     * @param state property state to store
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void store(PropertyState state) throws ItemStateException;
+
+    /**
+     * Store a references object. Subclass responsibility.
+     *
+     * @param refs references object to store
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void store(NodeReferences refs) throws ItemStateException;
+
+    /**
+     * Destroy a node state. Subclass responsibility.
+     *
+     * @param state node state to destroy
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void destroy(NodeState state) throws ItemStateException;
+
+    /**
+     * Destroy a property state. Subclass responsibility.
+     *
+     * @param state property state to destroy
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void destroy(PropertyState state) throws ItemStateException;
+
+    /**
+     * Destroy a node references object. Subclass responsibility.
+     *
+     * @param refs node references object to destroy
+     * @throws ItemStateException if an error occurs
+     */
+    protected abstract void destroy(NodeReferences refs)
+            throws ItemStateException;
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java	Sun Jan 23 09:11:20 2005
@@ -79,11 +79,15 @@
 
     protected long lastModified;
 
-    protected String baseVersionID;
 
     protected ItemId id;
 
     /**
+     * Flag indicating whether this state is transient
+     */
+    private final boolean isTransient;
+
+    /**
      * Listeners (weak references)
      */
     protected final transient Map listeners =
@@ -98,8 +102,10 @@
      * @param parentUUID    the UUID of the (primary) parent node or <code>null</code>
      * @param id            the id of the item state object
      * @param initialStatus the initial status of the item state object
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    protected ItemState(String parentUUID, ItemId id, int initialStatus) {
+    protected ItemState(String parentUUID, ItemId id, int initialStatus,
+                        boolean isTransient) {
         switch (initialStatus) {
             case STATUS_EXISTING:
             case STATUS_NEW:
@@ -112,10 +118,10 @@
         }
         this.id = id;
         this.parentUUID = parentUUID;
-        baseVersionID = "v0.0";
         // @todo use modification count instead of ms (not precise enough)
         lastModified = System.currentTimeMillis();
         overlayedState = null;
+        this.isTransient = isTransient;
     }
 
     /**
@@ -123,8 +129,10 @@
      *
      * @param overlayedState backing persistent item state
      * @param initialStatus  the initial status of the new <code>ItemState</code> instance
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    protected ItemState(ItemState overlayedState, int initialStatus) {
+    protected ItemState(ItemState overlayedState, int initialStatus,
+                        boolean isTransient) {
         switch (initialStatus) {
             case STATUS_EXISTING:
             case STATUS_EXISTING_MODIFIED:
@@ -137,24 +145,39 @@
                 throw new IllegalArgumentException(msg);
         }
         this.overlayedState = overlayedState;
-        // add this transient state as a listener on the overlayed state
         this.overlayedState.addListener(this);
+        this.isTransient = isTransient;
     }
 
     /**
-     * Copy state from another state. Copies over all state variables from
-     * another state.
-     *
-     * @param state state to copy
+     * Copy state information from a state into this state
+     * @param state source state information
      */
     protected void copy(ItemState state) {
-        parentUUID = state.parentUUID;
-        baseVersionID = state.getBaseVersionID();
+        parentUUID = state.getParentUUID();
         lastModified = state.getLastModified();
         id = state.getId();
     }
 
     /**
+     * Pull state information from overlayed state.
+     */
+    void pull() {
+        if (overlayedState != null) {
+            copy(overlayedState);
+        }
+    }
+
+    /**
+     * Push state information into overlayed state.
+     */
+    void push() {
+        if (overlayedState != null) {
+            overlayedState.copy(this);
+        }
+    }
+
+    /**
      * Called by <code>TransientItemStateManager</code> when this item state
      * is disposed.
      */
@@ -166,6 +189,17 @@
     }
 
     /**
+     * Connect this state to some underlying overlayed state.
+     */
+    protected void connect(ItemState overlayedState) {
+        if (this.overlayedState != null) {
+            throw new IllegalStateException("Item state already connected: " + this);
+        }
+        this.overlayedState = overlayedState;
+        this.overlayedState.addListener(this);
+    }
+
+    /**
      * Disconnect this state from the underlying overlayed state.
      */
     protected void disconnect() {
@@ -277,7 +311,7 @@
      *         otherwise <code>false</code>
      */
     public boolean isTransient() {
-        return status != STATUS_EXISTING;
+        return isTransient;
 
     }
 
@@ -319,13 +353,13 @@
      */
     public void setStatus(int newStatus) {
         switch (newStatus) {
-            case ItemState.STATUS_NEW:
-            case ItemState.STATUS_EXISTING:
-            case ItemState.STATUS_EXISTING_REMOVED:
-            case ItemState.STATUS_EXISTING_MODIFIED:
-            case ItemState.STATUS_STALE_MODIFIED:
-            case ItemState.STATUS_STALE_DESTROYED:
-            case ItemState.STATUS_UNDEFINED:
+            case STATUS_NEW:
+            case STATUS_EXISTING:
+            case STATUS_EXISTING_REMOVED:
+            case STATUS_EXISTING_MODIFIED:
+            case STATUS_STALE_MODIFIED:
+            case STATUS_STALE_DESTROYED:
+            case STATUS_UNDEFINED:
                 status = newStatus;
                 return;
         }
@@ -378,15 +412,6 @@
     }
 
     /**
-     * Returns the id of the version this item state is based on.
-     *
-     * @return the id of the version this item state is based on.
-     */
-    public String getBaseVersionID() {
-        return baseVersionID;
-    }
-
-    /**
      * Add an <code>ItemStateListener</code>
      *
      * @param listener the new listener to be informed on modifications
@@ -411,14 +436,21 @@
      * @see ItemStateListener#stateCreated
      */
     public void stateCreated(ItemState created) {
+        // underlying state has been permanently created
+        status = STATUS_EXISTING;
     }
 
     /**
      * @see ItemStateListener#stateDestroyed
      */
     public void stateDestroyed(ItemState destroyed) {
-        // underlying persistent state has been permanently destroyed
-        status = STATUS_STALE_DESTROYED;
+        // underlying state has been permanently destroyed
+        if (isTransient || status != STATUS_EXISTING) {
+            status = STATUS_STALE_DESTROYED;
+        } else {
+            status = STATUS_EXISTING_REMOVED;
+        }
+        // @todo propagate event to our listeners too?
     }
 
     /**
@@ -426,13 +458,21 @@
      */
     public void stateModified(ItemState modified) {
         // underlying state has been modified
-        status = STATUS_STALE_MODIFIED;
+        if (isTransient || status != STATUS_EXISTING) {
+            status = STATUS_STALE_MODIFIED;
+        } else {
+            // this instance represents existing state, update it
+            pull();
+        }
+        // @todo propagate event to our listeners too?
     }
 
     /**
      * @see ItemStateListener#stateDiscarded
      */
     public void stateDiscarded(ItemState discarded) {
+        // underlying persistent state has been discarded, discard this instance too
+        discard();
     }
 
     //-------------------------------------------------< Serializable support >

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java	Sun Jan 23 09:11:20 2005
@@ -24,6 +24,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
+import java.io.PrintStream;
 
 /**
  * An <code>ItemStateCache</code> maintains a cache of <code>ItemState</code>
@@ -157,5 +158,50 @@
         // use temp collection to avoid ConcurrentModificationException
         Collection tmp = new ArrayList(cache.values());
         return tmp.iterator();
+    }
+
+    /**
+     * Dumps the state of this <code>ItemStateCache</code> instance
+     * (used for diagnostic purposes).
+     *
+     * @param ps
+     */
+    void dump(PrintStream ps) {
+        ps.println("entries in cache:");
+        ps.println();
+        Iterator iter = keys();
+        while (iter.hasNext()) {
+            ItemId id = (ItemId) iter.next();
+            ItemState state = retrieve(id);
+            dumpItemState(id, state, ps);
+        }
+    }
+
+    private void dumpItemState(ItemId id, ItemState state, PrintStream ps) {
+        ps.print(state.isNode() ? "Node: " : "Prop: ");
+        switch (state.getStatus()) {
+            case ItemState.STATUS_EXISTING:
+                ps.print("[existing]           ");
+                break;
+            case ItemState.STATUS_EXISTING_MODIFIED:
+                ps.print("[existing, modified] ");
+                break;
+            case ItemState.STATUS_EXISTING_REMOVED:
+                ps.print("[existing, removed]  ");
+                break;
+            case ItemState.STATUS_NEW:
+                ps.print("[new]                ");
+                break;
+            case ItemState.STATUS_STALE_DESTROYED:
+                ps.print("[stale, destroyed]   ");
+                break;
+            case ItemState.STATUS_STALE_MODIFIED:
+                ps.print("[stale, modified]    ");
+                break;
+            case ItemState.STATUS_UNDEFINED:
+                ps.print("[undefined]          ");
+                break;
+        }
+        ps.println(id + " (" + state + ")");
     }
 }

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateManager.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateManager.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.NodeId;
+
+/**
+ * The <code>ItemStateManager</code> interface...
+ */
+public interface ItemStateManager {
+
+    /**
+     * Return an item state, given its item id.
+     * @param id item id
+     * @return item state
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException if an error occurs
+     */
+    public ItemState getItemState(ItemId id)
+            throws NoSuchItemStateException, ItemStateException;
+
+    /**
+     * Return a flag indicating whether an item state for a given
+     * item id exists.
+     * @param id item id
+     * @return <code>true</code> if an item state exists,
+     *         otherwise <code>false</code>
+     */
+    public boolean hasItemState(ItemId id);
+
+    /**
+     * Return a node references object, given its target id
+     * @param targetId target id
+     * @return
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException if an error occurs
+     */
+    public NodeReferences getNodeReferences(NodeId targetId)
+        throws NoSuchItemStateException, ItemStateException;
+
+    /**
+     * Begin an update operation on the provider.
+     * @return update operation
+     * @throws ItemStateException if an error occurs
+     */
+    public UpdateOperation beginUpdate() throws ItemStateException;
+}

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateProvider.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemStateProvider.java?view=auto&rev=126220
==============================================================================

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.commons.collections.ReferenceMap;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.QName;
+import org.apache.log4j.Logger;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Local <code>ItemStateManager</code> that isolates changes to
+ * persistent states from other clients.
+ */
+public class LocalItemStateManager extends ItemStateCache
+        implements ItemStateManager, ItemStateListener, TransactionListener {
+
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(LocalItemStateManager.class);
+
+    /**
+     * Known attribute name
+     */
+    private static final String ATTRIBUTE_STATES = "ItemStates";
+
+    /**
+     * Known attribute name
+     */
+    private static final String ATTRIBUTE_REFS = "NodeReferences";
+
+    /**
+     * Shared item state manager
+     */
+    private final SharedItemStateManager sharedStateMgr;
+
+    /**
+     * Currently associated transaction
+     */
+    private TransactionContext tx;
+
+    /**
+     * A cache for <code>NodeReferences</code> objects.
+     */
+    private Map refsCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+
+    /**
+     * Creates a new <code>LocalItemStateManager</code> instance.
+     *
+     * @param sharedStateMgr shared state manager
+     */
+    public LocalItemStateManager(SharedItemStateManager sharedStateMgr) {
+        this.sharedStateMgr = sharedStateMgr;
+    }
+
+    /**
+     * Disposes this <code>LocalItemStateManager</code> and frees resources.
+     */
+    public void dispose() {
+        // clear cache
+        evictAll();
+
+        refsCache.clear();
+    }
+
+    /**
+     * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
+     */
+    protected NodeState getNodeState(NodeId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        // check cache
+        if (isCached(id)) {
+            return (NodeState) retrieve(id);
+        }
+
+        // load from parent manager and wrap
+        NodeState state = (NodeState) sharedStateMgr.getItemState(id);
+        state = new NodeState(state, state.getStatus(), false);
+
+        // put it in cache
+        cache(state);
+
+        // register as listener
+        state.addListener(this);
+        return state;
+    }
+
+    /**
+     * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
+     */
+    protected PropertyState getPropertyState(PropertyId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        // check cache
+        if (isCached(id)) {
+            return (PropertyState) retrieve(id);
+        }
+
+        // load from parent manager and wrap
+        PropertyState state = (PropertyState) sharedStateMgr.getItemState(id);
+        state = new PropertyState(state, state.getStatus(), false);
+
+        // put it in cache
+        cache(state);
+
+        // register as listener
+        state.addListener(this);
+        return state;
+    }
+
+    /**
+     * Set transaction context
+     */
+    public void setTransactionContext(TransactionContext tx) {
+        dispose();
+
+        if (tx != null) {
+            if (tx.getAttribute(ATTRIBUTE_STATES) == null) {
+                tx.setAttribute(ATTRIBUTE_STATES, new ArrayList());
+                tx.setAttribute(ATTRIBUTE_REFS, new ArrayList());
+                tx.addListener(this);
+            } else {
+                List states = (List) tx.getAttribute(ATTRIBUTE_STATES);
+                for (int i = 0; i < states.size(); i++) {
+                    cache((ItemState) states.get(i));
+                }
+
+                List refsCollection = (List) tx.getAttribute(ATTRIBUTE_REFS);
+                for (int i = 0; i < refsCollection.size(); i++) {
+                    NodeReferences refs = (NodeReferences) states.get(i);
+                    refsCache.put(refs.getTargetId(), refs);
+                }
+            }
+        }
+        this.tx = tx;
+    }
+
+    /**
+     * Dumps the state of this <code>LocalItemStateManager</code> instance
+     * (used for diagnostic purposes).
+     *
+     * @param ps
+     */
+    public void dump(PrintStream ps) {
+        ps.println("LocalItemStateManager (" + this + ")");
+        ps.println();
+        super.dump(ps);
+    }
+
+    //-----------------------------------------------------< ItemStateManager >
+
+    /**
+     * @see ItemStateManager#getItemState(ItemId)
+     */
+    public synchronized ItemState getItemState(ItemId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        if (id.denotesNode()) {
+            return getNodeState((NodeId) id);
+        } else {
+            return getPropertyState((PropertyId) id);
+        }
+    }
+
+    /**
+     * @see ItemStateManager#hasItemState(ItemId)
+     */
+    public boolean hasItemState(ItemId id) {
+        if (isCached(id)) {
+            return true;
+        }
+        return sharedStateMgr.hasItemState(id);
+    }
+
+    /**
+     * @see ItemStateManager#getNodeReferences
+     */
+    public synchronized NodeReferences getNodeReferences(NodeId targetId)
+            throws NoSuchItemStateException, ItemStateException {
+
+        if (refsCache.containsKey(targetId)) {
+            return (NodeReferences) refsCache.get(targetId);
+        }
+
+        NodeReferences refs = sharedStateMgr.getNodeReferences(targetId);
+        refs = new NodeReferences(refs);
+
+        refsCache.put(targetId, refs);
+
+        return refs;
+    }
+
+    /**
+     * @see ItemStateManager#beginUpdate
+     */
+    public UpdateOperation beginUpdate() throws ItemStateException {
+        return new Update();
+    }
+
+    /**
+     * End an update operation
+     */
+    private void endUpdate(List states, List refsCollection)
+            throws ItemStateException {
+
+        for (int i = 0; i < states.size(); i++) {
+            ItemState state = (ItemState) states.get(i);
+            state.connect(getOrCreateOverlayed(state));
+            state.push();
+        }
+        for (int i = 0; i < refsCollection.size(); i++) {
+            NodeReferences refs = (NodeReferences) refsCollection.get(i);
+            refs.connect(getOrCreateOverlayed(refs));
+            refs.push();
+        }
+        sharedStateMgr.store(states, refsCollection);
+    }
+
+    /**
+     * Return the item state inside the shared item state manager
+     * corresponding to a given item state.
+     */
+    private ItemState getOrCreateOverlayed(ItemState state)
+            throws ItemStateException {
+
+        switch (state.getStatus()) {
+            case ItemState.STATUS_NEW:
+                if (state.isNode()) {
+                    NodeState ns = (NodeState) state;
+                    return sharedStateMgr.createInstance(ns.getUUID(),
+                            ns.getNodeTypeName(), ns.getParentUUID());
+                } else {
+                    PropertyState ps = (PropertyState) state;
+                    return sharedStateMgr.createInstance(ps.getName(),
+                            ps.getParentUUID());
+                }
+            default:
+                return sharedStateMgr.getItemState(state.getId());
+        }
+    }
+
+    /**
+     * Return the references object inside the shared item state manager
+     * corresponding to a references object.
+     */
+    private NodeReferences getOrCreateOverlayed(NodeReferences refs)
+            throws ItemStateException {
+
+        switch (refs.getStatus()) {
+            case NodeReferences.STATUS_NEW:
+                return new NodeReferences(refs.getTargetId());
+
+            default:
+                return sharedStateMgr.getNodeReferences(refs.getTargetId());
+        }
+    }
+
+    //--------------------------------------------------< TransactionListener >
+
+    /**
+     * @see TransactionListener#transactionCommitted
+     */
+    public void transactionCommitted(TransactionContext tx)
+            throws TransactionException {
+
+        List states = (List) tx.getAttribute(ATTRIBUTE_STATES);
+        List refsCollection = (List) tx.getAttribute(ATTRIBUTE_REFS);
+
+        try {
+            endUpdate(states, refsCollection);
+        } catch (ItemStateException e) {
+            throw new TransactionException("Unable to end update.", e);
+        }
+    }
+
+    /**
+     * @see TransactionListener#transactionRolledBack
+     */
+    public void transactionRolledBack(TransactionContext tx) {
+    }
+
+    //------------------------------------------------------< UpdateOperation >
+
+    class Update implements UpdateOperation {
+
+        /**
+         * Modified states
+         */
+        private final List states = new ArrayList();
+
+        /**
+         * Modified references
+         */
+        private final List refsCollection = new ArrayList();
+
+        /**
+         * @see UpdateOperation#createNew
+         */
+        public NodeState createNew(String uuid, QName nodeTypeName,
+                                   String parentUUID) {
+
+            NodeState state = new NodeState(uuid, nodeTypeName, parentUUID,
+                    ItemState.STATUS_NEW, false);
+
+            cache(state);
+            state.addListener(LocalItemStateManager.this);
+
+            return state;
+        }
+
+        /**
+         * @see UpdateOperation#createNew
+         */
+        public PropertyState createNew(QName propName, String parentUUID) {
+            PropertyState state = new PropertyState(propName, parentUUID,
+                    ItemState.STATUS_NEW, false);
+
+            cache(state);
+            state.addListener(LocalItemStateManager.this);
+
+            return state;
+        }
+
+        /**
+         * @see UpdateOperation#store
+         */
+        public void store(ItemState state) {
+            state.disconnect();
+            states.add(state);
+            // notify listeners that the specified instance has been modified
+            state.notifyStateUpdated();
+        }
+
+        /**
+         * @see UpdateOperation#store
+         */
+        public void store(NodeReferences refs) {
+            refs.disconnect();
+            refsCollection.add(refs);
+        }
+
+        /**
+         * @see UpdateOperation#destroy
+         */
+        public void destroy(ItemState state) {
+            state.disconnect();
+            state.setStatus(ItemState.STATUS_EXISTING_REMOVED);
+            states.add(state);
+            // notify listeners that the specified instance has been marked 'removed'
+            state.notifyStateDestroyed();
+        }
+
+        /**
+         * @see UpdateOperation#end
+         */
+        public void end() throws ItemStateException {
+            if (tx != null) {
+                List txStates = (List) tx.getAttribute(ATTRIBUTE_STATES);
+                List txRefs = (List) tx.getAttribute(ATTRIBUTE_REFS);
+
+                txStates.addAll(states);
+                txRefs.addAll(refsCollection);
+            } else {
+                endUpdate(states, refsCollection);
+            }
+        }
+    }
+
+    //----------------------------------------------------< ItemStateListener >
+    /**
+     * @see ItemStateListener#stateCreated
+     */
+    public void stateCreated(ItemState created) {
+        // not interested
+    }
+
+    /**
+     * @see ItemStateListener#stateModified
+     */
+    public void stateModified(ItemState modified) {
+        // not interested
+    }
+
+    /**
+     * @see ItemStateListener#stateDestroyed
+     */
+    public void stateDestroyed(ItemState destroyed) {
+        destroyed.removeListener(this);
+        evict(destroyed.getId());
+    }
+
+    /**
+     * @see ItemStateListener#stateDiscarded
+     */
+    public void stateDiscarded(ItemState discarded) {
+        discarded.removeListener(this);
+        evict(discarded.getId());
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java	Sun Jan 23 09:11:20 2005
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
+import org.apache.log4j.Logger;
 
 import java.io.Serializable;
 import java.util.*;
@@ -28,9 +29,17 @@
  */
 public class NodeReferences implements Serializable {
 
+    /**
+     * Serial UID
+     */
     static final long serialVersionUID = 7007727035982680717L;
 
     /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(NodeReferences.class);
+
+    /**
      * id of the target node
      */
     protected NodeId targetId;
@@ -43,7 +52,32 @@
      * REFERENCE property can contain multiple references (if it's multi-valued)
      * to potentially the same target node.
      */
-    protected List references;
+    protected ArrayList references = new ArrayList();
+
+    /**
+     * New state
+     */
+    public static final int STATUS_NEW = 0;
+
+    /**
+     * Existing state
+     */
+    public static final int STATUS_EXISTING = 1;
+
+    /**
+     * Destroyed state
+     */
+    public static final int STATUS_DESTROYED = 2;
+
+    /**
+     * the internal status of this item state
+     */
+    protected int status = STATUS_NEW;
+
+    /**
+     * Backing state (may be null)
+     */
+    private NodeReferences overlayed;
 
     /**
      * Package private constructor
@@ -51,8 +85,66 @@
      * @param targetId
      */
     public NodeReferences(NodeId targetId) {
-        this.targetId = targetId;
-        references = new ArrayList();
+        this.targetId  = targetId;
+    }
+
+    /**
+     * Package private constructor
+     *
+     * @param overlayed overlayed state
+     */
+    public NodeReferences(NodeReferences overlayed) {
+        this.overlayed = overlayed;
+
+        pull();
+    }
+
+    /**
+     * Copy information from another references object into this object
+     * @param refs source references object
+     */
+    void copy(NodeReferences refs) {
+        targetId = refs.targetId;
+        references.clear();
+        references.addAll(refs.getReferences());
+    }
+
+    /**
+     * Pull information from overlayed object.
+     */
+    void pull() {
+        if (overlayed != null) {
+            copy(overlayed);
+        }
+    }
+
+    /**
+     * Push information into overlayed object.
+     */
+    void push() {
+        if (overlayed != null) {
+            overlayed.copy(this);
+        }
+    }
+
+    /**
+     * Connect this object to an underlying overlayed object
+     */
+    void connect(NodeReferences overlayed) {
+        if (this.overlayed != null) {
+            throw new IllegalStateException(
+                    "References object already connected: " + this);
+        }
+        this.overlayed = overlayed;
+    }
+
+    /**
+     * Disconnect this object from the underlying overlayed object.
+     */
+    void disconnect() {
+        if (overlayed != null) {
+            overlayed = null;
+        }
     }
 
     /**
@@ -103,5 +195,32 @@
      */
     public void clearAllReferences() {
         references.clear();
+    }
+
+    /**
+     * Returns the status of this item.
+     *
+     * @return the status of this item.
+     */
+    public int getStatus() {
+        return status;
+    }
+
+    /**
+     * Sets the new status of this item.
+     *
+     * @param newStatus the new status
+     */
+    public void setStatus(int newStatus) {
+        switch (newStatus) {
+            case STATUS_NEW:
+            case STATUS_EXISTING:
+            case STATUS_DESTROYED:
+                status = newStatus;
+                return;
+        }
+        String msg = "illegal status: " + newStatus;
+        log.error(msg);
+        throw new IllegalArgumentException(msg);
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java	Sun Jan 23 09:11:20 2005
@@ -55,27 +55,32 @@
     protected List propertyEntries = new ArrayList();
 
     /**
-     * Package private constructor
+     * Constructor
      *
      * @param overlayedState the backing node state being overlayed
      * @param initialStatus  the initial status of the node state object
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    protected NodeState(NodeState overlayedState, int initialStatus) {
-        super(overlayedState, initialStatus);
+    public NodeState(NodeState overlayedState, int initialStatus,
+                     boolean isTransient) {
+        super(overlayedState, initialStatus, isTransient);
 
-        copy(overlayedState);
+        pull();
     }
 
     /**
-     * Package private constructor
+     * Constructor
      *
      * @param uuid          the UUID of the this node
      * @param nodeTypeName  node type of this node
      * @param parentUUID    the UUID of the parent node
      * @param initialStatus the initial status of the node state object
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    protected NodeState(String uuid, QName nodeTypeName, String parentUUID, int initialStatus) {
-        super(parentUUID, new NodeId(uuid), initialStatus);
+    public NodeState(String uuid, QName nodeTypeName, String parentUUID,
+                     int initialStatus, boolean isTransient) {
+        super(parentUUID, new NodeId(uuid), initialStatus, isTransient);
+
         if (parentUUID != null) {
             parentUUIDs.add(parentUUID);
         }
@@ -483,6 +488,16 @@
         propertyEntries.addAll(propEntries);
     }
 
+    /**
+     * Set the node type name. Needed for deserialization and should therefore
+     * not change the internal status.
+     *
+     * @param nodeTypeName node type name
+     */
+    public synchronized void setNodeTypeName(QName nodeTypeName) {
+        this.nodeTypeName = nodeTypeName;
+    }
+    
     //---------------------------------------------------------< diff methods >
     /**
      * Returns a list of parent UUID's, that do not exist in the overlayed node

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistableItemState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistableItemState.java?view=auto&rev=126220
==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistenceManager.java	Sun Jan 23 09:11:20 2005
@@ -18,7 +18,9 @@
 
 import org.apache.jackrabbit.core.ItemId;
 import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.config.WorkspaceConfig;
+import org.apache.jackrabbit.core.QName;
+
+import java.util.Iterator;
 
 /**
  * <code>PersistenceManager</code> ...
@@ -26,85 +28,74 @@
 public interface PersistenceManager {
 
     /**
-     * @param context
-     * @throws Exception
+     * Initialize this persistent manager.
+     * @param context persistence manager context
+     * @throws Exception if an error occurs
      */
     public void init(PMContext context) throws Exception;
 
     /**
-     * @throws Exception
+     * Close this persistence manager. After having closed a persistence
+     * manager, further operations on this object are treated as illegal
+     * and throw
+     * @throws Exception if an error occurs
      */
     public void close() throws Exception;
 
     /**
-     * @param state
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
+     * Create a new node state instance.
+     * @param uuid          the UUID of the this node
+     * @param nodeTypeName  node type of this node
+     * @param parentUUID    the UUID of the parent node
+     * @return node state instance.
      */
-    public void load(PersistentNodeState state)
-            throws NoSuchItemStateException, ItemStateException;
+    public NodeState createNew(String uuid, QName nodeTypeName,
+                               String parentUUID);
 
     /**
-     * @param state
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
+     * Create a new property state instance.
+     * @param name          name of the property
+     * @param parentUUID    the uuid of the parent node
+     * @return property state instance.
      */
-    public void load(PersistentPropertyState state)
-            throws NoSuchItemStateException, ItemStateException;
+    public PropertyState createNew(QName name, String parentUUID);
 
     /**
-     * @param refs
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
+     * Load the persistent members of a node state.
+     * @param uuid uuid of the node to load
+     * @return loaded node state
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException if an error occurs
      */
-    public void load(NodeReferences refs)
+    public NodeState load(String uuid)
             throws NoSuchItemStateException, ItemStateException;
 
     /**
-     * @param state
-     * @throws ItemStateException
-     */
-    public void store(PersistentNodeState state) throws ItemStateException;
-
-    /**
-     * @param state
-     * @throws ItemStateException
-     */
-    public void store(PersistentPropertyState state) throws ItemStateException;
-
-    /**
-     * @param refs
-     * @throws ItemStateException
+     * Load the persistent members of a property state.
+     * @param name name of the property
+     * @param parentUUID the uuid of the parent node
+     * @return loaded property state
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException if an error occurs
      */
-    public void store(NodeReferences refs) throws ItemStateException;
-
-    /**
-     * @param state
-     * @throws ItemStateException
-     */
-    public void destroy(PersistentNodeState state) throws ItemStateException;
+    public PropertyState load(QName name, String parentUUID)
+            throws NoSuchItemStateException, ItemStateException;
 
     /**
-     * @param state
-     * @throws ItemStateException
+     * Load the persistent members of a node references object.
+     * @param targetId node target id
+     * @return loaded references object
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException if an error occurs
      */
-    public void destroy(PersistentPropertyState state) throws ItemStateException;
-
-    /**
-     * @param refs
-     * @throws ItemStateException
-     */
-    public void destroy(NodeReferences refs) throws ItemStateException;
+    public NodeReferences load(NodeId targetId)
+            throws NoSuchItemStateException, ItemStateException;
 
     /**
-     * Determines if there's <code>PersistentItemState</code> data for
-     * the given item.
-     *
+     * Determines if there's <code>ItemState</code> data for the given item.
      * @param id
      * @return
      * @throws ItemStateException
-     * @see #load(PersistentNodeState)
-     * @see #load(PersistentPropertyState)
      */
     public boolean exists(ItemId id) throws ItemStateException;
 
@@ -115,7 +106,16 @@
      * @param targetId
      * @return
      * @throws ItemStateException
-     * @see #load(NodeReferences)
      */
     public boolean referencesExist(NodeId targetId) throws ItemStateException;
+
+    /**
+     * Save all modified states and node references, atomically.
+     * @param states states that have been modified
+     * @param refsIterator refs to store
+     * @throws ItemStateException if an error occurs
+     */
+    public void store(Iterator states, Iterator refsIterator)
+            throws ItemStateException;
+
 }

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateManager.java?view=auto&rev=126220
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateProvider.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentItemStateProvider.java?view=auto&rev=126220
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentNodeState.java?view=auto&rev=126220
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentPropertyState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PersistentPropertyState.java?view=auto&rev=126220
==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java	Sun Jan 23 09:11:20 2005
@@ -46,11 +46,13 @@
      *
      * @param overlayedState the backing property state being overlayed
      * @param initialStatus  the initial status of the property state object
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    PropertyState(PropertyState overlayedState, int initialStatus) {
-        super(overlayedState, initialStatus);
+    public PropertyState(PropertyState overlayedState, int initialStatus,
+                         boolean isTransient) {
+        super(overlayedState, initialStatus, isTransient);
 
-        copy(overlayedState);
+        pull();
     }
 
     /**
@@ -59,9 +61,11 @@
      * @param name          name of the property
      * @param parentUUID    the uuid of the parent node
      * @param initialStatus the initial status of the property state object
+     * @param isTransient   flag indicating whether this state is transient or not
      */
-    protected PropertyState(QName name, String parentUUID, int initialStatus) {
-        super(parentUUID, new PropertyId(parentUUID, name), initialStatus);
+    public PropertyState(QName name, String parentUUID, int initialStatus,
+                         boolean isTransient) {
+        super(parentUUID, new PropertyId(parentUUID, name), initialStatus, isTransient);
         this.name = name;
         type = PropertyType.UNDEFINED;
         values = new InternalValue[0];

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ReferenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ReferenceManager.java?view=auto&rev=126220
==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java	Sun Jan 23 09:11:20 2005
@@ -29,12 +29,12 @@
 /**
  * <code>SessionItemStateManager</code> ...
  */
-public class SessionItemStateManager implements ItemStateProvider {
+public class SessionItemStateManager implements ItemStateManager {
 
     private static Logger log = Logger.getLogger(SessionItemStateManager.class);
 
     private final NodeId rootNodeId;
-    private final PersistentItemStateProvider persistentStateMgr;
+    private final ItemStateManager persistentStateMgr;
     private VirtualItemStateProvider[] virtualProviders = new VirtualItemStateProvider[0];
     private final TransientItemStateManager transientStateMgr;
     private HierarchyManager hierMgr;
@@ -46,13 +46,17 @@
      * @param persistentStateMgr
      * @param nsResolver
      */
-    public SessionItemStateManager(String rootNodeUUID, PersistentItemStateProvider persistentStateMgr, NamespaceResolver nsResolver) {
+    public SessionItemStateManager(String rootNodeUUID,
+                                   ItemStateManager persistentStateMgr,
+                                   NamespaceResolver nsResolver) {
+
         rootNodeId = new NodeId(rootNodeUUID);
         this.persistentStateMgr = persistentStateMgr;
         // create transient item state manager
         transientStateMgr = new TransientItemStateManager();
         // create hierarchy manager that uses both transient and persistent state
-        hierMgr = new HierarchyManagerImpl(rootNodeUUID, this, nsResolver);
+        hierMgr = new HierarchyManagerImpl(rootNodeUUID, this, nsResolver,
+                transientStateMgr.getAttic());
     }
 
     /**
@@ -92,102 +96,8 @@
         virtualProviders = provs;
     }
 
-    private synchronized void collectDescendantItemStates(ItemId id, List descendents) {
-        // XXX very inefficient implementation, especially if # of transient states
-        // is relatively small compared to the total # of persistent states
-        if (descendents.size() == transientStateMgr.getEntriesCount()) {
-            return;
-        }
-        try {
-            if (id.denotesNode()) {
-                NodeId parentId = (NodeId) id;
-                ItemId[] childIds = hierMgr.listChildren(parentId);
-                for (int i = 0; i < childIds.length; i++) {
-                    ItemId childId = childIds[i];
-                    if (transientStateMgr.hasItemState(childId)) {
-                        ItemState state = transientStateMgr.getItemState(childId);
-                        if (!descendents.contains(state)) {
-                            descendents.add(state);
-                        }
-                    }
-                    if (childId.denotesNode()) {
-                        // recurse
-                        collectDescendantItemStates(childId, descendents);
-                    }
-                }
-                // also add transient child nodes that have been unlinked from
-                // the specified parent node but are not orphaned yet (i.e.
-                // they are still linked to at least one other parent node)
-                if (transientStateMgr.hasItemState(parentId)) {
-                    NodeState parentState = (NodeState) transientStateMgr.getItemState(parentId);
-                    Iterator iter = parentState.getRemovedChildNodeEntries().iterator();
-                    while (iter.hasNext()) {
-                        // removed child nodes
-                        NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) iter.next();
-                        NodeId removedChildId = new NodeId(cne.getUUID());
-                        if (transientStateMgr.hasItemState(removedChildId)) {
-                            ItemState state = transientStateMgr.getItemState(removedChildId);
-                            if (!descendents.contains(state)) {
-                                descendents.add(state);
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (ItemStateException ise) {
-            log.warn("inconsistent hierarchy state", ise);
-        } catch (RepositoryException re) {
-            log.warn("inconsistent hierarchy state", re);
-        }
-    }
-
-    private synchronized void collectDescendantItemStatesInAttic(ItemId id, List descendents) {
-        // XXX very inefficient implementation, especially if # of transient states
-        // is relatively small compared to the total # of persistent states
-        if (descendents.size() == transientStateMgr.getEntriesInAtticCount()) {
-            return;
-        }
-        try {
-            if (id.denotesNode()) {
-                NodeId parentId = (NodeId) id;
-
-                // traverse zombie children (i.e. children marked as removed)
-                ItemId[] childIds = hierMgr.listZombieChildren(parentId);
-                for (int i = 0; i < childIds.length; i++) {
-                    ItemId childId = childIds[i];
-                    // check attic
-                    if (transientStateMgr.hasItemStateInAttic(childId)) {
-                        // found on attic, add to descendents list
-                        ItemState state = transientStateMgr.getItemStateInAttic(childId);
-                        if (!descendents.contains(state)) {
-                            descendents.add(state);
-                        }
-                    }
-                    if (childId.denotesNode()) {
-                        // recurse
-                        collectDescendantItemStatesInAttic(childId, descendents);
-                    }
-                }
-
-                // traverse existing children (because they might have zombie children)
-                childIds = hierMgr.listChildren(parentId);
-                for (int i = 0; i < childIds.length; i++) {
-                    ItemId childId = childIds[i];
-                    if (childId.denotesNode()) {
-                        // recurse
-                        collectDescendantItemStatesInAttic(childId, descendents);
-                    }
-                }
-            }
-        } catch (ItemStateException ise) {
-            log.warn("inconsistent hierarchy state", ise);
-        } catch (RepositoryException re) {
-            log.warn("inconsistent hierarchy state", re);
-        }
-    }
-
     /**
-     * Dumps the state of this <code>TransientItemStateManager</code> instance
+     * Dumps the state of this <code>SessionItemStateManager</code> instance
      * (used for diagnostic purposes).
      *
      * @param ps
@@ -195,8 +105,11 @@
     public void dump(PrintStream ps) {
         ps.println("SessionItemStateManager (" + this + ")");
         ps.println();
-        //persistentStateMgr.dump(ps);
-        ps.println();
+        // FIXME hack!
+        if (persistentStateMgr instanceof ItemStateCache) {
+            ((ItemStateCache) persistentStateMgr).dump(ps);
+            ps.println();
+        }
         transientStateMgr.dump(ps);
         ps.println();
     }
@@ -210,15 +123,15 @@
         return hierMgr;
     }
 
-    //----------------------------------------------------< ItemStateProvider >
+    //-----------------------------------------------------< ItemStateManager >
     /**
-     * @see ItemStateProvider#getItemState(ItemId)
+     * @see ItemStateManager#getItemState(ItemId)
      */
     public ItemState getItemState(ItemId id)
             throws NoSuchItemStateException, ItemStateException {
 
         // first check if the specified item has been transiently removed
-        if (transientStateMgr.hasItemStateInAttic(id)) {
+        if (transientStateMgr.getAttic().hasItemState(id)) {
             /**
              * check if there's new transient state for the specified item
              * (e.g. if a property with name 'x' has been removed and a new
@@ -257,11 +170,11 @@
     }
 
     /**
-     * @see ItemStateProvider#hasItemState(ItemId)
+     * @see ItemStateManager#hasItemState(ItemId)
      */
     public boolean hasItemState(ItemId id) {
         // first check if the specified item has been transiently removed
-        if (transientStateMgr.hasItemStateInAttic(id)) {
+        if (transientStateMgr.getAttic().hasItemState(id)) {
             /**
              * check if there's new transient state for the specified item
              * (e.g. if a property with name 'x' has been removed and a new
@@ -281,6 +194,7 @@
                 return true;
             }
         }
+
         // check if there's persistent state for the specified item
         if (persistentStateMgr.hasItemState(id)) {
             return true;
@@ -297,21 +211,23 @@
     }
 
     /**
-     * @see ItemStateProvider#getItemStateInAttic(ItemId)
+     * @see ItemStateManager#getNodeReferences
      */
-    public ItemState getItemStateInAttic(ItemId id)
+    public NodeReferences getNodeReferences(NodeId targetId)
             throws NoSuchItemStateException, ItemStateException {
-        return transientStateMgr.getItemStateInAttic(id);
+
+        return persistentStateMgr.getNodeReferences(targetId);
     }
 
     /**
-     * @see ItemStateProvider#hasItemStateInAttic(ItemId)
+     * @see ItemStateManager#beginUpdate
      */
-    public boolean hasItemStateInAttic(ItemId id) {
-        return transientStateMgr.hasItemStateInAttic(id);
+    public UpdateOperation beginUpdate() throws ItemStateException {
+        return persistentStateMgr.beginUpdate();
     }
 
     //< more methods for listing and retrieving transient ItemState instances >
+
     /**
      * @param id
      * @return
@@ -658,38 +574,6 @@
      */
     public void disposeAllTransientItemStates() {
         transientStateMgr.disposeAllItemStates();
-    }
-
-    //------------------< methods for creating persistent ItemState instances >
-    /**
-     * Creates a <code>PersistentNodeState</code> instance representing new,
-     * i.e. not yet existing state. Call <code>{@link PersistentNodeState#store()}</code>
-     * on the returned object to make it persistent.
-     *
-     * @param uuid
-     * @param nodeTypeName
-     * @param parentUUID
-     * @return
-     * @throws ItemStateException
-     */
-    public PersistentNodeState createPersistentNodeState(String uuid, QName nodeTypeName, String parentUUID)
-            throws ItemStateException {
-        return persistentStateMgr.createNodeState(uuid, nodeTypeName, parentUUID);
-    }
-
-    /**
-     * Creates a <code>PersistentPropertyState</code> instance representing new,
-     * i.e. not yet existing state. Call <code>{@link PersistentPropertyState#store()}</code>
-     * on the returned object to make it persistent.
-     *
-     * @param parentUUID
-     * @param propName
-     * @return
-     * @throws ItemStateException
-     */
-    public PersistentPropertyState createPersistentPropertyState(String parentUUID, QName propName)
-            throws ItemStateException {
-        return persistentStateMgr.createPropertyState(parentUUID, propName);
     }
 
     //--------------------------------------------------------< inner classes >

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.commons.collections.ReferenceMap;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.nodetype.NodeDefId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.PropDefId;
+import org.apache.log4j.Logger;
+
+import javax.jcr.PropertyType;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Shared <code>ItemStateManager</code>. Caches objects returned from a
+ * <code>PersistenceManager</code>. Objects returned by this item state
+ * manager are shared among all sessions.
+ */
+public class SharedItemStateManager extends ItemStateCache
+        implements ItemStateManager, ItemStateListener {
+
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(SharedItemStateManager.class);
+
+    /**
+     * Persistence Manager to use for loading and storing items
+     */
+    protected final PersistenceManager persistMgr;
+
+    /**
+     * Keep a hard reference to the root node state
+     */
+    private NodeState root;
+
+    /**
+     * A cache for <code>NodeReferences</code> objects.
+     */
+    private Map refsCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+
+    /**
+     * Creates a new <code>DefaultItemStateManager</code> instance.
+     *
+     * @param persistMgr
+     * @param rootNodeUUID
+     * @param ntReg
+     */
+    public SharedItemStateManager(PersistenceManager persistMgr,
+                                  String rootNodeUUID,
+                                  NodeTypeRegistry ntReg)
+            throws ItemStateException {
+
+        this.persistMgr = persistMgr;
+
+        try {
+            root = getNodeState(new NodeId(rootNodeUUID));
+        } catch (NoSuchItemStateException e) {
+            // create root node
+            root = createRootNodeState(rootNodeUUID, ntReg);
+        }
+    }
+
+    /**
+     * Disposes this <code>SharedItemStateManager</code> and frees resources.
+     */
+    public void dispose() {
+        // clear cache
+        evictAll();
+    }
+
+    private NodeState createRootNodeState(String rootNodeUUID,
+                                          NodeTypeRegistry ntReg)
+            throws ItemStateException {
+
+        NodeState rootState = createInstance(rootNodeUUID, NodeTypeRegistry.REP_ROOT, null);
+
+        // @todo FIXME need to manually setup root node by creating mandatory jcr:primaryType property
+        NodeDefId nodeDefId = null;
+        PropDefId propDefId = null;
+
+        try {
+            nodeDefId = new NodeDefId(ntReg.getRootNodeDef());
+            // FIXME relies on definition of nt:base:
+            // first property definition in nt:base is jcr:primaryType
+            propDefId = new PropDefId(ntReg.getNodeTypeDef(NodeTypeRegistry.NT_BASE).getPropertyDefs()[0]);
+        } catch (NoSuchNodeTypeException nsnte) {
+            String msg = "failed to create root node";
+            log.error(msg, nsnte);
+            throw new ItemStateException(msg, nsnte);
+        }
+        rootState.setDefinitionId(nodeDefId);
+
+        QName propName = new QName(NamespaceRegistryImpl.NS_JCR_URI, "primaryType");
+        rootState.addPropertyEntry(propName);
+
+        PropertyState prop = createInstance(propName, rootNodeUUID);
+        prop.setValues(new InternalValue[]{InternalValue.create(NodeTypeRegistry.REP_ROOT)});
+        prop.setType(PropertyType.NAME);
+        prop.setMultiValued(false);
+        prop.setDefinitionId(propDefId);
+
+        ArrayList states = new ArrayList();
+        states.add(rootState);
+        states.add(prop);
+
+        // do persist root node (incl. properties)
+        store(states, Collections.EMPTY_LIST);
+
+        return rootState;
+    }
+
+    /**
+     * Dumps the state of this <code>SharedItemStateManager</code> instance
+     * (used for diagnostic purposes).
+     *
+     * @param ps
+     */
+    public void dump(PrintStream ps) {
+        ps.println("SharedItemStateManager (" + this + ")");
+        ps.println();
+        super.dump(ps);
+    }
+
+    /**
+     * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
+     */
+    protected NodeState getNodeState(NodeId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        // check cache
+        if (isCached(id)) {
+            return (NodeState) retrieve(id);
+        }
+
+        // load from persisted state
+        NodeState state = persistMgr.load(id.getUUID());
+        state.setStatus(ItemState.STATUS_EXISTING);
+
+        // put it in cache
+        cache(state);
+
+        // register as listener
+        state.addListener(this);
+        return state;
+    }
+
+    /**
+     * @param id
+     * @return
+     * @throws NoSuchItemStateException
+     * @throws ItemStateException
+     */
+    protected PropertyState getPropertyState(PropertyId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        // check cache
+        if (isCached(id)) {
+            return (PropertyState) retrieve(id);
+        }
+
+        // load from persisted state
+        PropertyState state = persistMgr.load(id.getName(), id.getParentUUID());
+        state.setStatus(ItemState.STATUS_EXISTING);
+
+        // put it in cache
+        cache(state);
+
+        // register as listener
+        state.addListener(this);
+        return state;
+    }
+
+    //-----------------------------------------------------< ItemStateManager >
+
+    /**
+     * @see ItemStateManager#getItemState(ItemId)
+     */
+    public synchronized ItemState getItemState(ItemId id)
+            throws NoSuchItemStateException, ItemStateException {
+
+        if (id.denotesNode()) {
+            return getNodeState((NodeId) id);
+        } else {
+            return getPropertyState((PropertyId) id);
+        }
+    }
+
+    /**
+     * @see ItemStateManager#hasItemState(ItemId)
+     */
+    public boolean hasItemState(ItemId id) {
+        if (isCached(id)) {
+            return true;
+        }
+
+        try {
+            return persistMgr.exists(id);
+        } catch (ItemStateException ise) {
+            return false;
+        }
+    }
+
+    /**
+     * @see ItemStateManager#getNodeReferences
+     */
+    public synchronized NodeReferences getNodeReferences(NodeId targetId)
+            throws NoSuchItemStateException, ItemStateException {
+
+        if (refsCache.containsKey(targetId)) {
+            return (NodeReferences) refsCache.get(targetId);
+        }
+
+        NodeReferences refs;
+
+        try {
+            refs = persistMgr.load(targetId);
+        } catch (NoSuchItemStateException nsise) {
+            refs = new NodeReferences(targetId);
+        }
+
+        refsCache.put(targetId, refs);
+        return refs;
+    }
+
+    /**
+     * @see ItemStateManager#beginUpdate
+     */
+    public UpdateOperation beginUpdate() throws ItemStateException {
+        throw new ItemStateException("Update not available.");
+    }
+
+    //-------------------------------------------------------- other operations
+
+    /**
+     * Create a new node state instance
+     *
+     * @param uuid         uuid
+     * @param nodeTypeName node type name
+     * @param parentUUID   parent UUID
+     * @return new node state instance
+     */
+    NodeState createInstance(String uuid, QName nodeTypeName,
+                             String parentUUID) {
+
+        NodeState state = persistMgr.createNew(uuid, nodeTypeName, parentUUID);
+        state.setStatus(ItemState.STATUS_NEW);
+        state.addListener(this);
+
+        return state;
+    }
+
+    /**
+     * Create a new property state instance
+     *
+     * @param propName   property name
+     * @param parentUUID parent UUID
+     * @return new property state instance
+     */
+    PropertyState createInstance(QName propName, String parentUUID) {
+        PropertyState state = persistMgr.createNew(propName, parentUUID);
+        state.setStatus(ItemState.STATUS_NEW);
+        state.addListener(this);
+
+        return state;
+    }
+
+    /**
+     * Store modified states and node references, atomically.
+     *
+     * @param states         states that have been modified
+     * @param refsCollection collection of refs to store
+     * @throws ItemStateException if an error occurs
+     */
+    void store(Collection states, Collection refsCollection)
+            throws ItemStateException {
+
+        persistMgr.store(states.iterator(), refsCollection.iterator());
+
+        Iterator iter = states.iterator();
+        while (iter.hasNext()) {
+            ItemState state = (ItemState) iter.next();
+            int status = state.getStatus();
+            // @todo FIXME need to notify listeners on underlying (shared) state
+            if (state.getOverlayedState() != null) {
+                state = state.getOverlayedState();
+            }
+            switch (status) {
+                case ItemState.STATUS_NEW:
+                    state.notifyStateCreated();
+                    state.setStatus(ItemState.STATUS_EXISTING);
+                    break;
+
+                case ItemState.STATUS_EXISTING_REMOVED:
+                    state.notifyStateDestroyed();
+                    state.discard();
+                    break;
+
+                default:
+                    state.notifyStateUpdated();
+                    state.setStatus(ItemState.STATUS_EXISTING);
+                    break;
+            }
+        }
+    }
+
+
+    //----------------------------------------------------< ItemStateListener >
+
+    /**
+     * @see ItemStateListener#stateCreated
+     */
+    public void stateCreated(ItemState created) {
+        cache(created);
+    }
+
+    /**
+     * @see ItemStateListener#stateModified
+     */
+    public void stateModified(ItemState modified) {
+        // not interested
+    }
+
+    /**
+     * @see ItemStateListener#stateDestroyed
+     */
+    public void stateDestroyed(ItemState destroyed) {
+        destroyed.removeListener(this);
+        evict(destroyed.getId());
+    }
+
+    /**
+     * @see ItemStateListener#stateDiscarded
+     */
+    public void stateDiscarded(ItemState discarded) {
+        discarded.removeListener(this);
+        evict(discarded.getId());
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionContext.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionContext.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionContext.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Represents the transaction on behalf of the component that wants to
+ * explictely demarcate transcation boundaries.
+ */
+public class TransactionContext {
+
+    /**
+     * Transaction listeners
+     */
+    private final List listeners = new ArrayList();
+
+    /**
+     * Transaction attributes
+     */
+    private final Map attributes = new HashMap();
+
+    /**
+     * Flag indicating whether rollback only is allowed
+     */
+    private boolean rollbackOnly;
+
+    /**
+     * Commit this transaction. Commits all changes to items contained in the
+     * transaction. After having successfully committed the transaction, it
+     * may no longer be used.
+     *
+     * @throws org.apache.jackrabbit.core.state.TransactionException if an error occurs
+     */
+    public void commit() throws TransactionException {
+        if (rollbackOnly) {
+            throw new TransactionException("Transaction set to rollback only.");
+        }
+        notifyCommitted();
+    }
+
+    /**
+     * Set outcome of this transaction to rollback only.
+     */
+    public void setRollbackOnly() {
+        rollbackOnly = true;
+    }
+
+    /**
+     * Rollback this transaction. Rollbacks all changes to items contained in
+     * the transaction. After having successfully rolled back the transaction,
+     * it may no longer be used.
+     *
+     * @throws org.apache.jackrabbit.core.state.TransactionException if an error occurs
+     */
+    public void rollback() throws TransactionException {
+        notifyRolledBack();
+    }
+
+    /**
+     * Set an attribute on this transaction. If the value specified is
+     * <code>null</code>, it is semantically equivalent to
+     * {@link #removeAttribute}.
+     *
+     * @param name  attribute name
+     * @param value attribute value
+     */
+    public void setAttribute(String name, Object value) {
+        if (value == null) {
+            removeAttribute(name);
+        }
+        attributes.put(name, value);
+    }
+
+    /**
+     * Return an attribute value on this transaction.
+     *
+     * @param name attribute name
+     * @return attribute value, <code>null</code> if no attribute with that
+     *         name exists
+     */
+    public Object getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    /**
+     * Remove an attribute on this transaction.
+     *
+     * @param name attribute name
+     */
+    public void removeAttribute(String name) {
+        attributes.remove(name);
+    }
+
+    /**
+     * Add a transaction listener. This listener will be invoked when the
+     * transaction is either committed or rolled back.
+     *
+     * @param listener listener to add
+     */
+    public void addListener(TransactionListener listener) {
+        synchronized (listeners) {
+            listeners.add(listener);
+        }
+    }
+
+    /**
+     * Remove a transaction listener previously added with {@link #addListener}
+     *
+     * @param listener listener to remove
+     */
+    public void removeListener(TransactionListener listener) {
+        synchronized (listeners) {
+            listeners.remove(listener);
+        }
+    }
+
+    /**
+     * Notify listeners that transaction was committed. Since there is at most
+     * one commit and one rollback event to be reported, the listeners can
+     * safely be cleared at the same time.
+     */
+    private void notifyCommitted() throws TransactionException {
+        TransactionListener[] al;
+
+        synchronized (listeners) {
+            al = new TransactionListener[listeners.size()];
+            listeners.toArray(al);
+            listeners.clear();
+        }
+
+        for (int i = 0; i < al.length; i++) {
+            al[i].transactionCommitted(this);
+        }
+    }
+
+    /**
+     * Notify listeners that transaction was rolled back. Since there is at most
+     * one commit and one rollback event to be reported, the listeners can
+     * safely be cleared at the same time.
+     */
+    private void notifyRolledBack() throws TransactionException {
+        TransactionListener[] al;
+
+        synchronized (listeners) {
+            al = new TransactionListener[listeners.size()];
+            listeners.toArray(al);
+            listeners.clear();
+        }
+
+        for (int i = 0; i < al.length; i++) {
+            al[i].transactionRolledBack(this);
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionException.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionException.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionException.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.BaseException;
+
+/**
+ * TransactionException is thrown when some operation inside the transaction
+ * fails.
+ */
+public class TransactionException extends BaseException {
+
+    /**
+     * Creates an instance of this class. Takes a detail message as parameter.
+     *
+     * @param message message
+     */
+    public TransactionException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates an instance of this class. Takes a root throwable as parameter.
+     *
+     * @param rootCause root throwable
+     */
+    public TransactionException(Throwable rootCause) {
+        super(rootCause);
+    }
+
+    /**
+     * Creates an instance of this class. Takes a message and a root throwable
+     * as parameter.
+     *
+     * @param message   message
+     * @param rootCause root throwable
+     */
+    public TransactionException(String message, Throwable rootCause) {
+        super(message, rootCause);
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionListener.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionListener.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransactionListener.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.state.TransactionContext;
+import org.apache.jackrabbit.core.state.TransactionException;
+
+/**
+ * Listener on a transaction. Will receive notifications about commit
+ * and rollback actions.
+ *
+ * @see org.apache.jackrabbit.core.state.TransactionContext
+ */
+public interface TransactionListener {
+
+    /**
+     * Transaction was committed
+     *
+     * @param tx transaction that was committed
+     */
+    public void transactionCommitted(TransactionContext tx)
+            throws TransactionException;
+
+    /**
+     * Transaction was rolled back
+     *
+     * @param tx transaction that was rolled back
+     */
+    public void transactionRolledBack(TransactionContext tx)
+            throws TransactionException;
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java	Sun Jan 23 09:11:20 2005
@@ -29,7 +29,7 @@
 /**
  * <code>TransientItemStateManager</code> ...
  */
-class TransientItemStateManager extends ItemStateCache implements ItemStateProvider {
+class TransientItemStateManager extends ItemStateCache implements ItemStateManager {
 
     private static Logger log = Logger.getLogger(TransientItemStateManager.class);
 
@@ -53,57 +53,16 @@
     void dump(PrintStream ps) {
         ps.println("TransientItemStateManager (" + this + ")");
         ps.println();
-        ps.println("entries in cache:");
+        ps.print("[transient] ");
+        super.dump(ps);
         ps.println();
-        Iterator iter = keys();
-        while (iter.hasNext()) {
-            ItemId id = (ItemId) iter.next();
-            ItemState state = retrieve(id);
-            dumpItemState(id, state, ps);
-        }
-
-        ps.println();
-        ps.println("entries in attic:");
-        ps.println();
-        iter = attic.keys();
-        while (iter.hasNext()) {
-            ItemId id = (ItemId) iter.next();
-            ItemState state = attic.retrieve(id);
-            dumpItemState(id, state, ps);
-        }
-    }
-
-    private void dumpItemState(ItemId id, ItemState state, PrintStream ps) {
-        ps.print(state.isNode() ? "Node: " : "Prop: ");
-        switch (state.getStatus()) {
-            case ItemState.STATUS_EXISTING:
-                ps.print("[existing]           ");
-                break;
-            case ItemState.STATUS_EXISTING_MODIFIED:
-                ps.print("[existing, modified] ");
-                break;
-            case ItemState.STATUS_EXISTING_REMOVED:
-                ps.print("[existing, removed]  ");
-                break;
-            case ItemState.STATUS_NEW:
-                ps.print("[new]                ");
-                break;
-            case ItemState.STATUS_STALE_DESTROYED:
-                ps.print("[stale, destroyed]   ");
-                break;
-            case ItemState.STATUS_STALE_MODIFIED:
-                ps.print("[stale, modified]    ");
-                break;
-            case ItemState.STATUS_UNDEFINED:
-                ps.print("[undefined]          ");
-                break;
-        }
-        ps.println(id + " (" + state + ")");
+        ps.print("[attic]     ");
+        attic.dump(ps);
     }
 
     //----------------------------------------------------< ItemStateProvider >
     /**
-     * @see ItemStateProvider#getItemState(ItemId)
+     * @see ItemStateManager#getItemState(ItemId)
      */
     public ItemState getItemState(ItemId id)
             throws NoSuchItemStateException, ItemStateException {
@@ -116,33 +75,30 @@
     }
 
     /**
-     * @see ItemStateProvider#hasItemState(ItemId)
+     * @see ItemStateManager#hasItemState(ItemId)
      */
     public boolean hasItemState(ItemId id) {
         return isCached(id);
     }
 
     /**
-     * @see ItemStateProvider#getItemStateInAttic(ItemId)
+     * @see ItemStateManager#getNodeReferences
      */
-    public ItemState getItemStateInAttic(ItemId id)
+    public NodeReferences getNodeReferences(NodeId targetId)
             throws NoSuchItemStateException, ItemStateException {
-        ItemState state = attic.retrieve(id);
-        if (state != null) {
-            return state;
-        } else {
-            throw new NoSuchItemStateException(id.toString());
-        }
+
+        throw new ItemStateException("getNodeReferences() not implemented");
     }
 
     /**
-     * @see ItemStateProvider#hasItemStateInAttic(ItemId)
+     * @see ItemStateManager#beginUpdate
      */
-    public boolean hasItemStateInAttic(ItemId id) {
-        return attic.isCached(id);
+    public UpdateOperation beginUpdate() throws ItemStateException {
+        throw new ItemStateException("beginUpdate() not implemented");
     }
 
     //------------------< methods for listing & querying state of cache/attic >
+
     /**
      * @return
      */
@@ -204,7 +160,7 @@
             throw new ItemStateException(msg);
         }
 
-        NodeState state = new NodeState(uuid, nodeTypeName, parentUUID, initialStatus);
+        NodeState state = new NodeState(uuid, nodeTypeName, parentUUID, initialStatus, true);
         // put it in cache
         cache(state);
         return state;
@@ -226,7 +182,7 @@
             throw new ItemStateException(msg);
         }
 
-        NodeState state = new NodeState(overlayedState, initialStatus);
+        NodeState state = new NodeState(overlayedState, initialStatus, true);
         // put it in cache
         cache(state);
         return state;
@@ -249,7 +205,7 @@
             throw new ItemStateException(msg);
         }
 
-        PropertyState state = new PropertyState(propName, parentUUID, initialStatus);
+        PropertyState state = new PropertyState(propName, parentUUID, initialStatus, true);
         // put it in cache
         cache(state);
         return state;
@@ -271,7 +227,7 @@
             throw new ItemStateException(msg);
         }
 
-        PropertyState state = new PropertyState(overlayedState, initialStatus);
+        PropertyState state = new PropertyState(overlayedState, initialStatus, true);
         // put it in cache
         cache(state);
         return state;
@@ -341,11 +297,57 @@
         }
     }
 
+    /**
+     * Return the attic item state provider that holds all items
+     * moved into the attic.
+     * @return attic
+     */
+    ItemStateManager getAttic() {
+        return attic;
+    }
+
     //--------------------------------------------------------< inner classes >
-    class Attic extends ItemStateCache {
+    class Attic extends ItemStateCache implements ItemStateManager {
 
         Attic() {
             super(ReferenceMap.HARD, ReferenceMap.HARD);
+        }
+
+        /**
+         * @see ItemStateManager#getItemState
+         */
+        public ItemState getItemState(ItemId id)
+                throws NoSuchItemStateException, ItemStateException {
+
+            ItemState state = retrieve(id);
+            if (state != null) {
+                return state;
+            } else {
+                throw new NoSuchItemStateException(id.toString());
+            }
+        }
+
+        /**
+         * @see ItemStateManager#hasItemState
+         */
+        public boolean hasItemState(ItemId id) {
+            return isCached(id);
+        }
+
+        /**
+         * @see ItemStateManager#getNodeReferences
+         */
+        public NodeReferences getNodeReferences(NodeId targetId)
+                throws NoSuchItemStateException, ItemStateException {
+
+            throw new ItemStateException("getNodeReferences() not implemented");
+        }
+
+        /**
+         * @see ItemStateManager#beginUpdate
+         */
+        public UpdateOperation beginUpdate() throws ItemStateException {
+            throw new ItemStateException("beginUpdate() not implemented");
         }
     }
 }

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/UpdateOperation.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/UpdateOperation.java?view=auto&rev=126221
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/UpdateOperation.java	Sun Jan 23 09:11:20 2005
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.QName;
+
+/**
+ * An update operation started inside an <code>ItemStateManager</code>
+ */
+public interface UpdateOperation {
+
+    /**
+     * Creates a {@link NodeState} instance representing new,
+     * i.e. not yet existing state. Call {@link #store}
+     * on the returned object to make it persistent.
+     *
+     * @param uuid         node UUID
+     * @param nodeTypeName qualified node type name
+     * @param parentUUID   parent node's UUID
+     * @return a node state
+     */
+    public NodeState createNew(String uuid, QName nodeTypeName,
+                               String parentUUID);
+
+    /**
+     * Creates a {@link PropertyState} instance representing new,
+     * i.e. not yet existing state. Call {@link #store}
+     * on the returned object to make it persistent.
+     *
+     * @param propName   qualified property name
+     * @param parentUUID parent node UUID
+     * @return a property state
+     */
+    public PropertyState createNew(QName propName, String parentUUID);
+
+    /**
+     * Store an item state.
+     * @param state item state that should be stored
+      */
+    public void store(ItemState state);
+
+    /**
+     * Store a node references object
+     * @param refs node references object that should be stored
+     */
+    public void store(NodeReferences refs);
+
+    /**
+     * Destroy an item state.
+     * @param state item state that should be destroyed
+      */
+    public void destroy(ItemState state);
+
+    /**
+     * End this update operation. This will save all items
+     * added to this update operation in a single step.
+     * If this operation fails, no item will have been saved.
+     * @throws ItemStateException if the update operation failed
+     */
+    public void end() throws ItemStateException;
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/mem/InMemPersistenceManager.java	Sun Jan 23 09:11:20 2005
@@ -48,7 +48,8 @@
  * </ul>
  * <b>Please note that this class should only be used for testing purposes.</b>
  */
-public class InMemPersistenceManager implements BLOBStore, PersistenceManager {
+public class InMemPersistenceManager extends AbstractPersistenceManager
+        implements BLOBStore {
 
     private static Logger log = Logger.getLogger(InMemPersistenceManager.class);
 
@@ -377,61 +378,67 @@
     }
 
     /**
-     * @see PersistenceManager#load(PersistentNodeState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentNodeState state)
+    public synchronized NodeState load(String uuid)
             throws NoSuchItemStateException, ItemStateException {
+
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
 
-        byte[] data = (byte[]) stateStore.get(state.getId());
+        NodeId id = new NodeId(uuid);
+
+        byte[] data = (byte[]) stateStore.get(id);
         if (data == null) {
-            throw new NoSuchItemStateException(state.getId().toString());
+            throw new NoSuchItemStateException(id.toString());
         }
 
         ByteArrayInputStream in = new ByteArrayInputStream(data);
         try {
+            NodeState state = createNew(uuid, null, null);
             ObjectPersistenceManager.deserialize(state, in);
-            // there's no need to close a ByteArrayInputStream
-            //in.close();
+            return state;
         } catch (Exception e) {
-            String msg = "failed to read node state: " + state.getId();
+            String msg = "failed to read node state: " + id;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         }
     }
 
     /**
-     * @see PersistenceManager#load(PersistentPropertyState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentPropertyState state)
+    public synchronized PropertyState load(QName name, String parentUUID)
             throws NoSuchItemStateException, ItemStateException {
+
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
 
-        byte[] data = (byte[]) stateStore.get(state.getId());
+        PropertyId id = new PropertyId(parentUUID, name);
+
+        byte[] data = (byte[]) stateStore.get(id);
         if (data == null) {
-            throw new NoSuchItemStateException(state.getId().toString());
+            throw new NoSuchItemStateException(id.toString());
         }
 
         ByteArrayInputStream in = new ByteArrayInputStream(data);
         try {
+            PropertyState state = createNew(name, parentUUID);
             ObjectPersistenceManager.deserialize(state, in, this);
-            // there's no need to close a ByteArrayInputStream
-            //in.close();
+            return state;
         } catch (Exception e) {
-            String msg = "failed to read property state: " + state.getId();
+            String msg = "failed to read property state: " + id;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         }
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(PersistentNodeState state) throws ItemStateException {
+    protected void store(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -453,9 +460,9 @@
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(PersistentPropertyState state) throws ItemStateException {
+    protected void store(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -477,9 +484,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(PersistentNodeState state) throws ItemStateException {
+    protected void destroy(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -489,9 +496,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(PersistentPropertyState state) throws ItemStateException {
+    protected void destroy(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -516,35 +523,36 @@
     }
 
     /**
-     * @see PersistenceManager#load(NodeReferences)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(NodeReferences refs)
+    public synchronized NodeReferences load(NodeId targetId)
             throws NoSuchItemStateException, ItemStateException {
+
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
 
-        byte[] data = (byte[]) refsStore.get(refs.getTargetId());
+        byte[] data = (byte[]) refsStore.get(targetId);
         if (data == null) {
-            throw new NoSuchItemStateException(refs.getTargetId().toString());
+            throw new NoSuchItemStateException(targetId.toString());
         }
 
         ByteArrayInputStream in = new ByteArrayInputStream(data);
         try {
+            NodeReferences refs = new NodeReferences(targetId);
             ObjectPersistenceManager.deserialize(refs, in);
-            // there's no need to close a ByteArrayInputStream
-            //in.close();
+            return refs;
         } catch (Exception e) {
-            String msg = "failed to load references: " + refs.getTargetId();
+            String msg = "failed to load references: " + targetId;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         }
     }
 
     /**
-     * @see PersistenceManager#store(NodeReferences)
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(NodeReferences refs) throws ItemStateException {
+    protected void store(NodeReferences refs) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -566,9 +574,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy(NodeReferences)
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(NodeReferences refs) throws ItemStateException {
+    protected void destroy(NodeReferences refs) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/obj/ObjectPersistenceManager.java	Sun Jan 23 09:11:20 2005
@@ -37,7 +37,8 @@
  * and <code>NodeReferences</code> objects using a simple custom serialization
  * format.
  */
-public class ObjectPersistenceManager implements BLOBStore, PersistenceManager {
+public class ObjectPersistenceManager extends AbstractPersistenceManager
+        implements BLOBStore {
 
     private static Logger log = Logger.getLogger(ObjectPersistenceManager.class);
 
@@ -125,9 +126,9 @@
      * @param state  <code>state</code> to serialize
      * @param stream the stream where the <code>state</code> should be serialized to
      * @throws Exception if an error occurs during the serialization
-     * @see #deserialize(PersistentNodeState, InputStream)
+     * @see #deserialize(NodeState, InputStream)
      */
-    public static void serialize(PersistentNodeState state, OutputStream stream)
+    public static void serialize(NodeState state, OutputStream stream)
             throws Exception {
         DataOutputStream out = new DataOutputStream(stream);
         // uuid
@@ -173,9 +174,9 @@
      * @param state  <code>state</code> to deserialize
      * @param stream the stream where the <code>state</code> should be deserialized from
      * @throws Exception if an error occurs during the deserialization
-     * @see #serialize(PersistentNodeState, OutputStream)
+     * @see #serialize(NodeState, OutputStream)
      */
-    public static void deserialize(PersistentNodeState state, InputStream stream)
+    public static void deserialize(NodeState state, InputStream stream)
             throws Exception {
         DataInputStream in = new DataInputStream(stream);
         // check uuid
@@ -239,9 +240,9 @@
      * @param stream    the stream where the <code>state</code> should be serialized to
      * @param blobStore handler for blob data
      * @throws Exception if an error occurs during the serialization
-     * @see #deserialize(PersistentPropertyState, InputStream, BLOBStore)
+     * @see #deserialize(PropertyState, InputStream, BLOBStore)
      */
-    public static void serialize(PersistentPropertyState state,
+    public static void serialize(PropertyState state,
                                  OutputStream stream,
                                  BLOBStore blobStore)
             throws Exception {
@@ -295,9 +296,9 @@
      * @param stream    the stream where the <code>state</code> should be deserialized from
      * @param blobStore handler for blob data
      * @throws Exception if an error occurs during the deserialization
-     * @see #serialize(PersistentPropertyState, OutputStream, BLOBStore)
+     * @see #serialize(PropertyState, OutputStream, BLOBStore)
      */
-    public static void deserialize(PersistentPropertyState state,
+    public static void deserialize(PropertyState state,
                                    InputStream stream,
                                    BLOBStore blobStore)
             throws Exception {
@@ -463,22 +464,22 @@
     }
 
     /**
-     * @see PersistenceManager#load(PersistentNodeState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentNodeState state)
+    public synchronized NodeState load(String uuid)
             throws NoSuchItemStateException, ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
 
-        String nodeFilePath = buildNodeFilePath(state.getUUID());
+        String nodeFilePath = buildNodeFilePath(uuid);
 
         try {
             if (!itemStateFS.isFile(nodeFilePath)) {
-                throw new NoSuchItemStateException(state.getId().toString());
+                throw new NoSuchItemStateException(nodeFilePath);
             }
         } catch (FileSystemException fse) {
-            String msg = "failed to read node state: " + state.getId();
+            String msg = "failed to read node state: " + nodeFilePath;
             log.error(msg, fse);
             throw new ItemStateException(msg, fse);
         }
@@ -487,39 +488,40 @@
             BufferedInputStream in =
                     new BufferedInputStream(itemStateFS.getInputStream(nodeFilePath));
             try {
+                NodeState state = createNew(uuid, null, null);
                 deserialize(state, in);
-                return;
+                return state;
             } catch (Exception e) {
-                String msg = "failed to read node state: " + state.getId();
+                String msg = "failed to read node state: " + uuid;
                 log.error(msg, e);
                 throw new ItemStateException(msg, e);
             } finally {
                 in.close();
             }
         } catch (Exception e) {
-            String msg = "failed to read node state: " + state.getId();
+            String msg = "failed to read node state: " + nodeFilePath;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         }
     }
 
     /**
-     * @see PersistenceManager#load(PersistentPropertyState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentPropertyState state)
+    public synchronized PropertyState load(QName name, String parentUUID)
             throws NoSuchItemStateException, ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
 
-        String propFilePath = buildPropFilePath(state.getParentUUID(), state.getName());
+        String propFilePath = buildPropFilePath(parentUUID, name);
 
         try {
             if (!itemStateFS.isFile(propFilePath)) {
-                throw new NoSuchItemStateException(state.getId().toString());
+                throw new NoSuchItemStateException(propFilePath);
             }
         } catch (FileSystemException fse) {
-            String msg = "failed to read property state: " + state.getId();
+            String msg = "failed to read property state: " + propFilePath;
             log.error(msg, fse);
             throw new ItemStateException(msg, fse);
         }
@@ -528,22 +530,61 @@
             BufferedInputStream in =
                     new BufferedInputStream(itemStateFS.getInputStream(propFilePath));
             try {
+                PropertyState state = createNew(name, parentUUID);
                 deserialize(state, in, this);
-                return;
+                return state;
             } finally {
                 in.close();
             }
         } catch (Exception e) {
-            String msg = "failed to read property state: " + state.getId();
+            String msg = "failed to read property state: " + propFilePath;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         }
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see PersistenceManager#load
      */
-    public synchronized void store(PersistentNodeState state) throws ItemStateException {
+    public synchronized NodeReferences load(NodeId targetId)
+            throws NoSuchItemStateException, ItemStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+
+        String refsFilePath = buildNodeReferencesFilePath(targetId.getUUID());
+
+        try {
+            if (!itemStateFS.isFile(refsFilePath)) {
+                throw new NoSuchItemStateException(targetId.toString());
+            }
+        } catch (FileSystemException fse) {
+            String msg = "failed to load references: " + targetId;
+            log.error(msg, fse);
+            throw new ItemStateException(msg, fse);
+        }
+
+        try {
+            BufferedInputStream in =
+                    new BufferedInputStream(itemStateFS.getInputStream(refsFilePath));
+            try {
+                NodeReferences refs = new NodeReferences(targetId);
+                deserialize(refs, in);
+                return refs;
+            } finally {
+                in.close();
+            }
+        } catch (Exception e) {
+            String msg = "failed to load references: " + targetId;
+            log.error(msg, e);
+            throw new ItemStateException(msg, e);
+        }
+    }
+
+    /**
+     * @see AbstractPersistenceManager#store
+     */
+    protected void store(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -569,9 +610,9 @@
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(PersistentPropertyState state) throws ItemStateException {
+    protected void store(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -596,9 +637,35 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void destroy(PersistentNodeState state) throws ItemStateException {
+    protected void store(NodeReferences refs) throws ItemStateException {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+
+        String uuid = refs.getTargetId().getUUID();
+        String refsFilePath = buildNodeReferencesFilePath(uuid);
+        FileSystemResource refsFile = new FileSystemResource(itemStateFS, refsFilePath);
+        try {
+            refsFile.makeParentDirs();
+            OutputStream out = new BufferedOutputStream(refsFile.getOutputStream());
+            try {
+                serialize(refs, out);
+            } finally {
+                out.close();
+            }
+        } catch (Exception e) {
+            String msg = "failed to store references: " + uuid;
+            log.error(msg, e);
+            throw new ItemStateException(msg, e);
+        }
+    }
+
+    /**
+     * @see AbstractPersistenceManager#destroy
+     */
+    protected void destroy(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -619,9 +686,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(PersistentPropertyState state) throws ItemStateException {
+    protected void destroy(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -656,72 +723,9 @@
     }
 
     /**
-     * @see PersistenceManager#load(NodeReferences)
-     */
-    public synchronized void load(NodeReferences refs)
-            throws NoSuchItemStateException, ItemStateException {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        String refsFilePath = buildNodeReferencesFilePath(refs.getTargetId().getUUID());
-
-        try {
-            if (!itemStateFS.isFile(refsFilePath)) {
-                throw new NoSuchItemStateException(refs.getTargetId().toString());
-            }
-        } catch (FileSystemException fse) {
-            String msg = "failed to load references: " + refs.getTargetId();
-            log.error(msg, fse);
-            throw new ItemStateException(msg, fse);
-        }
-
-        try {
-            BufferedInputStream in =
-                    new BufferedInputStream(itemStateFS.getInputStream(refsFilePath));
-            try {
-                deserialize(refs, in);
-                return;
-            } finally {
-                in.close();
-            }
-        } catch (Exception e) {
-            String msg = "failed to load references: " + refs.getTargetId();
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        }
-    }
-
-    /**
-     * @see PersistenceManager#store(NodeReferences)
-     */
-    public synchronized void store(NodeReferences refs) throws ItemStateException {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        String uuid = refs.getTargetId().getUUID();
-        String refsFilePath = buildNodeReferencesFilePath(uuid);
-        FileSystemResource refsFile = new FileSystemResource(itemStateFS, refsFilePath);
-        try {
-            refsFile.makeParentDirs();
-            OutputStream out = new BufferedOutputStream(refsFile.getOutputStream());
-            try {
-                serialize(refs, out);
-            } finally {
-                out.close();
-            }
-        } catch (Exception e) {
-            String msg = "failed to store references: " + uuid;
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        }
-    }
-
-    /**
-     * @see PersistenceManager#destroy(NodeReferences)
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(NodeReferences refs) throws ItemStateException {
+    protected void destroy(NodeReferences refs) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java	Sun Jan 23 09:11:20 2005
@@ -41,7 +41,7 @@
  * <code>PersistenceManager</code> that persists <code>ItemState</code>
  * and <code>NodeReferences</code> objects in XML format.
  */
-public class XMLPersistenceManager implements PersistenceManager {
+public class XMLPersistenceManager extends AbstractPersistenceManager {
 
     private static Logger log = Logger.getLogger(XMLPersistenceManager.class);
 
@@ -157,7 +157,7 @@
         return buildNodeFolderPath(uuid) + "/" + NODEREFSFILENAME;
     }
 
-    private void readState(Element nodeElement, PersistentNodeState state)
+    private void readState(Element nodeElement, NodeState state)
             throws ItemStateException {
         // first do some paranoid sanity checks
         if (!nodeElement.getName().equals(NODE_ELEMENT)) {
@@ -235,7 +235,7 @@
         }
     }
 
-    private void readState(Element propElement, PersistentPropertyState state)
+    private void readState(Element propElement, PropertyState state)
             throws ItemStateException {
         // first do some paranoid sanity checks
         if (!propElement.getName().equals(PROPERTY_ELEMENT)) {
@@ -392,10 +392,12 @@
         }
     }
 
+
+
     /**
-     * @see PersistenceManager#load(PersistentNodeState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentNodeState state)
+    public synchronized NodeState load(String uuid)
             throws NoSuchItemStateException, ItemStateException {
 
         if (!initialized) {
@@ -403,7 +405,6 @@
         }
 
         Exception e = null;
-        String uuid = state.getUUID();
         String nodeFilePath = buildNodeFilePath(uuid);
 
         try {
@@ -416,10 +417,11 @@
                 SAXBuilder builder = new SAXBuilder();
                 Element rootElement = builder.build(in).getRootElement();
                 String ntName = rootElement.getAttributeValue(NODETYPE_ATTRIBUTE);
-                state.setNodeTypeName(QName.valueOf(ntName));
 
+                NodeState state = createNew(uuid, null, null);
+                state.setNodeTypeName(QName.valueOf(ntName));
                 readState(rootElement, state);
-                return;
+                return state;
             } finally {
                 in.close();
             }
@@ -439,9 +441,9 @@
     }
 
     /**
-     * @see PersistenceManager#load(PersistentPropertyState)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(PersistentPropertyState state)
+    public synchronized PropertyState load(QName name, String parentUUID)
             throws NoSuchItemStateException, ItemStateException {
 
         if (!initialized) {
@@ -449,21 +451,20 @@
         }
 
         Exception e = null;
-        String parentUUID = state.getParentUUID();
-        QName propName = state.getName();
-        String propFilePath = buildPropFilePath(parentUUID, propName);
+        String propFilePath = buildPropFilePath(parentUUID, name);
 
         try {
             if (!itemStateStore.isFile(propFilePath)) {
-                throw new NoSuchItemStateException(parentUUID + "/" + propName);
+                throw new NoSuchItemStateException(parentUUID + "/" + name);
             }
             InputStream in = itemStateStore.getInputStream(propFilePath);
             try {
                 SAXBuilder builder = new SAXBuilder();
                 Element rootElement = builder.build(in).getRootElement();
 
+                PropertyState state = createNew(name, parentUUID);
                 readState(rootElement, state);
-                return;
+                return state;
             } finally {
                 in.close();
             }
@@ -477,15 +478,15 @@
             e = fse;
             // fall through
         }
-        String msg = "failed to read property state: " + parentUUID + "/" + propName;
+        String msg = "failed to read property state: " + parentUUID + "/" + name;
         log.error(msg, e);
         throw new ItemStateException(msg, e);
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(PersistentNodeState state) throws ItemStateException {
+    protected void store(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -568,9 +569,9 @@
     }
 
     /**
-     * @see PersistenceManager#store
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(PersistentPropertyState state) throws ItemStateException {
+    protected void store(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -682,9 +683,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(PersistentNodeState state) throws ItemStateException {
+    protected void destroy(NodeState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -705,9 +706,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(PersistentPropertyState state) throws ItemStateException {
+    protected void destroy(PropertyState state) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -742,9 +743,9 @@
     }
 
     /**
-     * @see PersistenceManager#load(NodeReferences)
+     * @see PersistenceManager#load
      */
-    public synchronized void load(NodeReferences refs)
+    public synchronized NodeReferences load(NodeId targetId)
             throws NoSuchItemStateException, ItemStateException {
 
         if (!initialized) {
@@ -752,14 +753,13 @@
         }
 
         Exception e = null;
-        String uuid = refs.getTargetId().getUUID();
+        String uuid = targetId.getUUID();
 
         String refsFilePath = buildNodeReferencesFilePath(uuid);
         try {
             if (!itemStateStore.isFile(refsFilePath)) {
                 throw new NoSuchItemStateException(uuid);
             }
-            refs.clearAllReferences();
 
             InputStream in = itemStateStore.getInputStream(refsFilePath);
 
@@ -767,8 +767,9 @@
                 SAXBuilder builder = new SAXBuilder();
                 Element rootElement = builder.build(in).getRootElement();
 
+                NodeReferences refs = new NodeReferences(targetId);
                 readState(rootElement, refs);
-                return;
+                return refs;
             } finally {
                 in.close();
             }
@@ -788,9 +789,9 @@
     }
 
     /**
-     * @see PersistenceManager#store(NodeReferences)
+     * @see AbstractPersistenceManager#store
      */
-    public synchronized void store(NodeReferences refs) throws ItemStateException {
+    protected void store(NodeReferences refs) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }
@@ -834,9 +835,9 @@
     }
 
     /**
-     * @see PersistenceManager#destroy(NodeReferences)
+     * @see AbstractPersistenceManager#destroy
      */
-    public synchronized void destroy(NodeReferences refs) throws ItemStateException {
+    protected void destroy(NodeReferences refs) throws ItemStateException {
         if (!initialized) {
             throw new IllegalStateException("not initialized");
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java	Sun Jan 23 09:11:20 2005
@@ -18,16 +18,14 @@
 
 import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.version.VersionManager;
-import org.apache.jackrabbit.core.version.InternalVersionHistory;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.virtual.VirtualNodeState;
 
 import javax.jcr.RepositoryException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * The history root node state represents the root node of all version histories.
@@ -51,6 +49,7 @@
 
     /**
      * creates a new history root state
+     *
      * @param stateMgr
      * @param parentUUID
      * @param uuid
@@ -58,8 +57,8 @@
      */
     protected HistoryRootNodeState(VersionItemStateProvider stateMgr,
                                    VersionManager vm,
-                                String parentUUID,
-                                String uuid) throws RepositoryException {
+                                   String parentUUID,
+                                   String uuid) throws RepositoryException {
         super(stateMgr, parentUUID, uuid, NodeTypeRegistry.NT_UNSTRUCTURED, new QName[0]);
         this.vm = vm;
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java	Sun Jan 23 09:11:20 2005
@@ -26,6 +26,7 @@
 
     /**
      * returns the name of the node.
+     *
      * @return the name of the node.
      */
     public QName getName();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java	Sun Jan 23 09:11:20 2005
@@ -16,8 +16,9 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.state.PropertyState;
+
 import javax.jcr.version.VersionException;
 
 /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java	Sun Jan 23 09:11:20 2005
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.version;
 
 import org.apache.jackrabbit.core.QName;
+
 import javax.jcr.version.Version;
 import java.util.Calendar;
 
@@ -42,18 +43,21 @@
 
     /**
      * Aequivalent to {@link javax.jcr.version.Version#getCreated()}
+     *
      * @see Version#getCreated()
      */
     public Calendar getCreated();
 
     /**
      * Aequivalent to {@link javax.jcr.version.Version#getSuccessors()}}
+     *
      * @see Version#getSuccessors()
      */
     public InternalVersion[] getSuccessors();
 
     /**
      * Aequivalent to {@link javax.jcr.version.Version#getPredecessors()}}
+     *
      * @see javax.jcr.version.Version#getPredecessors()
      */
     public InternalVersion[] getPredecessors();
@@ -86,6 +90,7 @@
 
     /**
      * Checks, if this version has the given label assosiated
+     *
      * @param label the label to check.
      * @return <code>true</code> if the label is assigned to this version;
      *         <code>false</code> otherwise.
@@ -94,6 +99,7 @@
 
     /**
      * returns the labels that are assigned to this version
+     *
      * @return a string array of labels.
      */
     public String[] getLabels();

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -29,12 +29,14 @@
 
     /**
      * Aequivalalent to {@link VersionHistory#getRootVersion()}.
+     *
      * @see VersionHistory#getRootVersion()
      */
     public InternalVersion getRootVersion();
 
     /**
      * Aequivalent to {@link VersionHistory#getVersion(java.lang.String)}.
+     *
      * @see VersionHistory#getVersion(java.lang.String)
      */
     public InternalVersion getVersion(QName versionName) throws VersionException;
@@ -95,9 +97,9 @@
      * label is removed from the previously assigned version and added to the
      * specified one.
      *
-     * @param name the name of the version
+     * @param name  the name of the version
      * @param label the label to assgign
-     * @param move flag what to do by collisions
+     * @param move  flag what to do by collisions
      * @return the version that was previously assigned by this label or <code>null</code>.
      * @throws VersionException
      */

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java	Sun Jan 23 09:11:20 2005
@@ -26,12 +26,14 @@
 
     /**
      * Returns the external id of this item
+     *
      * @return
      */
     public String getId();
 
     /**
      * returns the parent version item or null
+     *
      * @return
      */
     public InternalVersionItem getParent();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java	Sun Jan 23 09:11:20 2005
@@ -16,11 +16,11 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.NodeImpl;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
-import java.util.*;
+import java.util.Iterator;
 
 /**
  * This interface defines the access to the persistence layer of the
@@ -103,6 +103,7 @@
 
     /**
      * checks, if the item with the given external id exists
+     *
      * @param externalId
      * @return
      */
@@ -110,6 +111,7 @@
 
     /**
      * returns the item referred by the external id
+     *
      * @param externalId
      * @return
      * @throws RepositoryException
@@ -119,6 +121,7 @@
 
     /**
      * returns the item referred by the internal id
+     *
      * @param internalId
      * @return
      * @throws RepositoryException

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -51,9 +51,9 @@
      * @throws RepositoryException
      */
     public VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
-                                 NodeState state, NodeDef definition,
-                                 ItemLifeCycleListener[] listeners,
-                                 InternalVersionHistory history) throws RepositoryException {
+                              NodeState state, NodeDef definition,
+                              ItemLifeCycleListener[] listeners,
+                              InternalVersionHistory history) throws RepositoryException {
         super(itemMgr, session, id, state, definition, listeners);
         this.history = history;
     }

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -17,8 +17,6 @@
 package org.apache.jackrabbit.core.version;
 
 import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.version.InternalVersionHistory;
-import org.apache.jackrabbit.core.version.InternalVersion;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.virtual.VirtualNodeState;
 
@@ -39,14 +37,15 @@
 
     /**
      * Creates a new versiom history node state
+     *
      * @param vm
      * @param vh
      * @param parentUUID
      * @throws RepositoryException
      */
     protected VersionHistoryNodeState(VersionItemStateProvider vm,
-                                   InternalVersionHistory vh,
-                                   String parentUUID)
+                                      InternalVersionHistory vh,
+                                      String parentUUID)
             throws RepositoryException {
         super(vm, parentUUID, vh.getId(), NodeTypeRegistry.NT_VERSION_HISTORY, new QName[0]);
         this.vh = vh;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java	Sun Jan 23 09:11:20 2005
@@ -49,8 +49,8 @@
      * @throws RepositoryException
      */
     public VersionImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
-                          NodeState state, NodeDef definition,
-                          ItemLifeCycleListener[] listeners, InternalVersion version)
+                       NodeState state, NodeDef definition,
+                       ItemLifeCycleListener[] listeners, InternalVersion version)
             throws RepositoryException {
         super(itemMgr, session, id, state, definition, listeners);
         this.version = version;

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -16,19 +16,20 @@
  */
 package org.apache.jackrabbit.core.version;
 
+import org.apache.commons.collections.ReferenceMap;
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.jackrabbit.core.nodetype.*;
 import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.virtual.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
+import org.apache.jackrabbit.core.virtual.VirtualNodeState;
+import org.apache.jackrabbit.core.virtual.VirtualPropertyState;
 import org.apache.log4j.Logger;
-import org.apache.commons.collections.ReferenceMap;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.PropertyType;
-import javax.jcr.nodetype.ConstraintViolationException;
-import java.util.Map;
+import javax.jcr.RepositoryException;
 import java.util.HashSet;
+import java.util.Map;
 
 /**
  * This Class implements a virtual item state provider, in order to expose the
@@ -70,12 +71,13 @@
 
     /**
      * creates a new version item state provide
+     *
      * @param vMgr
      * @param rootId
      * @param parentId
      * @throws RepositoryException
      */
-    public VersionItemStateProvider(VersionManager vMgr, NodeTypeManagerImpl ntMgr, String rootId, String parentId)  throws RepositoryException {
+    public VersionItemStateProvider(VersionManager vMgr, NodeTypeManagerImpl ntMgr, String rootId, String parentId) throws RepositoryException {
         this.vMgr = vMgr;
         this.ntMgr = ntMgr;
         NDEF_UNSTRUCTURED = new NodeDefId(getNodeTypeManager().getNodeType(NodeTypeRegistry.NT_UNSTRUCTURED).getApplicableChildNodeDef(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_UNSTRUCTURED).unwrap());
@@ -86,10 +88,9 @@
         this.root.setDefinitionId(NDEF_UNSTRUCTURED);
     }
 
-    //--------------------------------------------------< ItemStateProvider >---
-
+    //-----------------------------------------------------< ItemStateManager >
     /**
-     * @see ItemStateProvider#hasItemState(org.apache.jackrabbit.core.ItemId)
+     * @see ItemStateManager#hasItemState(org.apache.jackrabbit.core.ItemId)
      */
     public boolean hasItemState(ItemId id) {
         if (id instanceof NodeId) {
@@ -100,7 +101,7 @@
     }
 
     /**
-     * @see ItemStateProvider#getItemState(org.apache.jackrabbit.core.ItemId)
+     * @see ItemStateManager#getItemState(ItemId)
      */
     public ItemState getItemState(ItemId id)
             throws NoSuchItemStateException, ItemStateException {
@@ -113,36 +114,32 @@
     }
 
     /**
-     * virtual item state provider do not have attics.
-     *
-     * @throws NoSuchItemStateException always
+     * @see ItemStateManager#getNodeReferences(NodeId)
      */
-    public ItemState getItemStateInAttic(ItemId id) throws NoSuchItemStateException {
-        // never has states in attic
-        throw new NoSuchItemStateException(id.toString());
+    public NodeReferences getNodeReferences(NodeId targetId)
+            throws NoSuchItemStateException, ItemStateException {
+
+        //@todo return node references
+        throw new NoSuchItemStateException(targetId.getUUID());
     }
 
     /**
-     * virtual item state provider do not have attics.
-     *
-     * @return <code>false</code>
+     * @see ItemStateManager#beginUpdate
      */
-    public boolean hasItemStateInAttic(ItemId id) {
-        // never has states in attic
-        return false;
+    public UpdateOperation beginUpdate() throws ItemStateException {
+        throw new ItemStateException("Update not available");
     }
 
     //-------------------------------------------< VirtualItemStateProvider >---
-
     /**
-     * @see VirtualItemStateProvider#isVirtualRoot(org.apache.jackrabbit.core.ItemId)
+     * @see VirtualItemStateProvider#isVirtualRoot(ItemId)
      */
     public boolean isVirtualRoot(ItemId id) {
         return id.equals(root.getId());
     }
 
     /**
-     * @see org.apache.jackrabbit.core.virtual.VirtualItemStateProvider#getVirtualRootId()
+     * @see VirtualItemStateProvider#getVirtualRootId()
      */
     public NodeId getVirtualRootId() {
         return (NodeId) root.getId();
@@ -162,7 +159,7 @@
     }
 
     /**
-     * @see VirtualItemStateProvider#getNodeState(org.apache.jackrabbit.core.NodeId)
+     * @see VirtualItemStateProvider#getNodeState(NodeId)
      */
     public VirtualNodeState getNodeState(NodeId id)
             throws NoSuchItemStateException, ItemStateException {
@@ -174,7 +171,7 @@
 
         // check cache
         VirtualNodeState state = (VirtualNodeState) nodes.get(id);
-        if (state==null) {
+        if (state == null) {
             try {
                 InternalVersionItem vi = vMgr.getItem(id.getUUID());
                 if (vi instanceof InternalVersionHistory) {
@@ -197,8 +194,7 @@
                 } else if (vi instanceof InternalFrozenNode) {
                     InternalFrozenNode fn = (InternalFrozenNode) vi;
                     VirtualNodeState parent = getNodeState(new NodeId(fn.getParent().getId()));
-                    state = createNodeState(
-                            parent,
+                    state = createNodeState(parent,
                             VersionManager.NODENAME_FROZEN,
                             id.getUUID(),
                             fn.getFrozenPrimaryType());
@@ -207,8 +203,7 @@
                 } else if (vi instanceof InternalFrozenVersionHistory) {
                     InternalFrozenVersionHistory fn = (InternalFrozenVersionHistory) vi;
                     VirtualNodeState parent = getNodeState(new NodeId(fn.getParent().getId()));
-                    state = createNodeState(
-                            parent,
+                    state = createNodeState(parent,
                             fn.getName(),
                             id.getUUID(),
                             NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
@@ -231,7 +226,7 @@
     }
 
     /**
-     * @see VirtualItemStateProvider#hasPropertyState(org.apache.jackrabbit.core.PropertyId)
+     * @see VirtualItemStateProvider#hasPropertyState(PropertyId)
      */
     public boolean hasPropertyState(PropertyId id) {
 
@@ -250,7 +245,7 @@
     }
 
     /**
-     * @see VirtualItemStateProvider#getPropertyState(org.apache.jackrabbit.core.PropertyId)
+     * @see VirtualItemStateProvider#getPropertyState(PropertyId)
      */
     public VirtualPropertyState getPropertyState(PropertyId id)
             throws NoSuchItemStateException, ItemStateException {
@@ -266,7 +261,7 @@
     }
 
     /**
-     * @see VirtualItemStateProvider#createPropertyState(org.apache.jackrabbit.core.virtual.VirtualNodeState, org.apache.jackrabbit.core.QName, int, boolean)
+     * @see VirtualItemStateProvider#createPropertyState(VirtualNodeState, QName, int, boolean)
      */
     public VirtualPropertyState createPropertyState(VirtualNodeState parent,
                                                     QName name, int type,
@@ -281,7 +276,7 @@
     }
 
     /**
-     * @see VirtualItemStateProvider#createNodeState(org.apache.jackrabbit.core.virtual.VirtualNodeState, org.apache.jackrabbit.core.QName, String, org.apache.jackrabbit.core.QName)
+     * @see VirtualItemStateProvider#createNodeState(VirtualNodeState, QName, String, QName)
      */
     public VirtualNodeState createNodeState(VirtualNodeState parent, QName name,
                                             String uuid, QName nodeTypeName)
@@ -319,6 +314,7 @@
 
     /**
      * returns the node type manager
+     *
      * @return
      */
     private NodeTypeManagerImpl getNodeTypeManager() {
@@ -326,7 +322,8 @@
     }
 
     /**
-     * mapps a frozen node
+     * maps a frozen node
+     *
      * @param state
      * @param node
      * @return
@@ -338,13 +335,13 @@
 
         // map native stuff
         state.setMixinNodeTypes(node.getFrozenMixinTypes());
-        if (node.getFrozenUUID()!=null) {
+        if (node.getFrozenUUID() != null) {
             state.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(node.getFrozenUUID()));
         }
 
         // map properties
         PropertyState[] props = node.getFrozenProperties();
-        for (int i=0; i<props.length; i++) {
+        for (int i = 0; i < props.length; i++) {
             if (props[i].isMultiValued()) {
                 state.setPropertyValues(props[i].getName(), props[i].getType(), props[i].getValues());
             } else {
@@ -353,7 +350,7 @@
         }
         // map child nodes
         InternalFreeze[] nodes = node.getFrozenChildNodes();
-        for (int i=0; i<nodes.length; i++) {
+        for (int i = 0; i < nodes.length; i++) {
             state.addChildNodeEntry(nodes[i].getName(), nodes[i].getId());
         }
         return state;

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -16,8 +16,11 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
 
 import javax.jcr.RepositoryException;
@@ -91,7 +94,7 @@
      * @return
      */
     public VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session,
-                                                                ItemStateProvider base);
+                                                                ItemStateManager base);
 
     /**
      * Creates a new version history. This action is needed either when creating
@@ -168,6 +171,7 @@
 
     /**
      * checks, if the node with the given id exists
+     *
      * @param id
      * @return
      */
@@ -175,6 +179,7 @@
 
     /**
      * Returns the version item with the given id
+     *
      * @param id
      * @return
      * @throws RepositoryException

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java	Sun Jan 23 09:11:20 2005
@@ -16,18 +16,18 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import org.apache.log4j.Logger;
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
+import org.apache.log4j.Logger;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.version.VersionHistory;
 import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
 import java.util.Iterator;
 
 /**
@@ -58,6 +58,7 @@
 
     /**
      * Creates a bew vesuion manager
+     *
      * @param vMgr
      */
     public VersionManagerImpl(PersistentVersionManager vMgr) {
@@ -71,7 +72,7 @@
      * @param base
      * @return
      */
-    public synchronized VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session, ItemStateProvider base) {
+    public synchronized VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session, ItemStateManager base) {
         if (virtProvider == null) {
             try {
                 // init the definition id mgr
@@ -99,6 +100,7 @@
 
     /**
      * returns the node type manager
+     *
      * @return
      */
     NodeTypeManagerImpl getNodeTypeManager() {
@@ -183,6 +185,7 @@
 
     /**
      * checks, if the node with the given id exists
+     *
      * @param id
      * @return
      */
@@ -192,6 +195,7 @@
 
     /**
      * Returns the version item with the given id
+     *
      * @param id
      * @return
      * @throws RepositoryException

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -18,9 +18,6 @@
 
 import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.version.VersionItemStateProvider;
-import org.apache.jackrabbit.core.version.InternalVersion;
-import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.util.uuid.UUID;
@@ -43,13 +40,14 @@
 
     /**
      * Creates a new version node state
+     *
      * @param vm
      * @param v
      * @param parentUUID
      * @throws RepositoryException
      */
     protected VersionNodeState(VersionItemStateProvider vm, InternalVersion v,
-                            String parentUUID)
+                               String parentUUID)
             throws RepositoryException {
         super(vm, parentUUID, v.getId(), NodeTypeRegistry.NT_VERSION, new QName[0]);
         this.v = v;
@@ -66,7 +64,7 @@
     public VirtualPropertyState getProperty(QName name)
             throws NoSuchItemStateException {
         VirtualPropertyState state = super.getProperty(name);
-        if (state!=null) {
+        if (state != null) {
             if (name.equals(VersionManager.PROPNAME_VERSION_LABELS)) {
                 state.setValues(InternalValue.create(v.getLabels()));
             } else if (name.equals(VersionManager.PROPNAME_PREDECESSORS)) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java	Sun Jan 23 09:11:20 2005
@@ -16,24 +16,24 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.jackrabbit.core.version.*;
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.version.*;
 
-import javax.jcr.RepositoryException;
-import javax.jcr.PropertyType;
-import javax.jcr.PropertyIterator;
 import javax.jcr.NodeIterator;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.version.OnParentVersionAction;
 import javax.jcr.version.VersionException;
-import javax.jcr.nodetype.NodeType;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  *
@@ -77,9 +77,9 @@
      * @throws javax.jcr.RepositoryException
      */
     protected InternalFrozenNodeImpl(PersistentVersionManager vMgr,
-                                 PersistentNode node,
-                                 String id,
-                                 InternalVersionItem parent) throws RepositoryException {
+                                     PersistentNode node,
+                                     String id,
+                                     InternalVersionItem parent) throws RepositoryException {
         super(vMgr, parent);
         this.node = node;
         this.id = id;
@@ -173,7 +173,7 @@
             List entries = node.getState().getChildNodeEntries();
             InternalFreeze[] freezes = new InternalFreeze[entries.size()];
             Iterator iter = entries.iterator();
-            int i=0;
+            int i = 0;
             while (iter.hasNext()) {
                 NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
                 freezes[i++] = (InternalFreeze) getVersionManager().getItemByInternal(entry.getUUID());

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java	Sun Jan 23 09:11:20 2005
@@ -16,8 +16,8 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.jackrabbit.core.version.*;
 import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.version.*;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.version.VersionException;

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -16,23 +16,23 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.jackrabbit.core.version.*;
-import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.InternalValue;
-import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.util.Text;
 import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.version.*;
 import org.apache.log4j.Logger;
 
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
-import javax.jcr.PropertyType;
 import javax.jcr.version.VersionException;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Calendar;
 
 /**
  *
@@ -172,7 +172,6 @@
     }
 
     /**
-     *
      * @param versionName
      * @return
      */

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -16,18 +16,18 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.jackrabbit.core.version.*;
-import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.InternalValue;
+import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.version.*;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.HashSet;
-import java.util.Arrays;
 
 /**
  *
@@ -142,7 +142,7 @@
         // get frozen node
         try {
             NodeState.ChildNodeEntry entry = node.getState().getChildNodeEntry(VersionManager.NODENAME_FROZEN, 1);
-            if (entry==null) {
+            if (entry == null) {
                 throw new IllegalStateException("version has no frozen node: " + getId());
             }
             return (InternalFrozenNode) getVersionManager().getItemByInternal(entry.getUUID());

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java	Sun Jan 23 09:11:20 2005
@@ -16,8 +16,8 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.jackrabbit.core.version.PersistentVersionManager;
 import org.apache.jackrabbit.core.version.InternalVersionItem;
+import org.apache.jackrabbit.core.version.PersistentVersionManager;
 
 /**
  *
@@ -31,6 +31,7 @@
 
     /**
      * Creates a new Internal version item impl
+     *
      * @param vMgr
      */
     protected InternalVersionItemImpl(PersistentVersionManager vMgr) {
@@ -39,6 +40,7 @@
 
     /**
      * Returns the persistent version manager for this item
+     *
      * @return
      */
     protected PersistentVersionManager getVersionManager() {
@@ -47,12 +49,14 @@
 
     /**
      * Returns the internal persistent id of this item
+     *
      * @return
      */
     protected abstract String getPersistentId();
 
     /**
      * Returns the external id of this item
+     *
      * @return
      */
     public abstract String getId();
@@ -60,6 +64,7 @@
 
     /**
      * returns the parent version item or null
+     *
      * @return
      */
     public abstract InternalVersionItem getParent();

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&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java&r2=126221
==============================================================================
--- 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	Sun Jan 23 09:11:20 2005
@@ -16,25 +16,30 @@
  */
 package org.apache.jackrabbit.core.version.persistence;
 
-import org.apache.log4j.Logger;
-import org.apache.jackrabbit.core.version.*;
+import org.apache.commons.collections.ReferenceMap;
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.nodetype.NodeDefId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.state.*;
-import org.apache.commons.collections.ReferenceMap;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.UpdateOperation;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.version.*;
+import org.apache.log4j.Logger;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
-import java.util.Iterator;
 
 /**
  * This Class implements the persistent part of the versioning. the
  * current implementation uses the 'normal' repository content as storage.
- * <p>
+ * <p/>
  * although the nodes need to be mapped again virtually in the real content,
  * the persistent nodes use a different structure as exposed later.
  * each versioning element (version history, version, freezes) is stored in a
@@ -42,10 +47,10 @@
  * a persistentnodestate that represents a version, is the UUID of that version.
  * the hierarchy is somewhat similar, thus histories contain versions, contain
  * frozen nodes, etc.
- * <p>
+ * <p/>
  * on startup, the entire structure is traversed, in order to get a mapping
  * from real to persistent uuids.
- * <p>
+ * <p/>
  * todo: the persistence is not synchronized yet and could lead to multi-threading issues
  */
 public class NativePVM implements PersistentVersionManager {
@@ -118,7 +123,12 @@
     /**
      * the state manager for the version storage
      */
-    private PersistentItemStateProvider stateMgr;
+    private ItemStateManager stateMgr;
+
+    /**
+     * the nodetype manager for the version storage
+     */
+    private NodeTypeManagerImpl ntMgr;
 
     /**
      * mapping from virtual uuids to persistent ids of the persistent nodes
@@ -130,7 +140,7 @@
      * mapping from virtual uuids to persistent ids of the persistent nodes
      * key=internalId, value=PersistentId
      */
-    private HashMap idsByInternal= new HashMap();
+    private HashMap idsByInternal = new HashMap();
 
     /**
      * list of histories for fast retrieval
@@ -145,15 +155,40 @@
     /**
      * Creates a new PersistentVersionManager.
      *
-     * @param pMgr
-     * @param ntReg
+     * @param session
      * @throws javax.jcr.RepositoryException
      */
-    public NativePVM(PersistenceManager pMgr, NodeTypeRegistry ntReg) throws RepositoryException {
+    public NativePVM(SessionImpl session) throws RepositoryException {
+        this.stateMgr = ((WorkspaceImpl) session.getWorkspace()).getItemStateManager();
+        this.ntMgr = session.getNodeTypeManager();
+
         try {
-            this.stateMgr = new PersistentItemStateManager(pMgr, PERSISTENT_ROOT_ID.getUUID(), ntReg);
-            PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(PERSISTENT_ROOT_ID);
-            historyRoot = new PersistentNode(stateMgr, nodeState);
+            NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
+            // enable this to make the persistence storage visible
+            if (true) {
+                // check for versionhistory root
+                if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME)) {
+                    // if not exist, create
+                    systemRoot.addNode(VERSION_HISTORY_ROOT_NAME, NodeTypeRegistry.NT_UNSTRUCTURED);
+                    systemRoot.save();
+                }
+                NodeState nodeState = (NodeState) stateMgr.getItemState(new NodeId(systemRoot.getNode(VERSION_HISTORY_ROOT_NAME).internalGetUUID()));
+                historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+            } else {
+                if (!stateMgr.hasItemState(PERSISTENT_ROOT_ID)) {
+                    UpdateOperation update = stateMgr.beginUpdate();
+                    NodeState nodeState = update.createNew(PERSISTENT_ROOT_ID.getUUID(), NodeTypeRegistry.NT_UNSTRUCTURED, null);
+                    nodeState.setDefinitionId(new NodeDefId(ntMgr.getRootNodeDefinition().unwrap()));
+                    // persist state
+                    update.store(nodeState);
+                    // finish update operation
+                    update.end();
+                    historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+                } else {
+                    NodeState nodeState = (NodeState) stateMgr.getItemState(PERSISTENT_ROOT_ID);
+                    historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+                }
+            }
             initVirtualIds(historyRoot.getState());
             log.info("loaded " + idsByExternal.size() + " virtual ids.");
         } catch (ItemStateException e) {
@@ -163,6 +198,7 @@
 
     /**
      * initializes the internal item ids
+     *
      * @param parent
      * @throws RepositoryException
      * @throws ItemStateException
@@ -180,6 +216,7 @@
 
     /**
      * initializes the internal item ids
+     *
      * @param realUUID
      * @param state
      * @throws ItemStateException
@@ -189,7 +226,7 @@
             throws ItemStateException, RepositoryException {
         PersistentId id = new PersistentId(realUUID, state);
         if (id.type != PersistentId.TYPE_UNDEFINED) {
-            synchronized(idsByExternal) {
+            synchronized (idsByExternal) {
                 idsByExternal.put(id.externalId, id);
                 idsByInternal.put(id.internalId, id);
             }
@@ -202,17 +239,19 @@
 
     /**
      * returns the persistentid for a given external uuid
+     *
      * @param uuid
      * @return
      */
     private PersistentId getIdByExternal(String uuid) {
-        synchronized(idsByExternal) {
+        synchronized (idsByExternal) {
             return (PersistentId) idsByExternal.get(uuid);
         }
     }
 
     /**
      * returns the persustentid for a given internal uuid
+     *
      * @param uuid
      * @return
      */
@@ -222,12 +261,13 @@
 
     /**
      * returns the persustentid for a give internal uuid and item type
+     *
      * @param uuid
      * @param type
      * @return
      */
     private PersistentId getIdByExternal(String uuid, int type) {
-        synchronized(idsByExternal) {
+        synchronized (idsByExternal) {
             PersistentId id = (PersistentId) idsByExternal.get(uuid);
             return id != null && id.type == type ? id : null;
         }
@@ -245,15 +285,15 @@
 
         // check if version history for that node already exists
         InternalVersionHistoryImpl hist = (InternalVersionHistoryImpl) getVersionHistory(node.internalGetUUID());
-        if (hist!=null) {
+        if (hist != null) {
             return hist;
         }
 
         // create deep path
         String uuid = UUID.randomUUID().toString();
         PersistentNode root = historyRoot;
-        for (int i=0; i<3; i++) {
-            QName name = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(i*2, i*2+2));
+        for (int i = 0; i < 3; i++) {
+            QName name = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(i * 2, i * 2 + 2));
             if (!root.hasNode(name)) {
                 root.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
                 root.store();
@@ -285,7 +325,7 @@
             throws RepositoryException {
 
         PersistentId pid = getIdByExternal(histId, PersistentId.TYPE_HISTORY);
-        return pid==null ? null : (InternalVersionHistory) getItem(pid);
+        return pid == null ? null : (InternalVersionHistory) getItem(pid);
     }
 
     /**
@@ -342,7 +382,7 @@
             throws RepositoryException {
 
         PersistentId pid = getIdByExternal(versionId, PersistentId.TYPE_VERSION);
-        return pid==null ? null : (InternalVersion) getItem(pid);
+        return pid == null ? null : (InternalVersion) getItem(pid);
     }
 
     /**
@@ -357,6 +397,7 @@
 
     /**
      * checks, if the item with the given external id exists
+     *
      * @param externalId
      * @return
      */
@@ -366,6 +407,7 @@
 
     /**
      * returns the item referred by the external id
+     *
      * @param externalId
      * @return
      * @throws RepositoryException
@@ -373,11 +415,12 @@
     public InternalVersionItem getItemByExternal(String externalId)
             throws RepositoryException {
         PersistentId pid = getIdByExternal(externalId);
-        return pid==null ? null : getItem(pid);
+        return pid == null ? null : getItem(pid);
     }
 
     /**
      * returns the item referred by the internal id
+     *
      * @param internalId
      * @return
      * @throws RepositoryException
@@ -385,11 +428,12 @@
     public InternalVersionItem getItemByInternal(String internalId)
             throws RepositoryException {
         PersistentId pid = getIdByInternal(internalId);
-        return pid==null ? null : getItem(pid);
+        return pid == null ? null : getItem(pid);
     }
 
     /**
      * returns the item with the given persistent id
+     *
      * @param pid
      * @return
      * @throws RepositoryException
@@ -397,10 +441,10 @@
     private InternalVersionItem getItem(PersistentId pid)
             throws RepositoryException {
 
-        InternalVersionItem item =(InternalVersionItem) items.get(pid);
-        if (item==null) {
+        InternalVersionItem item = (InternalVersionItem) items.get(pid);
+        if (item == null) {
             PersistentNode pNode = historyRoot.getNodeByUUID(pid.internalId);
-            if (pNode!=null) {
+            if (pNode != null) {
                 InternalVersionItem parent = getItemByInternal(pNode.getParentUUID());
                 if (pid.type == PersistentId.TYPE_FROZEN) {
                     item = new InternalFrozenNodeImpl(this, pNode, pid.externalId, parent);
@@ -414,7 +458,7 @@
                     //return null;
                 }
             }
-            if (item!=null) {
+            if (item != null) {
                 items.put(pid, item);
             }
         }
@@ -492,13 +536,19 @@
         private static final int TYPE_FROZEN = 3;
         private static final int TYPE_FROZEN_HISTORY = 4;
 
-        /** the type of the persistent node */
+        /**
+         * the type of the persistent node
+         */
         private final int type;
 
-        /** the persistent uuid of the node */
+        /**
+         * the persistent uuid of the node
+         */
         private final String externalId;
 
-        /** the persistent uuid of the node */
+        /**
+         * the persistent uuid of the node
+         */
         private final String internalId;
 
         public PersistentId(int type, String external, String internal) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java	Sun Jan 23 09:11:20 2005
@@ -1,6 +1,5 @@
 /*
- * Copyright 2004-2005 The Apache Software Foundation or its licensors,
- *                     as applicable.
+ * Copyright 2004 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +24,8 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeDef;
+import javax.jcr.nodetype.PropertyDef;
 import java.util.HashSet;
 import java.util.List;
 
@@ -32,17 +33,22 @@
  * This Class provides some basic node operations directly on the persistent
  * state.
  */
-class PersistentNode {
+public class PersistentNode {
 
     /**
      * the underlaying persistent state
      */
-    private PersistentNodeState nodeState;
+    private NodeState nodeState;
 
     /**
      * the state manager
      */
-    private final PersistentItemStateProvider stateMgr;
+    private final ItemStateManager stateMgr;
+
+    /**
+     * the node type manager
+     */
+    private final NodeTypeManagerImpl ntMgr;
 
     /**
      * the cached name
@@ -52,13 +58,16 @@
     /**
      * Creates a new persistent node
      *
-     * @param statemgr
+     * @param stateMgr
+     * @param ntMgr
      * @param nodeState
      */
-    protected PersistentNode(PersistentItemStateProvider statemgr,
-                             PersistentNodeState nodeState) {
+    protected PersistentNode(ItemStateManager stateMgr,
+                             NodeTypeManagerImpl ntMgr,
+                             NodeState nodeState) {
         this.nodeState = nodeState;
-        this.stateMgr = statemgr;
+        this.stateMgr = stateMgr;
+        this.ntMgr = ntMgr;
     }
 
 
@@ -94,7 +103,7 @@
         return nodeState.getParentUUID();
     }
 
-    protected PersistentNodeState getState() {
+    protected NodeState getState() {
         return nodeState;
     }
 
@@ -192,7 +201,8 @@
      */
     protected void setPropertyValues(QName name, int type, InternalValue[] values, boolean multiple)
             throws RepositoryException {
-        PersistentPropertyState prop = getOrCreatePropertyState(name, type, multiple);
+
+        PropertyState prop = getOrCreatePropertyState(name, type, multiple);
         prop.setValues(values);
     }
 
@@ -205,40 +215,84 @@
      * @return
      * @throws RepositoryException
      */
-    private PersistentPropertyState getOrCreatePropertyState(QName name, int type, boolean multiValued)
+    private PropertyState getOrCreatePropertyState(QName name, int type, boolean multiValued)
             throws RepositoryException {
 
         PropertyId propId = new PropertyId(nodeState.getUUID(), name);
         if (stateMgr.hasItemState(propId)) {
             try {
-                PersistentPropertyState propState = (PersistentPropertyState) stateMgr.getItemState(propId);
+                PropertyState propState = (PropertyState) stateMgr.getItemState(propId);
                 // someone calling this method will always alter the property state, so set status to modified
-                if (propState.getStatus()==ItemState.STATUS_EXISTING) {
-                    propState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
-                }
-                // although this is not quite correct, we mark node as modified aswell
-                if (nodeState.getStatus()==ItemState.STATUS_EXISTING) {
-                    nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
-                }
+                propState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
                 return propState;
             } catch (ItemStateException e) {
                 throw new RepositoryException("Unable to create property: " + e.toString());
             }
         } else {
-            try {
-                PersistentPropertyState propState = stateMgr.createPropertyState(nodeState.getUUID(), name);
-                propState.setType(type);
-                propState.setMultiValued(multiValued);
-                propState.setDefinitionId(PropDefId.valueOf("0"));
-                // need to store nodestate
-                nodeState.addPropertyEntry(name);
-                if (nodeState.getStatus()==ItemState.STATUS_EXISTING) {
-                    nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
-                }
-                return propState;
-            } catch (ItemStateException e) {
-                throw new RepositoryException("Unable to store property: " + e.toString());
-            }
+            PropertyDefImpl def = getApplicablePropertyDef(name, type, multiValued);
+            //@todo create property state inside an update
+            PropertyState propState = new PropertyState(name, nodeState.getUUID(),
+                    PropertyState.STATUS_NEW, false);
+            propState.setType(type);
+            propState.setMultiValued(multiValued);
+            propState.setDefinitionId(new PropDefId(def.unwrap()));
+
+            // need to store nodestate
+            nodeState.addPropertyEntry(name);
+            nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+            return propState;
+        }
+    }
+
+    /**
+     * retrieves the property definition for the given contraints
+     *
+     * @param propertyName
+     * @param type
+     * @param multiValued
+     * @return
+     * @throws RepositoryException
+     */
+    protected PropertyDefImpl getApplicablePropertyDef(QName propertyName,
+                                                       int type, boolean multiValued)
+            throws RepositoryException {
+        PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(propertyName, type, multiValued);
+        return ntMgr.getPropDef(new PropDefId(pd));
+    }
+
+    /**
+     * Retrieves the node definition for the given contraints.
+     *
+     * @param nodeName
+     * @param nodeTypeName
+     * @return
+     * @throws RepositoryException
+     */
+    protected NodeDefImpl getApplicableChildNodeDef(QName nodeName, QName nodeTypeName)
+            throws RepositoryException {
+        ChildNodeDef cnd = getEffectiveNodeType().getApplicableChildNodeDef(nodeName, nodeTypeName);
+        return ntMgr.getNodeDef(new NodeDefId(cnd));
+    }
+
+    /**
+     * Returns the effective (i.e. merged and resolved) node type representation
+     * of this node's primary and mixin node types.
+     *
+     * @return the effective node type
+     * @throws RepositoryException
+     */
+    protected EffectiveNodeType getEffectiveNodeType() throws RepositoryException {
+        // build effective node type of mixins & primary type
+        NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
+        // existing mixin's
+        HashSet set = new HashSet(nodeState.getMixinTypeNames());
+        // primary type
+        set.add(nodeState.getNodeTypeName());
+        try {
+            return ntReg.getEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));
+        } catch (NodeTypeConflictException ntce) {
+            String msg = "internal error: failed to build effective node type for node " + nodeState.getUUID();
+            throw new RepositoryException(msg, ntce);
         }
     }
 
@@ -273,9 +327,7 @@
      */
     protected boolean removeNode(QName name, int index) throws RepositoryException {
         if (nodeState.removeChildNodeEntry(name, index)) {
-            if (nodeState.getStatus()==ItemState.STATUS_EXISTING) {
-                nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
-            }
+            nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
             return true;
         } else {
             return false;
@@ -297,8 +349,8 @@
             return null;
         }
         try {
-            PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
-            return new PersistentNode(stateMgr, state);
+            NodeState state = (NodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+            return new PersistentNode(stateMgr, ntMgr, state);
         } catch (ItemStateException e) {
             throw new RepositoryException("Unable to getNode: " + e.toString());
         }
@@ -313,8 +365,8 @@
      */
     protected PersistentNode getNodeByUUID(String uuid) throws RepositoryException {
         try {
-            PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(uuid));
-            return new PersistentNode(stateMgr, state);
+            NodeState state = (NodeState) stateMgr.getItemState(new NodeId(uuid));
+            return new PersistentNode(stateMgr, ntMgr, state);
         } catch (ItemStateException e) {
             throw new RepositoryException("Unable to getNode: " + e.toString());
         }
@@ -332,41 +384,77 @@
      */
     protected PersistentNode addNode(QName nodeName, QName nodeTypeName)
             throws NoSuchNodeTypeException, ConstraintViolationException, RepositoryException {
-        return createChildNode(nodeName, nodeTypeName, null);
+        NodeTypeImpl nodeType = ntMgr.getNodeType(nodeTypeName);
+        NodeDefImpl def;
+        try {
+            def = getApplicableChildNodeDef(name, nodeType == null ? null : nodeType.getQName());
+        } catch (RepositoryException re) {
+            // hack, use nt:unstructured as parent
+            try {
+                NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
+                EffectiveNodeType ent = ntReg.getEffectiveNodeType(new QName[]{NodeTypeRegistry.NT_UNSTRUCTURED});
+                ChildNodeDef cnd = ent.getApplicableChildNodeDef(name, nodeTypeName);
+                def = ntMgr.getNodeDef(new NodeDefId(cnd));
+            } catch (NodeTypeConflictException e) {
+                String msg = "no definition found in parent node's node type for new node";
+                throw new ConstraintViolationException(msg, re);
+            }
+        }
+
+        if (nodeType == null) {
+            // use default node type
+            nodeType = (NodeTypeImpl) def.getDefaultPrimaryType();
+        }
+        return createChildNode(nodeName, def, nodeType, null);
     }
 
     /**
      * creates a new child node
      *
      * @param name
+     * @param def
+     * @param nodeType
      * @param uuid
      * @return
      * @throws RepositoryException
      */
-    private PersistentNode createChildNode(QName name, QName nodeTypeName, String uuid)
+    private PersistentNode createChildNode(QName name, NodeDefImpl def,
+                                           NodeTypeImpl nodeType, String uuid)
             throws RepositoryException {
 
         String parentUUID = nodeState.getUUID();
         // create a new node state
-        PersistentNodeState state = null;
-        try {
-            if (uuid == null) {
-                uuid = UUID.randomUUID().toString();	// version 4 uuid
-            }
-            state = stateMgr.createNodeState(uuid, nodeTypeName, parentUUID);
-            state.setDefinitionId(NodeDefId.valueOf("0"));
-        } catch (ItemStateException ise) {
-            String msg = "failed to add child node " + name + " to " + parentUUID;
-            throw new RepositoryException(msg, ise);
-        }
+        NodeState state = null;
+        if (uuid == null) {
+            uuid = UUID.randomUUID().toString();	// version 4 uuid
+        }
+        //@todo create node state inside an update
+        state = new NodeState(uuid, nodeType.getQName(), parentUUID,
+                NodeState.STATUS_NEW, false);
+        state.setDefinitionId(new NodeDefId(def.unwrap()));
 
         // create Node instance wrapping new node state
-        PersistentNode node = new PersistentNode(stateMgr, state);
+        PersistentNode node = new PersistentNode(stateMgr, ntMgr, state);
         // add new child node entry
         nodeState.addChildNodeEntry(name, state.getUUID());
-        if (nodeState.getStatus()==ItemState.STATUS_EXISTING) {
-            nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+        nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+
+        // add 'auto-create' properties defined in node type
+        PropertyDef[] pda = nodeType.getAutoCreatePropertyDefs();
+        for (int i = 0; i < pda.length; i++) {
+            PropertyDefImpl pd = (PropertyDefImpl) pda[i];
+            node.getOrCreatePropertyState(pd.getQName(), pd.getRequiredType(), pd.isMultiple());
         }
+
+        // recursively add 'auto-create' child nodes defined in node type
+        NodeDef[] nda = nodeType.getAutoCreateNodeDefs();
+        for (int i = 0; i < nda.length; i++) {
+            NodeDefImpl nd = (NodeDefImpl) nda[i];
+            node.createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+        }
+
+        // store primary type
+        node.setPropertyValue(ItemImpl.PROPNAME_PRIMARYTYPE, InternalValue.create(nodeType.getQName()));
         return node;
     }
 
@@ -382,8 +470,8 @@
             PersistentNode[] children = new PersistentNode[entries.size()];
             for (int i = 0; i < entries.size(); i++) {
                 NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) entries.get(i);
-                PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
-                children[i] = new PersistentNode(stateMgr, state);
+                NodeState state = (NodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+                children[i] = new PersistentNode(stateMgr, ntMgr, state);
             }
             return children;
         } catch (ItemStateException e) {
@@ -398,7 +486,9 @@
      */
     protected void store() throws RepositoryException {
         try {
-            store(nodeState);
+            UpdateOperation update = stateMgr.beginUpdate();
+            store(nodeState, update);
+            update.end();
         } catch (ItemStateException e) {
             throw new RepositoryException(e);
         }
@@ -408,28 +498,31 @@
      * stores the given persistent state recursively
      *
      * @param state
+     * @param update update operation
      * @throws ItemStateException
      */
-    private void store(PersistentNodeState state) throws ItemStateException {
+    private void store(NodeState state, UpdateOperation update)
+            throws ItemStateException {
+
         if (state.isTransient()) {
             // first store all transient properties
             List props = state.getPropertyEntries();
             for (int i = 0; i < props.size(); i++) {
                 NodeState.PropertyEntry entry = (NodeState.PropertyEntry) props.get(i);
-                PersistentPropertyState pstate = (PersistentPropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
+                PropertyState pstate = (PropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
                 if (pstate.isTransient()) {
-                    pstate.store();
+                    update.store(pstate);
                 }
             }
             // now store all child node entries
             List nodes = state.getChildNodeEntries();
             for (int i = 0; i < nodes.size(); i++) {
                 NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) nodes.get(i);
-                PersistentNodeState nstate = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
-                store(nstate);
+                NodeState nstate = (NodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+                store(nstate, update);
             }
             // and store itself
-            state.store();
+            update.store(state);
         }
     }
 
@@ -442,7 +535,7 @@
         try {
             reload(nodeState);
             // refetch nodestate if discarded
-            nodeState = (PersistentNodeState) stateMgr.getItemState(nodeState.getId());
+            nodeState = (NodeState) stateMgr.getItemState(nodeState.getId());
         } catch (ItemStateException e) {
             throw new RepositoryException(e);
         }
@@ -454,13 +547,13 @@
      * @param state
      * @throws ItemStateException
      */
-    private void reload(PersistentNodeState state) throws ItemStateException {
+    private void reload(NodeState state) throws ItemStateException {
         if (state.isTransient()) {
             // first discard all all transient properties
             List props = state.getPropertyEntries();
             for (int i = 0; i < props.size(); i++) {
                 NodeState.PropertyEntry entry = (NodeState.PropertyEntry) props.get(i);
-                PersistentPropertyState pstate = (PersistentPropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
+                PropertyState pstate = (PropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
                 if (pstate.isTransient()) {
                     pstate.discard();
                 }
@@ -469,7 +562,7 @@
             List nodes = state.getChildNodeEntries();
             for (int i = 0; i < nodes.size(); i++) {
                 NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) nodes.get(i);
-                PersistentNodeState nstate = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+                NodeState nstate = (NodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
                 reload(nstate);
             }
             // and reload itself
@@ -486,7 +579,8 @@
     protected void copyFrom(PropertyImpl prop) throws RepositoryException {
         if (prop.getDefinition().isMultiple()) {
             InternalValue[] values = prop.internalGetValues();
-            setPropertyValues(prop.getQName(), values[0].getType(), values);
+            int type = values.length>0 ? values[0].getType() : prop.getDefinition().getRequiredType();
+            setPropertyValues(prop.getQName(), type, values);
         } else {
             setPropertyValue(prop.getQName(), prop.internalGetValue());
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java	Sun Jan 23 09:11:20 2005
@@ -16,24 +16,24 @@
  */
 package org.apache.jackrabbit.core.virtual;
 
-import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
-import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
-import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 
 import javax.jcr.RepositoryException;
 
 /**
  * This Interface defines a virtual item state provider.
  */
-public interface VirtualItemStateProvider extends ItemStateProvider {
+public interface VirtualItemStateProvider extends ItemStateManager {
 
     /**
-     * Checks if the id referrs to the root of a virtual tree.
+     * Checks if the id refers to the root of a virtual tree.
+     *
      * @param id
      * @return
      */
@@ -41,12 +41,14 @@
 
     /**
      * Returns the id of the root node of the virtual tree.
+     *
      * @return
      */
     public NodeId getVirtualRootId();
 
     /**
      * Checks if the node with the given id exists in this item state provider.
+     *
      * @param id
      * @return
      */
@@ -54,6 +56,7 @@
 
     /**
      * Checks if the property with the given id exists in this item state provider.
+     *
      * @param id
      * @return
      */
@@ -61,6 +64,7 @@
 
     /**
      * Returns the node state for the given node id
+     *
      * @param id
      * @return
      * @throws ItemStateException
@@ -71,6 +75,7 @@
 
     /**
      * Returns the property state for the give property id
+     *
      * @param id
      * @return
      * @throws ItemStateException
@@ -81,6 +86,7 @@
 
     /**
      * Creats a new virtual property state
+     *
      * @param parent
      * @param name
      * @param type
@@ -95,6 +101,7 @@
 
     /**
      * Creates a new virtual node state
+     *
      * @param parent
      * @param name
      * @param uuid

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java	Sun Jan 23 09:11:20 2005
@@ -59,7 +59,7 @@
                                    QName nodeTypeName,
                                    QName[] mixins)
             throws RepositoryException {
-        super(uuid, nodeTypeName, parentUUID, ItemState.STATUS_EXISTING);
+        super(uuid, nodeTypeName, parentUUID, ItemState.STATUS_EXISTING, false);
         this.stateMgr = stateMgr;
 
         // add default properties

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java	Sun Jan 23 09:11:20 2005
@@ -31,6 +31,6 @@
      * @param parentUUID
      */
     public VirtualPropertyState(QName name, String parentUUID) {
-        super(name, parentUUID, ItemState.STATUS_EXISTING);
+        super(name, parentUUID, ItemState.STATUS_EXISTING, false);
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java	Sun Jan 23 09:11:20 2005
@@ -18,7 +18,7 @@
 
 import org.apache.jackrabbit.core.*;
 import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.log4j.Logger;
@@ -48,7 +48,7 @@
 
     private static Logger log = Logger.getLogger(AbstractSAXEventGenerator.class);
 
-    protected final ItemStateProvider stateProvider;
+    protected final ItemStateManager stateProvider;
     protected final NamespaceRegistryImpl nsReg;
     protected final AccessManagerImpl accessMgr;
     protected final ContentHandler contentHandler;
@@ -83,7 +83,7 @@
      */
     protected AbstractSAXEventGenerator(NodeState nodeState, QName nodeName,
                                         boolean noRecurse, boolean binaryAsLink,
-                                        ItemStateProvider stateProvider,
+                                        ItemStateManager stateProvider,
                                         NamespaceRegistryImpl nsReg,
                                         AccessManagerImpl accessMgr,
                                         ContentHandler contentHandler) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java	Sun Jan 23 09:11:20 2005
@@ -17,7 +17,7 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.util.Base64;
@@ -76,7 +76,7 @@
      */
     public DocViewSAXEventGenerator(NodeState nodeState, QName nodeName,
                                     boolean noRecurse, boolean binaryAsLink,
-                                    ItemStateProvider stateProvider,
+                                    ItemStateManager stateProvider,
                                     NamespaceRegistryImpl nsReg,
                                     AccessManagerImpl accessMgr,
                                     HierarchyManager hierMgr,

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java?view=diff&rev=126221&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java&r1=126220&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java&r2=126221
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java	Sun Jan 23 09:11:20 2005
@@ -17,7 +17,7 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.util.Base64;
@@ -74,7 +74,7 @@
      */
     public SysViewSAXEventGenerator(NodeState nodeState, QName nodeName,
                                     boolean noRecurse, boolean binaryAsLink,
-                                    ItemStateProvider stateProvider,
+                                    ItemStateManager stateProvider,
                                     NamespaceRegistryImpl nsReg,
                                     AccessManagerImpl accessMgr,
                                     HierarchyManager hierMgr,

Mime
View raw message