You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2006/08/31 11:38:18 UTC
svn commit: r438851 [1/2] - in
/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core: ./
state/ version/ virtual/
Author: dpfister
Date: Thu Aug 31 02:38:17 2006
New Revision: 438851
URL: http://svn.apache.org/viewvc?rev=438851&view=rev
Log:
JCR-552 Move listeners from item state to item state managers
Added:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/StateChangeDispatcher.java
Removed:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
Modified:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemState.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemStateListener.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeStateListener.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Thu Aug 31 02:38:17 2006
@@ -282,7 +282,9 @@
* {@inheritDoc}
*/
public void stateModified(ItemState modified) {
- stateModified((NodeState) modified);
+ if (modified.isNode()) {
+ stateModified((NodeState) modified);
+ }
}
/**
@@ -324,7 +326,6 @@
* {@inheritDoc}
*/
public void stateDestroyed(ItemState destroyed) {
- destroyed.removeListener(this);
remove(destroyed.getId());
}
@@ -332,7 +333,6 @@
* {@inheritDoc}
*/
public void stateDiscarded(ItemState discarded) {
- discarded.removeListener(this);
if (discarded.isTransient() && !discarded.hasOverlayedState()) {
// a new node has been discarded -> remove from cache
remove(discarded.getId());
@@ -344,36 +344,6 @@
}
/**
- * Called when an <code>ItemState</code> has been overlaid by some
- * other state that now takes its identity. This notification is sent
- * on the state being overlaid.
- *
- * @param overlayer the <code>ItemState</code> that overlays this state
- */
- public void stateOverlaid(ItemState overlayer) {
- if (overlayer.isNode()) {
- overlayer.getOverlayedState().removeListener(this);
- overlayer.addListener(this);
- }
- }
-
- /**
- * Called when an <code>ItemState</code> no longer overlayes some other
- * item state. This notification is sent on the state overlaying another
- * state.
- *
- * @param overlayer the <code>ItemState</code> that overlaid another
- * item state. To get the overlaid state, invoke
- * {@link ItemState#getOverlayedState()}
- */
- public void stateUncovered(ItemState overlayer) {
- if (overlayer.isNode()) {
- overlayer.removeListener(this);
- overlayer.getOverlayedState().addListener(this);
- }
- }
-
- /**
* {@inheritDoc}
*/
public void nodeAdded(NodeState state, QName name, int index, NodeId id) {
@@ -507,8 +477,6 @@
LRUEntry entry = new LRUEntry(id, element);
element.set(entry);
idCache.put(id, entry);
-
- state.addListener(this);
}
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Thu Aug 31 02:38:17 2006
@@ -141,9 +141,6 @@
}
}
notifyCreated();
-
- // add this item as listener to events of the underlying state object
- this.state.addListener(this);
}
/**
@@ -893,110 +890,108 @@
* {@inheritDoc}
*/
public void stateDestroyed(ItemState destroyed) {
- // underlying state has been permanently destroyed
-
- // set state of this instance to 'destroyed'
- status = STATUS_DESTROYED;
- // dispose state
if (state == destroyed) {
- state.removeListener(this);
- state = null;
+ // set state of this instance to 'destroyed'
+ status = STATUS_DESTROYED;
+ // dispose state
+ if (state == destroyed) {
+ state = null;
+ }
+ /**
+ * notify the listeners that this instance has been
+ * permanently invalidated
+ */
+ notifyDestroyed();
}
- /**
- * notify the listeners that this instance has been
- * permanently invalidated
- */
- notifyDestroyed();
}
/**
* {@inheritDoc}
*/
public void stateModified(ItemState modified) {
- status = STATUS_MODIFIED;
+ if (state == modified) {
+ status = STATUS_MODIFIED;
+ }
}
/**
* {@inheritDoc}
*/
public void stateDiscarded(ItemState discarded) {
- /**
- * the state of this item has been discarded, probably as a result
- * of calling Item.refresh(false) or ItemImpl.setRemoved()
- */
- if (isTransient()) {
- switch (state.getStatus()) {
- /**
- * persistent item that has been transiently removed
- */
- case ItemState.STATUS_EXISTING_REMOVED:
- /**
- * persistent item that has been transiently modified
- */
- case ItemState.STATUS_EXISTING_MODIFIED:
- /**
- * persistent item that has been transiently modified or removed
- * and the underlying persistent state has been externally
- * modified since the transient modification/removal.
- */
- case ItemState.STATUS_STALE_MODIFIED:
- ItemState persistentState = state.getOverlayedState();
+ if (state == discarded) {
+ /**
+ * the state of this item has been discarded, probably as a result
+ * of calling Item.refresh(false) or ItemImpl.setRemoved()
+ */
+ if (isTransient()) {
+ switch (state.getStatus()) {
/**
- * the state is a transient wrapper for the underlying
- * persistent state, therefore restore the
- * persistent state and resurrect this item instance
- * if necessary
+ * persistent item that has been transiently removed
*/
- state.removeListener(this);
- persistentState.addListener(this);
- stateMgr.disconnectTransientItemState(state);
- state = persistentState;
+ case ItemState.STATUS_EXISTING_REMOVED:
+ /**
+ * persistent item that has been transiently modified
+ */
+ case ItemState.STATUS_EXISTING_MODIFIED:
+ /**
+ * persistent item that has been transiently modified or removed
+ * and the underlying persistent state has been externally
+ * modified since the transient modification/removal.
+ */
+ case ItemState.STATUS_STALE_MODIFIED:
+ ItemState persistentState = state.getOverlayedState();
+ /**
+ * the state is a transient wrapper for the underlying
+ * persistent state, therefore restore the
+ * persistent state and resurrect this item instance
+ * if necessary
+ */
+ stateMgr.disconnectTransientItemState(state);
+ state = persistentState;
- return;
+ return;
- /**
- * persistent item that has been transiently modified or removed
- * and the underlying persistent state has been externally
- * destroyed since the transient modification/removal.
- */
- case ItemState.STATUS_STALE_DESTROYED:
- /**
- * first notify the listeners that this instance has been
- * permanently invalidated
- */
- notifyDestroyed();
- // now set state of this instance to 'destroyed'
- status = STATUS_DESTROYED;
- // finally dispose state
- state.removeListener(this);
- state = null;
- return;
+ /**
+ * persistent item that has been transiently modified or removed
+ * and the underlying persistent state has been externally
+ * destroyed since the transient modification/removal.
+ */
+ case ItemState.STATUS_STALE_DESTROYED:
+ /**
+ * first notify the listeners that this instance has been
+ * permanently invalidated
+ */
+ notifyDestroyed();
+ // now set state of this instance to 'destroyed'
+ status = STATUS_DESTROYED;
+ state = null;
+ return;
- /**
- * new item that has been transiently added
- */
- case ItemState.STATUS_NEW:
- /**
- * first notify the listeners that this instance has been
- * permanently invalidated
- */
- notifyDestroyed();
- // now set state of this instance to 'destroyed'
- status = STATUS_DESTROYED;
- // finally dispose state
- state.removeListener(this);
- state = null;
- return;
+ /**
+ * new item that has been transiently added
+ */
+ case ItemState.STATUS_NEW:
+ /**
+ * first notify the listeners that this instance has been
+ * permanently invalidated
+ */
+ notifyDestroyed();
+ // now set state of this instance to 'destroyed'
+ status = STATUS_DESTROYED;
+ // finally dispose state
+ state = null;
+ return;
+ }
}
- }
- /**
- * first notify the listeners that this instance has been
- * invalidated
- */
- notifyInvalidated();
- // now render this instance 'invalid'
- status = STATUS_INVALIDATED;
+ /**
+ * first notify the listeners that this instance has been
+ * invalidated
+ */
+ notifyInvalidated();
+ // now render this instance 'invalid'
+ status = STATUS_INVALIDATED;
+ }
}
//-----------------------------------------------------------------< Item >
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/ItemManager.java Thu Aug 31 02:38:17 2006
@@ -28,6 +28,8 @@
import org.apache.jackrabbit.core.state.NoSuchItemStateException;
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.SessionItemStateManager;
+import org.apache.jackrabbit.core.state.ItemStateListener;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.core.version.VersionHistoryImpl;
import org.apache.jackrabbit.core.version.VersionImpl;
@@ -74,7 +76,7 @@
* If the parent <code>Session</code> is an <code>XASession</code>, there is
* one <code>ItemManager</code> instance per started global transaction.
*/
-public class ItemManager implements ItemLifeCycleListener, Dumpable {
+public class ItemManager implements ItemLifeCycleListener, Dumpable, ItemStateListener {
private static Logger log = LoggerFactory.getLogger(ItemManager.class);
@@ -100,7 +102,7 @@
* @param rootNodeDef the definition of the root node
* @param rootNodeId the id of the root node
*/
- protected ItemManager(ItemStateManager itemStateProvider, HierarchyManager hierMgr,
+ protected ItemManager(SessionItemStateManager itemStateProvider, HierarchyManager hierMgr,
SessionImpl session, NodeDefinition rootNodeDef,
NodeId rootNodeId) {
this.itemStateProvider = itemStateProvider;
@@ -111,6 +113,7 @@
// setup item cache with weak references to items
itemCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+ itemStateProvider.addListener(this);
}
/**
@@ -689,6 +692,48 @@
ps.print(" ");
}
ps.println(id + "\t" + item.safeGetJCRPath() + " (" + item + ")");
+ }
+ }
+
+ //----------------------------------------------------< ItemStateListener >
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stateCreated(ItemState created) {
+ ItemImpl item = retrieveItem(created.getId());
+ if (item != null) {
+ item.stateCreated(created);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stateModified(ItemState modified) {
+ ItemImpl item = retrieveItem(modified.getId());
+ if (item != null) {
+ item.stateModified(modified);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stateDestroyed(ItemState destroyed) {
+ ItemImpl item = retrieveItem(destroyed.getId());
+ if (item != null) {
+ item.stateDestroyed(destroyed);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stateDiscarded(ItemState discarded) {
+ ItemImpl item = retrieveItem(discarded.getId());
+ if (item != null) {
+ item.stateDiscarded(discarded);
}
}
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Thu Aug 31 02:38:17 2006
@@ -281,10 +281,6 @@
// make transient (copy-on-write)
NodeState transientState =
stateMgr.createTransientNodeState((NodeState) state, ItemState.STATUS_EXISTING_MODIFIED);
- // remove listener on persistent state
- state.removeListener(this);
- // add listener on transient state
- transientState.addListener(this);
// replace persistent with transient state
state = transientState;
} catch (ItemStateException ise) {
@@ -972,10 +968,6 @@
stateMgr.store(persistentState);
}
- // remove listener from transient state
- transientState.removeListener(this);
- // add listener to persistent state
- persistentState.addListener(this);
// tell state manager to disconnect item state
stateMgr.disconnectTransientItemState(transientState);
// swap transient state with persistent state
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Thu Aug 31 02:38:17 2006
@@ -89,10 +89,6 @@
try {
PropertyState transientState =
stateMgr.createTransientPropertyState((PropertyState) state, ItemState.STATUS_EXISTING_MODIFIED);
- // remove listener on persistent state
- state.removeListener(this);
- // add listener on transient state
- transientState.addListener(this);
// swap persistent with transient state
state = transientState;
} catch (ItemStateException ise) {
@@ -134,10 +130,6 @@
stateMgr.store(persistentState);
}
- // remove listener from transient state
- transientState.removeListener(this);
- // add listener to persistent state
- persistentState.addListener(this);
// tell state manager to disconnect item state
stateMgr.disconnectTransientItemState(transientState);
// swap transient state with persistent state
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Thu Aug 31 02:38:17 2006
@@ -30,6 +30,7 @@
import org.apache.jackrabbit.core.state.SessionItemStateManager;
import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
+import org.apache.jackrabbit.core.state.LocalItemStateManager;
import org.apache.jackrabbit.value.ValueFactoryImpl;
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.xml.DocViewSAXEventGenerator;
@@ -258,7 +259,7 @@
*
* @return session item state manager
*/
- protected SessionItemStateManager createSessionItemStateManager(UpdatableItemStateManager manager) {
+ protected SessionItemStateManager createSessionItemStateManager(LocalItemStateManager manager) {
return new SessionItemStateManager(rep.getRootNodeId(),
manager, getNamespaceResolver());
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Thu Aug 31 02:38:17 2006
@@ -95,7 +95,7 @@
* (i.e. that is isolated from transient changes made through
* the session).
*/
- protected final HierarchyManagerImpl hierMgr;
+ protected final CachingHierarchyManager hierMgr;
/**
* The <code>ObservationManager</code> instance for this session.
@@ -133,6 +133,7 @@
this.stateMgr = createItemStateManager(stateMgr);
this.hierMgr = new CachingHierarchyManager(rep.getRootNodeId(),
this.stateMgr, session.getNamespaceResolver());
+ this.stateMgr.addListener(hierMgr);
this.session = session;
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemState.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemState.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemState.java Thu Aug 31 02:38:17 2006
@@ -18,7 +18,6 @@
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.util.WeakIdentityCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,12 +25,11 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
-import java.util.Collection;
/**
* <code>ItemState</code> represents the state of an <code>Item</code>.
*/
-public abstract class ItemState implements ItemStateListener, Serializable {
+public abstract class ItemState implements Serializable {
/** Serialization UID of this class. */
static final long serialVersionUID = -1473610775880779769L;
@@ -87,9 +85,9 @@
private final boolean isTransient;
/**
- * Listeners (weak references)
+ * Parent container.
*/
- private final transient Collection listeners = new WeakIdentityCollection(5);
+ private transient ItemStateListener container;
/**
* the backing persistent item state (may be null)
@@ -173,10 +171,6 @@
* <code>LocalItemStateManager</code> when this item state has been disposed.
*/
void onDisposed() {
- // prepare this instance so it can be gc'ed
- synchronized (listeners) {
- listeners.clear();
- }
disconnect();
overlayedState = null;
status = STATUS_UNDEFINED;
@@ -192,7 +186,6 @@
}
}
this.overlayedState = overlayedState;
- this.overlayedState.addListener(this);
}
/**
@@ -203,7 +196,6 @@
if (this.overlayedState == null) {
throw new IllegalStateException("Item state cannot be reconnected because there's no underlying state to reconnect to: " + this);
}
- this.overlayedState.addListener(this);
}
/**
@@ -211,77 +203,51 @@
*/
protected void disconnect() {
if (overlayedState != null) {
- // de-register listener on overlayed state...
- overlayedState.removeListener(this);
overlayedState = null;
}
}
/**
- * Notify the listeners that the persistent state this object is
- * representing has been discarded.
+ * Return a flag indicating whether this state is connected to some other state.
+ * @return <code>true</code> if this state is connected, <code>false</code> otherwise.
+ */
+ protected boolean isConnected() {
+ return overlayedState != null;
+ }
+
+ /**
+ * Notify the parent container about changes to this state.
*/
protected void notifyStateDiscarded() {
- // copy listeners to array to avoid ConcurrentModificationException
- ItemStateListener[] la;
- synchronized (listeners) {
- la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
- }
- for (int i = 0; i < la.length; i++) {
- if (la[i] != null) {
- la[i].stateDiscarded(this);
- }
+ if (container != null) {
+ container.stateDiscarded(this);
}
}
/**
- * Notify the listeners that the persistent state this object is
- * representing has been created.
+ * Notify the parent container about changes to this state.
*/
protected void notifyStateCreated() {
- // copy listeners to array to avoid ConcurrentModificationException
- ItemStateListener[] la;
- synchronized (listeners) {
- la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
- }
- for (int i = 0; i < la.length; i++) {
- if (la[i] != null) {
- la[i].stateCreated(this);
- }
+ if (container != null) {
+ container.stateCreated(this);
}
}
/**
- * Notify the listeners that the persistent state this object is
- * representing has been updated.
+ * Notify the parent container about changes to this state.
*/
public void notifyStateUpdated() {
- // copy listeners to array to avoid ConcurrentModificationException
- ItemStateListener[] la;
- synchronized (listeners) {
- la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
- }
- for (int i = 0; i < la.length; i++) {
- if (la[i] != null) {
- la[i].stateModified(this);
- }
+ if (container != null) {
+ container.stateModified(this);
}
}
/**
- * Notify the listeners that the persistent state this object is
- * representing has been destroyed.
+ * Notify the parent container about changes to this state.
*/
protected void notifyStateDestroyed() {
- // copy listeners to array to avoid ConcurrentModificationException
- ItemStateListener[] la;
- synchronized (listeners) {
- la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
- }
- for (int i = 0; i < la.length; i++) {
- if (la[i] != null) {
- la[i].stateDestroyed(this);
- }
+ if (container != null) {
+ container.stateDestroyed(this);
}
}
@@ -427,26 +393,23 @@
}
/**
- * Add an <code>ItemStateListener</code>
- *
- * @param listener the new listener to be informed on modifications
+ * Set the parent container that will receive notifications about changes to this state.
+ * @param container container to be informed on modifications
*/
- public void addListener(ItemStateListener listener) {
- synchronized (listeners) {
- assert (!listeners.contains(listener));
- listeners.add(listener);
+ public void setContainer(ItemStateListener container) {
+ if (this.container != null) {
+ throw new IllegalStateException("State already connected to a container: " + this.container);
}
+ this.container = container;
}
/**
- * Remove an <code>ItemStateListener</code>
- *
- * @param listener an existing listener
+ * Return the parent container that will receive notifications about changes to this state. Returns
+ * <code>null</code> if none has been yet assigned.
+ * @return container or <code>null</code>
*/
- public void removeListener(ItemStateListener listener) {
- synchronized (listeners) {
- listeners.remove(listener);
- }
+ public ItemStateListener getContainer() {
+ return container;
}
/**
@@ -455,53 +418,6 @@
* @return the approximate memory consumption of this state.
*/
public abstract long calculateMemoryFootprint();
-
- //----------------------------------------------------< ItemStateListener >
- /**
- * {@inheritDoc}
- */
- public void stateCreated(ItemState created) {
- // underlying state has been permanently created
- status = STATUS_EXISTING;
- pull();
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateDestroyed(ItemState destroyed) {
- // underlying state has been permanently destroyed
- if (isTransient) {
- status = STATUS_STALE_DESTROYED;
- } else {
- status = STATUS_EXISTING_REMOVED;
- notifyStateDestroyed();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateModified(ItemState modified) {
- // underlying state has been modified
- if (isTransient) {
- status = STATUS_STALE_MODIFIED;
- } else {
- synchronized (this) {
- // this instance represents existing state, update it
- pull();
- notifyStateUpdated();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateDiscarded(ItemState discarded) {
- // underlying persistent state has been discarded, discard this instance too
- discard();
- }
//-------------------------------------------------< Serializable support >
private void writeObject(ObjectOutputStream out) throws IOException {
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemStateListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemStateListener.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemStateListener.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/ItemStateListener.java Thu Aug 31 02:38:17 2006
@@ -19,8 +19,6 @@
/**
* The <code>ItemStateListener</code> interface allows an implementing object
* to be informed about changes on an <code>ItemState</code>.
- *
- * @see ItemState#addListener
*/
public interface ItemStateListener {
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Thu Aug 31 02:38:17 2006
@@ -30,7 +30,7 @@
* persistent states from other clients.
*/
public class LocalItemStateManager
- implements UpdatableItemStateManager, ItemStateListener {
+ implements UpdatableItemStateManager, NodeStateListener {
/**
* cache of weak references to ItemState objects issued by this
@@ -59,6 +59,11 @@
private final ChangeLog changeLog = new ChangeLog();
/**
+ * State change dispatcher.
+ */
+ private final transient StateChangeDispatcher dispatcher = new StateChangeDispatcher();
+
+ /**
* Creates a new <code>LocalItemStateManager</code> instance.
* @param sharedStateMgr shared state manager
* @param factory event state collection factory
@@ -68,6 +73,8 @@
cache = new ItemStateReferenceCache();
this.sharedStateMgr = sharedStateMgr;
this.factory = factory;
+
+ sharedStateMgr.addListener(this);
}
/**
@@ -90,8 +97,8 @@
// put it in cache
cache.cache(state);
- // register as listener
- state.addListener(this);
+ // set parent container
+ state.setContainer(this);
return state;
}
@@ -115,8 +122,8 @@
// put it in cache
cache.cache(state);
- // register as listener
- state.addListener(this);
+ // set parent container
+ state.setContainer(this);
return state;
}
@@ -231,6 +238,7 @@
NodeState state = new NodeState(id, nodeTypeName, parentId,
ItemState.STATUS_NEW, false);
changeLog.added(state);
+ state.setContainer(this);
return state;
}
@@ -245,6 +253,7 @@
PropertyState state = new PropertyState(
new PropertyId(parentId, propName), ItemState.STATUS_NEW, false);
changeLog.added(state);
+ state.setContainer(this);
return state;
}
@@ -321,16 +330,14 @@
* {@inheritDoc}
*/
public void dispose() {
+ sharedStateMgr.removeListener(this);
+
// this LocalItemStateManager instance is no longer needed;
// cached item states can now be safely discarded
Iterator iter = cache.values().iterator();
while (iter.hasNext()) {
ItemState state = (ItemState) iter.next();
- // we're no longer interested in status changes of this item state
- state.removeListener(this);
- // discard item state; any remaining listeners will be informed
- // about this status change
- state.discard();
+ dispatcher.notifyStateDiscarded(state);
// let the item state know that it has been disposed
state.onDisposed();
}
@@ -338,34 +345,157 @@
cache.evictAll();
}
+ /**
+ * Add an <code>ItemStateListener</code>
+ * @param listener the new listener to be informed on modifications
+ */
+ public void addListener(ItemStateListener listener) {
+ dispatcher.addListener(listener);
+ }
+
+ /**
+ * Remove an <code>ItemStateListener</code>
+ * @param listener an existing listener
+ */
+ public void removeListener(ItemStateListener listener) {
+ dispatcher.removeListener(listener);
+ }
+
//----------------------------------------------------< ItemStateListener >
+
/**
* {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both local states that this state manager
+ * has created, as well as states that were created by the shared state manager
+ * we're listening to.
*/
public void stateCreated(ItemState created) {
+ ItemState local = null;
+ if (created.getContainer() != this) {
+ // shared state was created
+ try {
+ local = changeLog.get(created.getId());
+ if (local != null) {
+ // underlying state has been permanently created
+ local.pull();
+ local.setStatus(ItemState.STATUS_EXISTING);
+ cache.cache(local);
+ }
+ } catch (NoSuchItemStateException e) {
+ /* ignore */
+ }
+ } else {
+ // local state was created
+ local = created;
+ }
+ if (local != null) {
+ dispatcher.notifyStateCreated(created);
+ }
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both local states that this state manager
+ * has created, as well as states that were created by the shared state manager
+ * we're listening to.
*/
public void stateModified(ItemState modified) {
+ ItemState local = null;
+ if (modified.getContainer() != this) {
+ // shared state was modified
+ local = cache.retrieve(modified.getId());
+ if (local != null && local.isConnected()) {
+ // this instance represents existing state, update it
+ local.pull();
+ }
+ } else {
+ // local state was modified
+ local = modified;
+ }
+ if (local != null) {
+ dispatcher.notifyStateModified(local);
+ }
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both local states that this state manager
+ * has created, as well as states that were created by the shared state manager
+ * we're listening to.
*/
public void stateDestroyed(ItemState destroyed) {
- destroyed.removeListener(this);
-
+ ItemState local = null;
+ if (destroyed.getContainer() != this) {
+ // shared state was destroyed
+ local = cache.retrieve(destroyed.getId());
+ if (local != null && local.isConnected()) {
+ local.setStatus(ItemState.STATUS_EXISTING_REMOVED);
+ }
+ } else {
+ // local state was destroyed
+ local = destroyed;
+ }
cache.evict(destroyed.getId());
+ if (local != null) {
+ dispatcher.notifyStateDestroyed(local);
+ }
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both local states that this state manager
+ * has created, as well as states that were created by the shared state manager
+ * we're listening to.
*/
public void stateDiscarded(ItemState discarded) {
- discarded.removeListener(this);
-
+ ItemState local = null;
+ if (discarded.getContainer() != this) {
+ // shared state was discarded
+ local = cache.retrieve(discarded.getId());
+ if (local != null && local.isConnected()) {
+ local.setStatus(ItemState.STATUS_UNDEFINED);
+ }
+ } else {
+ // local state was discarded
+ local = discarded;
+ }
cache.evict(discarded.getId());
+ if (local != null) {
+ dispatcher.notifyStateDiscarded(local);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Optimization: shared state manager we're listening to does not deliver node state changes, therefore the state
+ * concerned must be a local state.
+ */
+ public void nodeAdded(NodeState state, QName name, int index, NodeId id) {
+ dispatcher.notifyNodeAdded(state, name, index, id);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Optimization: shared state manager we're listening to does not deliver node state changes, therefore the state
+ * concerned must be a local state.
+ */
+ public void nodesReplaced(NodeState state) {
+ dispatcher.notifyNodesReplaced(state);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Optimization: shared state manager we're listening to does not deliver node state changes, therefore the state
+ * concerned must be a local state.
+ */
+ public void nodeRemoved(NodeState state, QName name, int index, NodeId id) {
+ dispatcher.notifyNodeRemoved(state, name, index, id);
}
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java Thu Aug 31 02:38:17 2006
@@ -23,7 +23,6 @@
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.nodetype.NodeDefId;
import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.util.WeakIdentityCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,9 +101,9 @@
private boolean sharedPropertyNames = false;
/**
- * Listeners (weak references)
+ * Listener.
*/
- private final transient Collection listeners = new WeakIdentityCollection(3);
+ private transient NodeStateListener listener;
/**
* Constructs a new node state that is initially connected to an overlayed
@@ -736,40 +735,21 @@
}
//--------------------------------------------------< ItemState overrides >
- /**
- * {@inheritDoc}
- * <p/>
- * If the listener passed is at the same time a <code>NodeStateListener</code>
- * we add it to our list of specialized listeners.
- */
- public void addListener(ItemStateListener listener) {
- if (listener instanceof NodeStateListener) {
- synchronized (listeners) {
- if (listeners.contains(listener)) {
- log.debug("listener already registered: " + listener);
- // no need to add to call ItemState.addListener()
- return;
- } else {
- listeners.add(listener);
- }
- }
- }
- super.addListener(listener);
- }
/**
* {@inheritDoc}
* <p/>
* If the listener passed is at the same time a <code>NodeStateListener</code>
- * we remove it from our list of specialized listeners.
+ * we remember it as well.
*/
- public void removeListener(ItemStateListener listener) {
+ public void setContainer(ItemStateListener listener) {
if (listener instanceof NodeStateListener) {
- synchronized (listeners) {
- listeners.remove(listener);
+ if (this.listener != null) {
+ throw new IllegalStateException("State already connected to a listener: " + this.listener);
}
+ this.listener = (NodeStateListener) listener;
}
- super.removeListener(listener);
+ super.setContainer(listener);
}
//-------------------------------------------------< misc. helper methods >
@@ -804,15 +784,8 @@
* Notify the listeners that a child node entry has been added
*/
protected void notifyNodeAdded(ChildNodeEntry added) {
- synchronized (listeners) {
- Iterator iter = listeners.iterator();
- while (iter.hasNext()) {
- NodeStateListener l = (NodeStateListener) iter.next();
- if (l != null) {
- l.nodeAdded(this, added.getName(),
- added.getIndex(), added.getId());
- }
- }
+ if (listener != null) {
+ listener.nodeAdded(this, added.getName(), added.getIndex(), added.getId());
}
}
@@ -820,14 +793,8 @@
* Notify the listeners that the child node entries have been replaced
*/
protected void notifyNodesReplaced() {
- synchronized (listeners) {
- Iterator iter = listeners.iterator();
- while (iter.hasNext()) {
- NodeStateListener l = (NodeStateListener) iter.next();
- if (l != null) {
- l.nodesReplaced(this);
- }
- }
+ if (listener != null) {
+ listener.nodesReplaced(this);
}
}
@@ -835,15 +802,8 @@
* Notify the listeners that a child node entry has been removed
*/
protected void notifyNodeRemoved(ChildNodeEntry removed) {
- synchronized (listeners) {
- Iterator iter = listeners.iterator();
- while (iter.hasNext()) {
- NodeStateListener l = (NodeStateListener) iter.next();
- if (l != null) {
- l.nodeRemoved(this, removed.getName(),
- removed.getIndex(), removed.getId());
- }
- }
+ if (listener != null) {
+ listener.nodeRemoved(this, removed.getName(), removed.getIndex(), removed.getId());
}
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeStateListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeStateListener.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeStateListener.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeStateListener.java Thu Aug 31 02:38:17 2006
@@ -22,8 +22,6 @@
/**
* Extends the <code>ItemStateListener</code> allowing a client to be
* additionally informed about changes on a <code>NodeState</code>.
- *
- * @see NodeState#addListener
*/
public interface NodeStateListener extends ItemStateListener {
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java Thu Aug 31 02:38:17 2006
@@ -22,6 +22,7 @@
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.ZombieHierarchyManager;
+import org.apache.jackrabbit.core.PropertyId;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
@@ -37,46 +38,67 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Collection;
/**
- * <code>SessionItemStateManager</code> ...
+ * Item state manager that handles both transient and persistent items.
*/
public class SessionItemStateManager
- implements UpdatableItemStateManager, Dumpable {
+ implements UpdatableItemStateManager, Dumpable, NodeStateListener {
private static Logger log = LoggerFactory.getLogger(SessionItemStateManager.class);
/**
* State manager that allows updates
*/
- private final UpdatableItemStateManager persistentStateMgr;
+ private final UpdatableItemStateManager stateMgr;
/**
- * State manager for the transient items
+ * Hierarchy manager
*/
- private final TransientItemStateManager transientStateMgr;
+ private CachingHierarchyManager hierMgr;
/**
- * Hierarchy manager
+ * map of those states that have been removed transiently
*/
- private CachingHierarchyManager hierMgr;
+ private final ItemStateStore atticStore;
+
+ /**
+ * map of new or modified transient states
+ */
+ private final ItemStateStore transientStore;
+
+ /**
+ * ItemStateManager view of the states in the attic; lazily instantiated
+ * in {@link #getAttic()}
+ */
+ private AtticItemStateManager attic;
+
+ /**
+ * State change dispatcher.
+ */
+ private final transient StateChangeDispatcher dispatcher = new StateChangeDispatcher();
/**
* Creates a new <code>SessionItemStateManager</code> instance.
*
* @param rootNodeId
- * @param persistentStateMgr
+ * @param stateMgr
* @param nsResolver
*/
public SessionItemStateManager(NodeId rootNodeId,
- UpdatableItemStateManager persistentStateMgr,
+ LocalItemStateManager stateMgr,
NamespaceResolver nsResolver) {
- this.persistentStateMgr = persistentStateMgr;
- // create transient item state manager
- transientStateMgr = new TransientItemStateManager();
+ this.stateMgr = stateMgr;
+ stateMgr.addListener(this);
+
// create hierarchy manager that uses both transient and persistent state
hierMgr = new CachingHierarchyManager(rootNodeId, this, nsResolver);
+ addListener(hierMgr);
+
+ transientStore = new ItemStateMap();
+ atticStore = new ItemStateMap();
}
/**
@@ -95,7 +117,19 @@
public void dump(PrintStream ps) {
ps.println("SessionItemStateManager (" + this + ")");
ps.println();
- transientStateMgr.dump(ps);
+ ps.print("[transient] ");
+ if (transientStore instanceof Dumpable) {
+ ((Dumpable) transientStore).dump(ps);
+ } else {
+ ps.println(transientStore.toString());
+ }
+ ps.println();
+ ps.print("[attic] ");
+ if (atticStore instanceof Dumpable) {
+ ((Dumpable) atticStore).dump(ps);
+ } else {
+ ps.println(atticStore.toString());
+ }
ps.println();
}
@@ -107,7 +141,7 @@
throws NoSuchItemStateException, ItemStateException {
// first check if the specified item has been transiently removed
- if (transientStateMgr.getAttic().hasItemState(id)) {
+ if (atticStore.contains(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
@@ -115,17 +149,17 @@
* this will throw a NoSuchItemStateException if there's no new
* transient state
*/
- return transientStateMgr.getItemState(id);
+ return getTransientItemState(id);
}
// check if there's transient state for the specified item
- if (transientStateMgr.hasItemState(id)) {
- return transientStateMgr.getItemState(id);
+ if (transientStore.contains(id)) {
+ return getTransientItemState(id);
}
// check if there's persistent state for the specified item
- if (persistentStateMgr.hasItemState(id)) {
- return persistentStateMgr.getItemState(id);
+ if (stateMgr.hasItemState(id)) {
+ return stateMgr.getItemState(id);
}
throw new NoSuchItemStateException(id.toString());
@@ -136,20 +170,20 @@
*/
public boolean hasItemState(ItemId id) {
// first check if the specified item has been transiently removed
- if (transientStateMgr.getAttic().hasItemState(id)) {
+ if (atticStore.contains(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
* property with same name has been created);
*/
- return transientStateMgr.hasItemState(id);
+ return transientStore.contains(id);
}
// check if there's transient state for the specified item
- if (transientStateMgr.hasItemState(id)) {
+ if (transientStore.contains(id)) {
return true;
}
// check if there's persistent state for the specified item
- return persistentStateMgr.hasItemState(id);
+ return stateMgr.hasItemState(id);
}
/**
@@ -158,14 +192,14 @@
public NodeReferences getNodeReferences(NodeReferencesId id)
throws NoSuchItemStateException, ItemStateException {
- return persistentStateMgr.getNodeReferences(id);
+ return stateMgr.getNodeReferences(id);
}
/**
* {@inheritDoc}
*/
public boolean hasNodeReferences(NodeReferencesId id) {
- return persistentStateMgr.hasNodeReferences(id);
+ return stateMgr.hasNodeReferences(id);
}
//--------------------------------------------< UpdatableItemStateManager >
@@ -173,14 +207,14 @@
* {@inheritDoc}
*/
public void edit() throws IllegalStateException {
- persistentStateMgr.edit();
+ stateMgr.edit();
}
/**
* {@inheritDoc}
*/
public boolean inEditMode() {
- return persistentStateMgr.inEditMode();
+ return stateMgr.inEditMode();
}
/**
@@ -189,7 +223,7 @@
public NodeState createNew(NodeId id, QName nodeTypeName,
NodeId parentId)
throws IllegalStateException {
- return persistentStateMgr.createNew(id, nodeTypeName, parentId);
+ return stateMgr.createNew(id, nodeTypeName, parentId);
}
/**
@@ -211,7 +245,7 @@
*/
public PropertyState createNew(QName propName, NodeId parentId)
throws IllegalStateException {
- return persistentStateMgr.createNew(propName, parentId);
+ return stateMgr.createNew(propName, parentId);
}
/**
@@ -232,21 +266,21 @@
* {@inheritDoc}
*/
public void store(ItemState state) throws IllegalStateException {
- persistentStateMgr.store(state);
+ stateMgr.store(state);
}
/**
* {@inheritDoc}
*/
public void destroy(ItemState state) throws IllegalStateException {
- persistentStateMgr.destroy(state);
+ stateMgr.destroy(state);
}
/**
* {@inheritDoc}
*/
public void cancel() throws IllegalStateException {
- persistentStateMgr.cancel();
+ stateMgr.cancel();
}
/**
@@ -255,7 +289,7 @@
public void update()
throws ReferentialIntegrityException, StaleItemStateException,
ItemStateException, IllegalStateException {
- persistentStateMgr.update();
+ stateMgr.update();
}
/**
@@ -263,9 +297,9 @@
*/
public void dispose() {
// discard all transient changes
- transientStateMgr.disposeAllItemStates();
+ disposeAllTransientItemStates();
// dispose our (i.e. 'local') state manager
- persistentStateMgr.dispose();
+ stateMgr.dispose();
}
//< more methods for listing and retrieving transient ItemState instances >
@@ -278,7 +312,13 @@
*/
public ItemState getTransientItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
- return transientStateMgr.getItemState(id);
+
+ ItemState state = transientStore.get(id);
+ if (state != null) {
+ return state;
+ } else {
+ throw new NoSuchItemStateException(id.toString());
+ }
}
/**
@@ -286,7 +326,7 @@
* <code>false</code> otherwise.
*/
public boolean hasAnyTransientItemStates() {
- return transientStateMgr.hasAnyItemStates();
+ return !transientStore.isEmpty();
}
/**
@@ -306,7 +346,7 @@
*/
public Iterator getDescendantTransientItemStates(NodeId parentId)
throws InvalidItemStateException, RepositoryException {
- if (!transientStateMgr.hasAnyItemStates()) {
+ if (transientStore.isEmpty()) {
return Collections.EMPTY_LIST.iterator();
}
@@ -317,7 +357,7 @@
// the depth is used as array index
List[] la = new List[10];
try {
- Iterator iter = transientStateMgr.getEntries();
+ Iterator iter = transientStore.values().iterator();
while (iter.hasNext()) {
ItemState state = (ItemState) iter.next();
// determine relative depth: > 0 means it's a descendant
@@ -395,7 +435,7 @@
* @return an iterator over descendant transient item state instances in the attic
*/
public Iterator getDescendantTransientItemStatesInAttic(NodeId parentId) {
- if (!transientStateMgr.hasAnyItemStatesInAttic()) {
+ if (atticStore.isEmpty()) {
return Collections.EMPTY_LIST.iterator();
}
@@ -406,14 +446,14 @@
ZombieHierarchyManager zombieHierMgr =
new ZombieHierarchyManager(hierMgr.getRootNodeId(),
this,
- transientStateMgr.getAttic(),
+ getAttic(),
hierMgr.getNamespaceResolver());
// use an array of lists to group the descendants by relative depth;
// the depth is used as array index
List[] la = new List[10];
try {
- Iterator iter = transientStateMgr.getEntriesInAttic();
+ Iterator iter = atticStore.values().iterator();
while (iter.hasNext()) {
ItemState state = (ItemState) iter.next();
// determine relative depth: > 0 means it's a descendant
@@ -471,7 +511,7 @@
* <code>false</code> otherwise
*/
public boolean isItemStateInAttic(ItemId id) {
- return transientStateMgr.getAttic().hasItemState(id);
+ return atticStore.contains(id);
}
//------< methods for creating & discarding transient ItemState instances >
@@ -485,7 +525,22 @@
*/
public NodeState createTransientNodeState(NodeId id, QName nodeTypeName, NodeId parentId, int initialStatus)
throws ItemStateException {
- return transientStateMgr.createNodeState(id, nodeTypeName, parentId, initialStatus);
+
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientStore) {
+ if (transientStore.contains(id)) {
+ String msg = "there's already a node state instance with id " + id;
+ log.debug(msg);
+ throw new ItemStateException(msg);
+ }
+
+ NodeState state = new NodeState(id, nodeTypeName, parentId,
+ initialStatus, true);
+ // put transient state in the map
+ transientStore.put(state);
+ state.setContainer(this);
+ return state;
+ }
}
/**
@@ -497,9 +552,22 @@
public NodeState createTransientNodeState(NodeState overlayedState, int initialStatus)
throws ItemStateException {
- NodeState state = transientStateMgr.createNodeState(overlayedState, initialStatus);
- hierMgr.stateOverlaid(state);
- return state;
+ ItemId id = overlayedState.getNodeId();
+
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientStore) {
+ if (transientStore.contains(id)) {
+ String msg = "there's already a node state instance with id " + id;
+ log.debug(msg);
+ throw new ItemStateException(msg);
+ }
+
+ NodeState state = new NodeState(overlayedState, initialStatus, true);
+ // put transient state in the map
+ transientStore.put(state);
+ state.setContainer(this);
+ return state;
+ }
}
/**
@@ -511,7 +579,23 @@
*/
public PropertyState createTransientPropertyState(NodeId parentId, QName propName, int initialStatus)
throws ItemStateException {
- return transientStateMgr.createPropertyState(parentId, propName, initialStatus);
+
+ PropertyId id = new PropertyId(parentId, propName);
+
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientStore) {
+ if (transientStore.contains(id)) {
+ String msg = "there's already a property state instance with id " + id;
+ log.debug(msg);
+ throw new ItemStateException(msg);
+ }
+
+ PropertyState state = new PropertyState(id, initialStatus, true);
+ // put transient state in the map
+ transientStore.put(state);
+ state.setContainer(this);
+ return state;
+ }
}
/**
@@ -523,9 +607,22 @@
public PropertyState createTransientPropertyState(PropertyState overlayedState, int initialStatus)
throws ItemStateException {
- PropertyState state = transientStateMgr.createPropertyState(overlayedState, initialStatus);
- hierMgr.stateOverlaid(state);
- return state;
+ PropertyId id = overlayedState.getPropertyId();
+
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientStore) {
+ if (transientStore.contains(id)) {
+ String msg = "there's already a property state instance with id " + id;
+ log.debug(msg);
+ throw new ItemStateException(msg);
+ }
+
+ PropertyState state = new PropertyState(overlayedState, initialStatus, true);
+ // put transient state in the map
+ transientStore.put(state);
+ state.setContainer(this);
+ return state;
+ }
}
/**
@@ -536,7 +633,6 @@
* be disconnected
*/
public void disconnectTransientItemState(ItemState state) {
- hierMgr.stateUncovered(state);
state.disconnect();
}
@@ -549,7 +645,13 @@
* @see ItemState#discard()
*/
public void disposeTransientItemState(ItemState state) {
- transientStateMgr.disposeItemState(state);
+ // discard item state, this will invalidate the wrapping Item
+ // instance of the transient state
+ state.discard();
+ // remove from map
+ transientStore.remove(state.getId());
+ // give the instance a chance to prepare to get gc'ed
+ state.onDisposed();
}
/**
@@ -560,7 +662,10 @@
* be moved to the attic
*/
public void moveTransientItemStateToAttic(ItemState state) {
- transientStateMgr.moveItemStateToAttic(state);
+ // remove from map
+ transientStore.remove(state.getId());
+ // add to attic
+ atticStore.put(state);
}
/**
@@ -571,13 +676,229 @@
* be disposed @see ItemState#discard()
*/
public void disposeTransientItemStateInAttic(ItemState state) {
- transientStateMgr.disposeItemStateInAttic(state);
+ // discard item state, this will invalidate the wrapping Item
+ // instance of the transient state
+ state.discard();
+ // remove from attic
+ atticStore.remove(state.getId());
+ // give the instance a chance to prepare to get gc'ed
+ state.onDisposed();
}
/**
* Disposes all transient item states in the cache and in the attic.
*/
public void disposeAllTransientItemStates() {
- transientStateMgr.disposeAllItemStates();
+ // dispose item states in transient map & attic
+ // (use temp collection to avoid ConcurrentModificationException)
+ Collection tmp = new ArrayList(transientStore.values());
+ Iterator iter = tmp.iterator();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ disposeTransientItemState(state);
+ }
+ tmp = new ArrayList(atticStore.values());
+ iter = tmp.iterator();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ disposeTransientItemStateInAttic(state);
+ }
+ }
+
+ /**
+ * Add an <code>ItemStateListener</code>
+ * @param listener the new listener to be informed on modifications
+ */
+ public void addListener(ItemStateListener listener) {
+ dispatcher.addListener(listener);
+ }
+
+ /**
+ * Remove an <code>ItemStateListener</code>
+ * @param listener an existing listener
+ */
+ public void removeListener(ItemStateListener listener) {
+ dispatcher.removeListener(listener);
+ }
+
+ /**
+ * Return the attic item state provider that holds all items
+ * moved into the attic.
+ *
+ * @return attic
+ */
+ ItemStateManager getAttic() {
+ if (attic == null) {
+ attic = new AtticItemStateManager();
+ }
+ return attic;
+ }
+
+ //----------------------------------------------------< ItemStateListener >
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both transient states that this state manager
+ * has created, as well as states that were created by the local state manager
+ * we're listening to.
+ */
+ public void stateCreated(ItemState created) {
+ ItemState visibleState = created;
+ if (created.getContainer() != this) {
+ // local state was created
+ ItemState transientState = transientStore.get(created.getId());
+ if (transientState != null) {
+ // underlying state has been permanently created
+ transientState.pull();
+ transientState.setStatus(ItemState.STATUS_EXISTING);
+ visibleState = transientState;
+ }
+ }
+ dispatcher.notifyStateCreated(visibleState);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both transient states that this state manager
+ * has created, as well as states that were created by the local state manager
+ * we're listening to.
+ */
+ public void stateModified(ItemState modified) {
+ ItemState visibleState = modified;
+ if (modified.getContainer() != this) {
+ // local state was modified
+ ItemState transientState = transientStore.get(modified.getId());
+ if (transientState != null) {
+ transientState.setStatus(ItemState.STATUS_STALE_MODIFIED);
+ visibleState = transientState;
+ }
+ }
+ dispatcher.notifyStateModified(visibleState);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both transient states that this state manager
+ * has created, as well as states that were created by the local state manager
+ * we're listening to.
+ */
+ public void stateDestroyed(ItemState destroyed) {
+ ItemState visibleState = destroyed;
+ if (destroyed.getContainer() != this) {
+ // local state was destroyed
+ ItemState transientState = transientStore.get(destroyed.getId());
+ if (transientState != null) {
+ transientState.setStatus(ItemState.STATUS_STALE_DESTROYED);
+ visibleState = transientState;
+ }
+ }
+ dispatcher.notifyStateDestroyed(visibleState);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Notification handler gets called for both transient states that this state manager
+ * has created, as well as states that were created by the local state manager
+ * we're listening to.
+ */
+ public void stateDiscarded(ItemState discarded) {
+ ItemState visibleState = discarded;
+ if (discarded.getContainer() != this) {
+ // local state was discarded
+ ItemState transientState = transientStore.get(discarded.getId());
+ if (transientState != null) {
+ transientState.setStatus(ItemState.STATUS_UNDEFINED);
+ visibleState = transientState;
+ }
+ }
+ dispatcher.notifyStateDiscarded(visibleState);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Pass notification to listeners if a transient state was modified
+ * or if the local state is not overlayed.
+ */
+ public void nodeAdded(NodeState state, QName name, int index, NodeId id) {
+ if (state.getContainer() == this || !transientStore.contains(state.getId())) {
+ dispatcher.notifyNodeAdded(state, name, index, id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Pass notification to listeners if a transient state was modified
+ * or if the local state is not overlayed.
+ */
+ public void nodesReplaced(NodeState state) {
+ if (state.getContainer() == this || !transientStore.contains(state.getId())) {
+ dispatcher.notifyNodesReplaced(state);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Pass notification to listeners if a transient state was modified
+ * or if the local state is not overlayed.
+ */
+ public void nodeRemoved(NodeState state, QName name, int index, NodeId id) {
+ if (state.getContainer() == this || !transientStore.contains(state.getId())) {
+ dispatcher.notifyNodeRemoved(state, name, index, id);
+ }
+ }
+
+ //--------------------------------------------------------< inner classes >
+
+ /**
+ * ItemStateManager view of the states in the attic
+ *
+ * @see SessionItemStateManager#getAttic
+ */
+ private class AtticItemStateManager implements ItemStateManager {
+
+ /**
+ * {@inheritDoc}
+ */
+ public ItemState getItemState(ItemId id)
+ throws NoSuchItemStateException, ItemStateException {
+
+ ItemState state = atticStore.get(id);
+ if (state != null) {
+ return state;
+ } else {
+ throw new NoSuchItemStateException(id.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasItemState(ItemId id) {
+ return atticStore.contains(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NodeReferences getNodeReferences(NodeReferencesId id)
+ throws NoSuchItemStateException, ItemStateException {
+ // n/a
+ throw new ItemStateException("getNodeReferences() not implemented");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasNodeReferences(NodeReferencesId id) {
+ // n/a
+ return false;
+ }
}
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Thu Aug 31 02:38:17 2006
@@ -156,6 +156,11 @@
private boolean noLockHack = false;
/**
+ * State change dispatcher.
+ */
+ private final transient StateChangeDispatcher dispatcher = new StateChangeDispatcher();
+
+ /**
* Read-/Write-Lock to synchronize access on this item state manager.
*/
private final ReadWriteLock rwLock =
@@ -340,34 +345,57 @@
}
//----------------------------------------------------< ItemStateListener >
+
/**
* {@inheritDoc}
+ * <p/>
+ * Notifications are received for items that this manager created itself or items that are
+ * managed by one of the virtual providers.
*/
public void stateCreated(ItemState created) {
- cache.cache(created);
+ if (created.getContainer() == this) {
+ // shared state was created
+ cache.cache(created);
+ }
+ dispatcher.notifyStateCreated(created);
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notifications are received for items that this manager created itself or items that are
+ * managed by one of the virtual providers.
*/
public void stateModified(ItemState modified) {
- // not interested
+ dispatcher.notifyStateModified(modified);
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notifications are received for items that this manager created itself or items that are
+ * managed by one of the virtual providers.
*/
public void stateDestroyed(ItemState destroyed) {
- destroyed.removeListener(this);
- cache.evict(destroyed.getId());
+ if (destroyed.getContainer() == this) {
+ // shared state was destroyed
+ cache.evict(destroyed.getId());
+ }
+ dispatcher.notifyStateDestroyed(destroyed);
}
/**
* {@inheritDoc}
+ * <p/>
+ * Notifications are received for items that this manager created itself or items that are
+ * managed by one of the virtual providers.
*/
public void stateDiscarded(ItemState discarded) {
- discarded.removeListener(this);
- cache.evict(discarded.getId());
+ if (discarded.getContainer() == this) {
+ // shared state was discarded
+ cache.evict(discarded.getId());
+ }
+ dispatcher.notifyStateDiscarded(discarded);
}
//-------------------------------------------------------------< Dumpable >
@@ -405,6 +433,8 @@
System.arraycopy(virtualProviders, 0, provs, 0, virtualProviders.length);
provs[virtualProviders.length] = prov;
virtualProviders = provs;
+
+ prov.addListener(this);
}
/**
@@ -717,7 +747,24 @@
beginUpdate(local, factory, null).end();
}
+ /**
+ * Add an <code>ItemStateListener</code>
+ * @param listener the new listener to be informed on modifications
+ */
+ public void addListener(ItemStateListener listener) {
+ dispatcher.addListener(listener);
+ }
+
+ /**
+ * Remove an <code>ItemStateListener</code>
+ * @param listener an existing listener
+ */
+ public void removeListener(ItemStateListener listener) {
+ dispatcher.removeListener(listener);
+ }
+
//-------------------------------------------------------< implementation >
+
/**
* Create a new node state instance
*
@@ -733,7 +780,7 @@
state.setNodeTypeName(nodeTypeName);
state.setParentId(parentId);
state.setStatus(ItemState.STATUS_NEW);
- state.addListener(this);
+ state.setContainer(this);
return state;
}
@@ -810,8 +857,8 @@
state.setStatus(ItemState.STATUS_EXISTING);
// put it in cache
cache.cache(state);
- // register as listener
- state.addListener(this);
+ // set parent container
+ state.setContainer(this);
}
return state;
}
@@ -863,7 +910,7 @@
private PropertyState createInstance(QName propName, NodeId parentId) {
PropertyState state = persistMgr.createNew(new PropertyId(parentId, propName));
state.setStatus(ItemState.STATUS_NEW);
- state.addListener(this);
+ state.setContainer(this);
return state;
}
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/StateChangeDispatcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/StateChangeDispatcher.java?rev=438851&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/StateChangeDispatcher.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/StateChangeDispatcher.java Thu Aug 31 02:38:17 2006
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.util.WeakIdentityCollection;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.core.NodeId;
+
+import java.util.Collection;
+
+/**
+ * Component that holds weak references to listeners interested in changes to item states and dispatches notifications.
+ */
+public class StateChangeDispatcher {
+
+ /**
+ * Simple item state listeners (weak references)
+ */
+ private final transient Collection listeners = new WeakIdentityCollection(5);
+
+ /**
+ * Node state listeners (weak references)
+ */
+ private final transient Collection nsListeners = new WeakIdentityCollection(5);
+
+ /**
+ * Add an <code>ItemStateListener</code>.
+ * @param listener the new listener to be informed on modifications
+ */
+ public void addListener(ItemStateListener listener) {
+ synchronized (listeners) {
+ assert (!listeners.contains(listener));
+ listeners.add(listener);
+ }
+ if (listener instanceof NodeStateListener) {
+ synchronized (nsListeners) {
+ assert (!nsListeners.contains(listener));
+ nsListeners.add(listener);
+ }
+ }
+ }
+
+ /**
+ * Remove an <code>ItemStateListener</code>
+ * @param listener an existing listener
+ */
+ public void removeListener(ItemStateListener listener) {
+ if (listener instanceof NodeStateListener) {
+ synchronized (nsListeners) {
+ nsListeners.remove(listener);
+ }
+ }
+ synchronized (listeners) {
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param created created state.
+ */
+ public void notifyStateCreated(ItemState created) {
+ ItemStateListener[] la;
+ synchronized (listeners) {
+ la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateCreated(created);
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param modified modified state.
+ */
+ public void notifyStateModified(ItemState modified) {
+ ItemStateListener[] la;
+ synchronized (listeners) {
+ la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateModified(modified);
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param destroyed destroyed state.
+ */
+ public void notifyStateDestroyed(ItemState destroyed) {
+ ItemStateListener[] la;
+ synchronized (listeners) {
+ la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateDestroyed(destroyed);
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param discarded discarded state.
+ */
+ public void notifyStateDiscarded(ItemState discarded) {
+ ItemStateListener[] la;
+ synchronized (listeners) {
+ la = (ItemStateListener[]) listeners.toArray(new ItemStateListener[listeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateDiscarded(discarded);
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param state node state that changed
+ * @param name name of node that was added
+ * @param index index of new node
+ * @param id id of new node
+ */
+ public void notifyNodeAdded(NodeState state, QName name, int index, NodeId id) {
+ // small optimization as there are only a few clients interested in node state modifications
+ if (!nsListeners.isEmpty()) {
+ NodeStateListener[] la;
+ synchronized (nsListeners) {
+ la = (NodeStateListener[]) nsListeners.toArray(new NodeStateListener[nsListeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].nodeAdded(state, name, index, id);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param state node state that changed
+ */
+ public void notifyNodesReplaced(NodeState state) {
+ // small optimization as there are only a few clients interested in node state modifications
+ if (!nsListeners.isEmpty()) {
+ NodeStateListener[] la;
+ synchronized (nsListeners) {
+ la = (NodeStateListener[]) nsListeners.toArray(new NodeStateListener[nsListeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].nodesReplaced(state);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notify listeners about changes to some state.
+ * @param state node state that changed
+ * @param name name of node that was added
+ * @param index index of new node
+ * @param id id of new node
+ */
+ public void notifyNodeRemoved(NodeState state, QName name, int index, NodeId id) {
+ // small optimization as there are only a few clients interested in node state modifications
+ if (!nsListeners.isEmpty()) {
+ NodeStateListener[] la;
+ synchronized (nsListeners) {
+ la = (NodeStateListener[]) nsListeners.toArray(new NodeStateListener[nsListeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].nodeRemoved(state, name, index, id);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/InternalVersionItemImpl.java Thu Aug 31 02:38:17 2006
@@ -23,7 +23,7 @@
/**
* Implements a <code>InternalVersionItem</code>.
*/
-abstract class InternalVersionItemImpl implements InternalVersionItem, ItemStateListener {
+abstract class InternalVersionItemImpl implements InternalVersionItem {
/**
* the underlying persistance node
@@ -43,10 +43,6 @@
protected InternalVersionItemImpl(AbstractVersionManager vMgr, NodeStateEx node) {
this.vMgr = vMgr;
this.node = node;
- // register as listener. this is not the best solution since this item
- // could be discarded by the GC and then later be recreated. this will
- // unnecessarily increase the number of listeners.
- node.getState().addListener(this);
}
/**
@@ -71,41 +67,4 @@
* @return the parent version item or <code>null</code>.
*/
public abstract InternalVersionItem getParent();
-
- //-----------------------------------------------------< ItemStateListener >
- // handle notifications from underlying item states. currently, we only need
- // to care about removals, since the versioning items do not cache their
- // values
-
- /**
- * {@inheritDoc}
- */
- public void stateCreated(ItemState item) {
- // ignore
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateModified(ItemState item) {
- // ignore
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateDestroyed(ItemState item) {
- vMgr.itemDiscarded(this);
- }
-
- /**
- * {@inheritDoc}
- */
- public void stateDiscarded(ItemState item) {
- // ignore
- }
-
-
-
-
}
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java?rev=438851&r1=438850&r2=438851&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java Thu Aug 31 02:38:17 2006
@@ -73,8 +73,12 @@
this.vMgr = vMgr;
this.stateMgr = stateMgr;
this.historyRootId = vMgr.getHistoryRootId();
+
+ stateMgr.addListener(this);
}
+ //------------------------------------------< VirtualItemStateProvider >---
+
/**
* @inheritDoc
*/
@@ -117,9 +121,6 @@
if (item == null) {
item = stateMgr.getItemState(id);
items.put(id, item);
-
- // attach us as listener
- item.addListener(this);
}
return item;
}
@@ -152,6 +153,22 @@
public boolean hasNodeReferences(NodeReferencesId id) {
return stateMgr.hasNodeReferences(id);
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addListener(ItemStateListener listener) {
+ stateMgr.addListener(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeListener(ItemStateListener listener) {
+ stateMgr.removeListener(listener);
+ }
+
+ //-------------------------------------------------< ItemStateListener >---
/**
* @inheritDoc