Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 54860 invoked from network); 15 Aug 2006 13:50:50 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 15 Aug 2006 13:50:49 -0000 Received: (qmail 4753 invoked by uid 500); 15 Aug 2006 13:50:49 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 4661 invoked by uid 500); 15 Aug 2006 13:50:49 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 4652 invoked by uid 99); 15 Aug 2006 13:50:49 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Aug 2006 06:50:49 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Aug 2006 06:50:48 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id D06B01A981A; Tue, 15 Aug 2006 06:50:27 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r431601 - in /jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state: CachingItemStateManager.java TransientItemStateManager.java Date: Tue, 15 Aug 2006 13:50:27 -0000 To: commits@jackrabbit.apache.org From: mreutegg@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060815135027.D06B01A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: mreutegg Date: Tue Aug 15 06:50:26 2006 New Revision: 431601 URL: http://svn.apache.org/viewvc?rev=431601&view=rev Log: TransientItemStatemanager now also extends from CachingItemStateManager. Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java?rev=431601&r1=431600&r2=431601&view=diff ============================================================================== --- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java (original) +++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java Tue Aug 15 06:50:26 2006 @@ -31,7 +31,7 @@ * CachingItemStateManager implements an {@link ItemStateManager} * and decorates it with a caching facility. */ -public class CachingItemStateManager implements ItemStateManager, ItemStateLifeCycleListener { +public class CachingItemStateManager implements ItemStateManager { /** * The logger instance for this class. @@ -55,9 +55,10 @@ private final Map recentlyUsed; /** - * The root node of the workspace. + * The root node of the workspace or null if it has not been + * retrieved yet. */ - private final NodeState root; + private NodeState root; /** * The Id factory. @@ -65,28 +66,32 @@ private final IdFactory idFactory; /** + * An {@link ItemStateLifeCycleListener} to maintain the LRU and UUID + * reference cache. + */ + private final ItemStateLifeCycleListener lifeCycleListener; + + /** * Creates a new CachingItemStateManager. * * @param isf the item state factory to create item state instances. * @param idFactory the id factory. - * @throws NoSuchItemStateException if the root node cannot be obtained. - * @throws ItemStateException if any other error occurs while - * obtaining the root node. */ - public CachingItemStateManager(ItemStateFactory isf, IdFactory idFactory) - throws ItemStateException, NoSuchItemStateException { + public CachingItemStateManager(ItemStateFactory isf, IdFactory idFactory) { this.isf = isf; this.idFactory = idFactory; this.uuid2NodeState = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK); this.recentlyUsed = new LRUMap(1000); // TODO: make configurable - // initialize root - root = isf.createNodeState(idFactory.createNodeId((String) null, Path.ROOT), this); - root.addListener(this); + this.lifeCycleListener = new ISLifeCycleListener(); } //---------------------------------------------------< ItemStateManager >--- public NodeState getRootState() throws ItemStateException { + if (root == null) { + root = isf.createNodeState(idFactory.createNodeId((String) null, Path.ROOT), this); + root.addListener(lifeCycleListener); + } return root; } @@ -130,35 +135,15 @@ return false; } - //------------------------< ItemStateListener >----------------------------- - - public void statusChanged(ItemState state, int previousStatus) { - if (state.getStatus() == ItemState.STATUS_REMOVED || - state.getStatus() == ItemState.STATUS_STALE_DESTROYED) { - recentlyUsed.remove(state); - if (state.isNode()) { - NodeState nodeState = (NodeState) state; - if (nodeState.getUUID() != null) { - uuid2NodeState.remove(nodeState.getUUID()); - } - } - } - } - - public void stateCreated(ItemState created) { - } - - public void stateModified(ItemState modified) { - } - - public void stateDestroyed(ItemState destroyed) { - } + //------------------------------< internal >-------------------------------- - public void stateDiscarded(ItemState discarded) { + /** + * @return the item state factory of this ItemStateManager. + */ + protected final ItemStateFactory getItemStateFactory() { + return isf; } - //------------------------------< internal >-------------------------------- - /** * Called whenever an item state is accessed. Calling this method will update * the LRU map which keeps track of most recently used item states. @@ -183,7 +168,7 @@ Path relPath = id.getRelativePath(); // start with root node if no uuid part in id - NodeState nodeState = root; + NodeState nodeState = getRootState(); // resolve uuid part if (uuid != null) { nodeState = (NodeState) uuid2NodeState.get(uuid); @@ -191,7 +176,7 @@ // state identified by the uuid is not yet cached -> get from ISM NodeId refId = (relPath == null) ? (NodeId) id : idFactory.createNodeId(uuid); nodeState = isf.createNodeState(refId, this); - nodeState.addListener(this); + nodeState.addListener(lifeCycleListener); uuid2NodeState.put(uuid, nodeState); } } @@ -223,7 +208,12 @@ } } else { // start from root - state = root; + try { + state = getRootState(); + } catch (ItemStateException e) { + log.warn("unable to get root node state:" + e.getMessage()); + return null; + } } // resolve relative path @@ -237,5 +227,35 @@ } return state; + } + + //------------------------< ItemStateListener >----------------------------- + + private class ISLifeCycleListener implements ItemStateLifeCycleListener { + + public void statusChanged(ItemState state, int previousStatus) { + if (state.getStatus() == ItemState.STATUS_REMOVED || + state.getStatus() == ItemState.STATUS_STALE_DESTROYED) { + recentlyUsed.remove(state); + if (state.isNode()) { + NodeState nodeState = (NodeState) state; + if (nodeState.getUUID() != null) { + uuid2NodeState.remove(nodeState.getUUID()); + } + } + } + } + + public void stateCreated(ItemState created) { + } + + public void stateModified(ItemState modified) { + } + + public void stateDestroyed(ItemState destroyed) { + } + + public void stateDiscarded(ItemState discarded) { + } } } Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java?rev=431601&r1=431600&r2=431601&view=diff ============================================================================== --- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java (original) +++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java Tue Aug 15 06:50:26 2006 @@ -40,8 +40,8 @@ * {@link #createNodeState(QName, String, QName, NodeState)} and * {@link #createPropertyState(NodeState, QName)}. */ -public class TransientItemStateManager - implements ItemStateManager, ItemStateLifeCycleListener { +public class TransientItemStateManager extends CachingItemStateManager + implements ItemStateLifeCycleListener { /** * Logger instance for this class. @@ -55,11 +55,6 @@ private final ChangeLog changeLog; /** - * - */ - private final IdFactory idFactory; - - /** * The parent item state manager, which return item states that are then * overlayed by transient item states created by this TransientItemStateManager. */ @@ -69,7 +64,7 @@ * The transient item state factory to create new and existing item state * instances. */ - private final TransientItemStateFactory isf; + private final TransientISFactory isf; /** * ItemStateManager view of the states in the attic; lazily instantiated @@ -77,121 +72,78 @@ */ private AtticItemStateManager attic; + /** + * The root node state or null if it hasn't been retrieved yet. + */ + private NodeState rootNodeState; + TransientItemStateManager(IdFactory idFactory, ItemStateManager parent) { + super(new TransientISFactory(idFactory, parent), idFactory); this.changeLog = new ChangeLog(); - this.idFactory = idFactory; this.parent = parent; - this.isf = new TransientISFactory(); + this.isf = (TransientISFactory) getItemStateFactory(); + this.isf.setListener(this); } //-----------------------< ItemStateManager >------------------------------- /** - * Return the root node state or null if the root state has - * not been modified yet. + * Return the root node state. * - * @return - * @throws ItemStateException + * @return the root node state. + * @throws ItemStateException if an error occurs while retrieving the root + * node state. * @see ItemStateManager#getRootState() */ public NodeState getRootState() throws ItemStateException { - // TODO - return null; + if (rootNodeState == null) { + rootNodeState = isf.createNodeState(parent.getRootState().getNodeId(), this); + rootNodeState.addListener(this); + } + return rootNodeState; } /** - * Return an item state given its id. Returns null - * if the item state is neither in the added nor in the modified - * section. Throws a NoSuchItemStateException if - * the item state is in the deleted section. + * Return an item state given its id. Please note that this implementation + * also returns item states that are in removed state ({@link + * ItemState.STATUS_EXISTING_REMOVED} but not yet saved. * - * @return item state or null - * @throws NoSuchItemStateException if the item has been deleted + * @return item state. + * @throws NoSuchItemStateException if there is no item state (not even a + * removed item state) with the given id. * @see ItemStateManager#getItemState(ItemId) */ public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException { - // TODO: this is expensive. Improvement: Lookup item, then check its state - ItemState state = null; - for (Iterator it = changeLog.addedStates(); it.hasNext(); ) { - ItemState s = (ItemState) it.next(); - if (s.getId().equals(id)) { - state = s; - break; - } - } - if (state == null) { - for (Iterator it = changeLog.modifiedStates(); it.hasNext(); ) { - ItemState s = (ItemState) it.next(); - if (s.getId().equals(id)) { - state = s; - break; - } - } - if (state == null) { - for (Iterator it = changeLog.deletedStates(); it.hasNext(); ) { - ItemState s = (ItemState) it.next(); - if (s.getId().equals(id)) { - throw new NoSuchItemStateException("State has been marked destroyed: " + id); - } - } - } - } - return state; + return super.getItemState(id); } /** * Return a flag indicating whether a given item state exists. * - * @return true if item state exists within this - * log; false otherwise + * @return true if item state exists within this item state + * manager; false otherwise * @see ItemStateManager#hasItemState(ItemId) */ public boolean hasItemState(ItemId id) { - // TODO: too expensive. lookup item and check status - for (Iterator it = changeLog.addedStates(); it.hasNext(); ) { - ItemState s = (ItemState) it.next(); - if (s.getId().equals(id)) { - return true; - } - } - for (Iterator it = changeLog.modifiedStates(); it.hasNext(); ) { - ItemState s = (ItemState) it.next(); - if (s.getId().equals(id)) { - return true; - } - } - return false; + return super.hasItemState(id); } /** - * Return a node references object given its id. Returns - * null if the node reference is not in the modified - * section. - * - * @return node references or null + * Always throws an {@link UnsupportedOperationException}. A transient item + * state manager does not maintain node reference. * @see ItemStateManager#getNodeReferences(NodeId) */ public NodeReferences getNodeReferences(NodeId id) { - // TODO: improve - for (Iterator it = changeLog.modifiedRefs(); it.hasNext(); ) { - NodeReferences refs = (NodeReferences) it.next(); - if (refs.getId().equals(id)) { - return refs; - } - } - return null; + throw new UnsupportedOperationException("getNodeReferences() not implemented"); } /** - * Returns false if the node reference is not in the modified - * section. - * - * @return false if no references are present in this changelog for the - * given id. + * Always throws an {@link UnsupportedOperationException}. A transient item + * state manager does not maintain node reference. * @see ItemStateManager#hasNodeReferences(NodeId) */ public boolean hasNodeReferences(NodeId id) { - return getNodeReferences(id) != null; + throw new UnsupportedOperationException("hasNodeReferences() not implemented"); } /** @@ -409,99 +361,6 @@ return changeLog.deletedStates(); } - //----------------------< TransientItemStateFactory >----------------------- - - private final class TransientISFactory implements TransientItemStateFactory { - - /** - * @inheritDoc - * @see TransientItemStateFactory#createNewNodeState(QName, String, NodeState) - */ - public NodeState createNewNodeState(QName name, String uuid, NodeState parent) { - NodeState nodeState = new NodeState(name, uuid, parent, null, - ItemState.STATUS_NEW, true, this, idFactory); - // get a notification when this item state is saved or invalidated - nodeState.addListener(TransientItemStateManager.this); - changeLog.added(nodeState); - return nodeState; - } - - /** - * @inheritDoc - * @see TransientItemStateFactory#createNewPropertyState(QName, NodeState) - */ - public PropertyState createNewPropertyState(QName name, NodeState parent) { - PropertyState propState = new PropertyState(name, parent, - ItemState.STATUS_NEW, true, idFactory); - // get a notification when this item state is saved or invalidated - propState.addListener(TransientItemStateManager.this); - changeLog.added(propState); - return propState; - } - - /** - * @inheritDoc - * @see TransientItemStateFactory#createNodeState(NodeId, ItemStateManager) - */ - public NodeState createNodeState(NodeId nodeId, ItemStateManager ism) - throws NoSuchItemStateException, ItemStateException { - // retrieve state to overlay - NodeState overlayedState = (NodeState) parent.getItemState(nodeId); - NodeId parentId = overlayedState.getParent().getNodeId(); - NodeState parentState = (NodeState) ism.getItemState(parentId); - NodeState nodeState = new NodeState(overlayedState, parentState, - ItemState.STATUS_EXISTING, true, this, idFactory); - nodeState.addListener(TransientItemStateManager.this); - return nodeState; - } - - /** - * @inheritDoc - * @see TransientItemStateFactory#createNodeState(NodeId, NodeState) - */ - public NodeState createNodeState(NodeId nodeId, NodeState parentState) - throws NoSuchItemStateException, ItemStateException { - // retrieve state to overlay - NodeState overlayedState = (NodeState) parent.getItemState(nodeId); - NodeState nodeState = new NodeState(overlayedState, parentState, - ItemState.STATUS_EXISTING, true, this, idFactory); - nodeState.addListener(TransientItemStateManager.this); - return nodeState; - } - - /** - * @inheritDoc - * @see TransientItemStateFactory#createPropertyState(PropertyId, ItemStateManager) - */ - public PropertyState createPropertyState(PropertyId propertyId, - ItemStateManager ism) - throws NoSuchItemStateException, ItemStateException { - // retrieve state to overlay - PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId); - NodeId parentId = overlayedState.getParent().getNodeId(); - NodeState parentState = (NodeState) ism.getItemState(parentId); - PropertyState propState = new PropertyState(overlayedState, parentState, - ItemState.STATUS_EXISTING, true, idFactory); - propState.addListener(TransientItemStateManager.this); - return propState; - } - - /** - * @inheritDoc - * @see TransientItemStateFactory#createPropertyState(PropertyId, NodeState) - */ - public PropertyState createPropertyState(PropertyId propertyId, - NodeState parentState) - throws NoSuchItemStateException, ItemStateException { - // retrieve state to overlay - PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId); - PropertyState propState = new PropertyState(overlayedState, parentState, - ItemState.STATUS_EXISTING, true, idFactory); - propState.addListener(TransientItemStateManager.this); - return propState; - } - } - //-----------------------< ItemStateLifeCycleListener >--------------------- /** @@ -587,8 +446,8 @@ // state is now stale. keep in modified. wait until refreshed break; case ItemState.STATUS_NEW: - // should never happen - log.warn("ItemState changed status to 'new'"); + // new state has been created + changeLog.added(state); break; case ItemState.STATUS_UNDEFINED: // should never happen @@ -673,6 +532,117 @@ public boolean hasNodeReferences(NodeId id) { // n/a return false; + } + } + + //----------------------< TransientItemStateFactory >----------------------- + + private final static class TransientISFactory implements TransientItemStateFactory { + + private final IdFactory idFactory; + + private ItemStateLifeCycleListener listener; + + private final ItemStateManager parent; + + private TransientISFactory(IdFactory idFactory, + ItemStateManager parent) { + this.idFactory = idFactory; + this.parent = parent; + } + + private void setListener(ItemStateLifeCycleListener listener) { + this.listener = listener; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createNewNodeState(QName, String, NodeState) + */ + public NodeState createNewNodeState(QName name, String uuid, NodeState parent) { + NodeState nodeState = new NodeState(name, uuid, parent, null, + ItemState.STATUS_NEW, true, this, idFactory); + // get a notification when this item state is saved or invalidated + nodeState.addListener(listener); + // notify listener that a node state has been created + listener.statusChanged(nodeState, ItemState.STATUS_NEW); + return nodeState; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createNewPropertyState(QName, NodeState) + */ + public PropertyState createNewPropertyState(QName name, NodeState parent) { + PropertyState propState = new PropertyState(name, parent, + ItemState.STATUS_NEW, true, idFactory); + // get a notification when this item state is saved or invalidated + propState.addListener(listener); + // notify listener that a property state has been created + listener.statusChanged(propState, ItemState.STATUS_NEW); + return propState; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createNodeState(NodeId, ItemStateManager) + */ + public NodeState createNodeState(NodeId nodeId, ItemStateManager ism) + throws NoSuchItemStateException, ItemStateException { + // retrieve state to overlay + NodeState overlayedState = (NodeState) parent.getItemState(nodeId); + NodeId parentId = overlayedState.getParent().getNodeId(); + NodeState parentState = (NodeState) ism.getItemState(parentId); + NodeState nodeState = new NodeState(overlayedState, parentState, + ItemState.STATUS_EXISTING, true, this, idFactory); + nodeState.addListener(listener); + return nodeState; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createNodeState(NodeId, NodeState) + */ + public NodeState createNodeState(NodeId nodeId, NodeState parentState) + throws NoSuchItemStateException, ItemStateException { + // retrieve state to overlay + NodeState overlayedState = (NodeState) parent.getItemState(nodeId); + NodeState nodeState = new NodeState(overlayedState, parentState, + ItemState.STATUS_EXISTING, true, this, idFactory); + nodeState.addListener(listener); + return nodeState; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createPropertyState(PropertyId, ItemStateManager) + */ + public PropertyState createPropertyState(PropertyId propertyId, + ItemStateManager ism) + throws NoSuchItemStateException, ItemStateException { + // retrieve state to overlay + PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId); + NodeId parentId = overlayedState.getParent().getNodeId(); + NodeState parentState = (NodeState) ism.getItemState(parentId); + PropertyState propState = new PropertyState(overlayedState, parentState, + ItemState.STATUS_EXISTING, true, idFactory); + propState.addListener(listener); + return propState; + } + + /** + * @inheritDoc + * @see TransientItemStateFactory#createPropertyState(PropertyId, NodeState) + */ + public PropertyState createPropertyState(PropertyId propertyId, + NodeState parentState) + throws NoSuchItemStateException, ItemStateException { + // retrieve state to overlay + PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId); + PropertyState propState = new PropertyState(overlayedState, parentState, + ItemState.STATUS_EXISTING, true, idFactory); + propState.addListener(listener); + return propState; } } }