You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/10/26 13:02:04 UTC
svn commit: r467956 [1/3] - in
/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi:
./ state/ version/
Author: angela
Date: Thu Oct 26 04:02:02 2006
New Revision: 467956
URL: http://svn.apache.org/viewvc?view=rev&rev=467956
Log:
work in progress
- version always protected
- versionHistory always protected
- fix Node.getReferences && reference properties
- mixinTypes are 'active' upon save only (and not before). therefore
cleanup after removeMixin is done only after save.
adding new states defined by a new mixin are only added after the
node has been saved.
- nodestates identified by a uuid only were created a second time upon
ChildNodeEntry.resolve => fix needs to be improved
- Events/ChangeLog are processed by the save-target state
- ChangeLog.persisted not used any more
Added:
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java (with props)
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java (with props)
Modified:
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
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/ChangeLog.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java Thu Oct 26 04:02:02 2006
@@ -21,8 +21,6 @@
import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
import org.apache.jackrabbit.jcr2spi.state.StaleItemStateException;
import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
-import org.apache.jackrabbit.jcr2spi.state.NodeState;
-import org.apache.jackrabbit.jcr2spi.state.PropertyState;
import org.apache.jackrabbit.jcr2spi.state.ItemStateLifeCycleListener;
import org.apache.jackrabbit.jcr2spi.state.Status;
import org.apache.jackrabbit.jcr2spi.operation.Remove;
@@ -30,7 +28,6 @@
import org.apache.jackrabbit.jcr2spi.util.LogUtil;
import org.apache.jackrabbit.name.NoPrefixDeclaredException;
import org.apache.jackrabbit.name.Path;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.PathFormat;
import org.slf4j.LoggerFactory;
@@ -88,7 +85,7 @@
notifyCreated();
// add this item as listener to events of the underlying state object
- this.state.addListener(this);
+ state.addListener(this);
}
//-----------------------------------------------------< Item interface >---
@@ -457,11 +454,9 @@
*
* @throws UnsupportedRepositoryOperationException
* @throws RepositoryException
- * @see ItemStateValidator#checkAddNode(NodeState, QName, QName, int)
- * @see ItemStateValidator#checkAddProperty(NodeState, QName, QPropertyDefinition, int)
- * @see ItemStateValidator#checkSetProperty(PropertyState, int)
+ * @see ItemStateValidator
*/
- void checkIsWritable() throws UnsupportedRepositoryOperationException, ConstraintViolationException, RepositoryException {
+ protected void checkIsWritable() throws UnsupportedRepositoryOperationException, ConstraintViolationException, RepositoryException {
checkSupportedOption(Repository.LEVEL_2_SUPPORTED);
checkStatus();
}
@@ -491,7 +486,7 @@
*
* @return state associated with this <code>Item</code>
*/
- ItemState getItemState() {
+ protected ItemState getItemState() {
return state;
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Thu Oct 26 04:02:02 2006
@@ -375,7 +375,7 @@
public Property setProperty(String name, String value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
Value v = (value == null) ? null : session.getValueFactory().createValue(value, type);
- return setProperty(name, v);
+ return setProperty(name, v, type);
}
/**
@@ -384,7 +384,7 @@
public Property setProperty(String name, InputStream value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
Value v = (value == null ? null : session.getValueFactory().createValue(value));
- return setProperty(name, v);
+ return setProperty(name, v, PropertyType.BINARY);
}
/**
@@ -392,7 +392,7 @@
*/
public Property setProperty(String name, boolean value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
- return setProperty(name, session.getValueFactory().createValue(value));
+ return setProperty(name, session.getValueFactory().createValue(value), PropertyType.BOOLEAN);
}
/**
@@ -400,7 +400,7 @@
*/
public Property setProperty(String name, double value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
- return setProperty(name, session.getValueFactory().createValue(value));
+ return setProperty(name, session.getValueFactory().createValue(value), PropertyType.DOUBLE);
}
/**
@@ -408,7 +408,7 @@
*/
public Property setProperty(String name, long value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
- return setProperty(name, session.getValueFactory().createValue(value));
+ return setProperty(name, session.getValueFactory().createValue(value), PropertyType.LONG);
}
/**
@@ -417,16 +417,24 @@
public Property setProperty(String name, Calendar value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
// validation performed in subsequent method
Value v = (value == null ? null : session.getValueFactory().createValue(value));
- return setProperty(name, v);
+ return setProperty(name, v, PropertyType.DATE);
}
/**
* @see Node#setProperty(String, Node)
*/
public Property setProperty(String name, Node value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- // validation performed in subsequent method
- Value v = (value == null ? null : session.getValueFactory().createValue(value));
- return setProperty(name, v);
+ // duplicate check to make sure, writability is asserted before value
+ // validation below.
+ checkIsWritable();
+ Value v;
+ if (value == null) {
+ v = null;
+ } else {
+ PropertyImpl.checkValidReference(value, PropertyType.REFERENCE, this);
+ v = session.getValueFactory().createValue(value);
+ }
+ return setProperty(name, v, PropertyType.REFERENCE);
}
/**
@@ -536,11 +544,12 @@
*/
public String getUUID() throws UnsupportedRepositoryOperationException, RepositoryException {
checkStatus();
- if (!isNodeType(QName.MIX_REFERENCEABLE)) {
+ String uuid = getNodeState().getUUID();
+ if (!isNodeType(QName.MIX_REFERENCEABLE) && uuid != null) {
throw new UnsupportedRepositoryOperationException();
}
// Node is referenceable -> NodeId must contain a UUID part
- return getNodeId().getUUID();
+ return uuid;
}
/**
@@ -574,12 +583,12 @@
checkStatus();
try {
ItemStateManager itemStateMgr = session.getItemStateManager();
- if (itemStateMgr.hasReferingStates(getNodeState())) {
- Collection refStates = itemStateMgr.getReferingStates(getNodeState());
- return new LazyItemIterator(itemMgr, refStates);
- } else {
+ Collection refStates = itemStateMgr.getReferingStates(getNodeState());
+ if (refStates.isEmpty()) {
// there are no references, return empty iterator
return IteratorHelper.EMPTY;
+ } else {
+ return new LazyItemIterator(itemMgr, refStates);
}
} catch (ItemStateException e) {
String msg = "Unable to retrieve REFERENCE properties that refer to " + safeGetJCRPath();
@@ -754,6 +763,9 @@
} catch (VersionException e) {
log.debug("Cannot add mixin '" + mixinName + "': " + e.getMessage());
return false;
+ } catch (ConstraintViolationException e) {
+ log.debug("Cannot add mixin '" + mixinName + "': " + e.getMessage());
+ return false;
}
}
@@ -991,7 +1003,7 @@
checkSessionHasPendingChanges();
// check for version-enabled and lock are performed with subsequent calls.
Version v = getVersionHistory().getVersion(versionName);
- restore(v, removeExisting);
+ restore(this, null, v, removeExisting);
}
/**
@@ -1074,10 +1086,6 @@
* @throws RepositoryException
*/
private void restore(NodeImpl targetNode, Path relQPath, Version version, boolean removeExisting) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
- targetNode.checkIsWritable();
- targetNode.checkIsLocked();
-
-
if (relQPath == null) {
/* restore target already exists. */
// target must be versionable
@@ -1092,6 +1100,8 @@
if (vH.getRootVersion().isSame(version)) {
throw new VersionException("Attempt to restore root version.");
}
+ targetNode.checkIsWritable();
+ targetNode.checkIsLocked();
} else {
/* If no node exists at relPath then a VersionException is thrown if
the parent node is not checked out. */
@@ -1101,6 +1111,7 @@
+ LogUtil.safeGetJCRPath(relQPath, session.getNamespaceResolver())
+ "' must be checked out.");
}
+ targetNode.checkIsLocked();
// NOTE: check for nodetype constraint violation is left to the 'server'
}
@@ -1270,7 +1281,7 @@
if (!isNodeType(QName.MIX_LOCKABLE)) {
String msg = "Unable to perform locking operation on non-lockable node: " + getPath();
log.debug(msg);
- throw new UnsupportedRepositoryOperationException(msg);
+ throw new LockException(msg);
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/PropertyImpl.java Thu Oct 26 04:02:02 2006
@@ -262,23 +262,9 @@
if (value == null) {
setInternalValues(null, reqType);
} else {
- if (reqType == PropertyType.REFERENCE) {
- if (value instanceof NodeImpl) {
- NodeImpl targetNode = (NodeImpl)value;
- if (targetNode.isNodeType(QName.MIX_REFERENCEABLE)) {
- QValue qValue = QValue.create(targetNode.getUUID(), PropertyType.REFERENCE);
- setInternalValues(new QValue[]{qValue}, reqType);
- } else {
- throw new ValueFormatException("Target node must be of node type mix:referenceable");
- }
- } else {
- String msg = "Incompatible Node object: " + value + "(" + safeGetJCRPath() + ")";
- log.debug(msg);
- throw new RepositoryException(msg);
- }
- } else {
- throw new ValueFormatException("Property must be of type REFERENCE (" + safeGetJCRPath() + ")");
- }
+ checkValidReference(value, reqType, this);
+ QValue qValue = QValue.create(((NodeImpl)value).getUUID(), PropertyType.REFERENCE);
+ setInternalValues(new QValue[]{qValue}, reqType);
}
}
@@ -477,7 +463,7 @@
*/
private QValue getQValue() throws ValueFormatException, RepositoryException {
checkStatus();
- if (isMultiple()) {
+ if (isMultiple()) {
throw new ValueFormatException(safeGetJCRPath() + " is multi-valued and can therefore only be retrieved as an array of values");
}
// avoid unnecessary object creation if possible
@@ -553,5 +539,30 @@
*/
private PropertyState getPropertyState() {
return (PropertyState) getItemState();
+ }
+
+ /**
+ *
+ * @param value
+ * @param propertyType
+ * @param itemImpl
+ * @throws ValueFormatException
+ * @throws RepositoryException
+ */
+ static void checkValidReference(Node value, int propertyType, ItemImpl itemImpl) throws ValueFormatException, RepositoryException {
+ if (propertyType == PropertyType.REFERENCE) {
+ if (value instanceof NodeImpl) {
+ NodeImpl targetNode = (NodeImpl)value;
+ if (!targetNode.isNodeType(QName.MIX_REFERENCEABLE)) {
+ throw new ValueFormatException("Target node must be of node type mix:referenceable");
+ }
+ } else {
+ String msg = "Incompatible Node object: " + value + "(" + itemImpl.safeGetJCRPath() + ")";
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ } else {
+ throw new ValueFormatException("Property must be of type REFERENCE (" + itemImpl.safeGetJCRPath() + ")");
+ }
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Thu Oct 26 04:02:02 2006
@@ -545,7 +545,8 @@
* of a workspace operation. In that case there are no
* local transient changes.
*/
- private void onEventReceived(EventIterator events, boolean isLocal, ChangeLog changeLog) {
+ private void onEventReceived(EventIterator events, boolean isLocal,
+ ChangeLog changeLog) {
// notify listener
// need to copy events into a list because we notify multiple listeners
List eventList = new ArrayList();
@@ -832,7 +833,7 @@
public void visit(LockOperation operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.lock(sessionInfo, nId, operation.isDeep());
+ events = service.lock(sessionInfo, nId, operation.isDeep(), operation.isSessionScoped());
}
public void visit(LockRefresh operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
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?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- 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 Thu Oct 26 04:02:02 2006
@@ -21,12 +21,9 @@
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.PropertyId;
-import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.commons.collections.map.LRUMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Map;
import java.util.Collection;
import java.util.Iterator;
import java.util.Collections;
@@ -51,14 +48,9 @@
private final ItemStateFactory isf;
/**
- * Maps a String uuid to a {@link NodeState}.
+ * Cache
*/
- private final Map uuid2NodeState;
-
- /**
- * Map of recently used <code>ItemState</code>.
- */
- private final Map recentlyUsed;
+ private final ItemStateCache cache;
/**
* The root node of the workspace or <code>null</code> if it has not been
@@ -72,12 +64,6 @@
private final IdFactory idFactory;
/**
- * An {@link ItemStateLifeCycleListener} to maintain the LRU and UUID
- * reference cache.
- */
- private final ItemStateLifeCycleListener lifeCycleListener;
-
- /**
* Creates a new <code>CachingItemStateManager</code>.
*
* @param isf the item state factory to create item state instances.
@@ -86,9 +72,9 @@
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
- this.lifeCycleListener = new ISLifeCycleListener();
+ this.cache = new ItemStateCache();
+
+ isf.setCache(cache);
}
//---------------------------------------------------< ItemStateManager >---
@@ -96,10 +82,6 @@
public NodeState getRootState() throws ItemStateException {
if (root == null) {
root = isf.createRootState(this);
- if (root.getUUID() != null) {
- uuid2NodeState.put(root.getUUID(), root);
- }
- root.addListener(lifeCycleListener);
}
return root;
}
@@ -131,16 +113,16 @@
* @param nodeState
*/
public Collection getReferingStates(NodeState nodeState) throws ItemStateException {
- if (hasReferingStates(nodeState)) {
- Set refStates = new HashSet();
- Iterator it = nodeState.getNodeReferences().iterator();
- while (it.hasNext()) {
- PropertyId pId = (PropertyId) it.next();
- refStates.add(getItemState(pId));
- }
- return Collections.unmodifiableCollection(refStates);
- } else {
+ Set refStates = new HashSet();
+ Iterator it = nodeState.getNodeReferences().iterator();
+ while (it.hasNext()) {
+ PropertyId pId = (PropertyId) it.next();
+ refStates.add(getItemState(pId));
+ }
+ if (refStates.isEmpty()) {
return Collections.EMPTY_SET;
+ } else {
+ return Collections.unmodifiableCollection(refStates);
}
}
@@ -151,7 +133,7 @@
*/
public boolean hasReferingStates(NodeState nodeState) {
NodeReferences nr = nodeState.getNodeReferences();
- return nr != null && !nr.isEmpty();
+ return !nr.isEmpty();
}
//------------------------------< internal >--------------------------------
@@ -164,16 +146,6 @@
}
/**
- * Called whenever an item state is accessed. Calling this method will update
- * the LRU map which keeps track of most recently used item states.
- *
- * @param state the touched state.
- */
- protected void touch(ItemState state) {
- recentlyUsed.put(state, state);
- }
-
- /**
* Resolves the id into an <code>ItemState</code>.
*
* @param id the id of the <code>ItemState</code> to resolve.
@@ -189,13 +161,11 @@
NodeState nodeState;
// resolve uuid part
if (uuid != null) {
- nodeState = (NodeState) uuid2NodeState.get(uuid);
+ nodeState = cache.getNodeState(uuid);
if (nodeState == null) {
- // state identified by the uuid is not yet cached -> get from ISM
+ // state identified by the uuid is not yet cached -> get from ISF
NodeId refId = (path == null) ? (NodeId) id : idFactory.createNodeId(uuid);
nodeState = isf.createNodeState(refId, this);
- nodeState.addListener(lifeCycleListener);
- uuid2NodeState.put(uuid, nodeState);
}
} else {
// start with root node if no uuid part in id
@@ -206,7 +176,6 @@
if (path != null) {
s = PathResolver.resolve(nodeState, path);
}
- touch(s);
return s;
}
@@ -222,7 +191,7 @@
ItemState state;
// resolve UUID
if (id.getUUID() != null) {
- state = (ItemState) uuid2NodeState.get(id.getUUID());
+ state = cache.getNodeState(id.getUUID());
if (state == null) {
// not cached
return null;
@@ -248,23 +217,5 @@
}
return state;
- }
-
- //-----------------------------------------< ItemStateLifeCycleListener >---
-
- private class ISLifeCycleListener implements ItemStateLifeCycleListener {
-
- public void statusChanged(ItemState state, int previousStatus) {
- if (state.getStatus() == Status.REMOVED ||
- state.getStatus() == Status.STALE_DESTROYED) {
- recentlyUsed.remove(state);
- if (state.isNode()) {
- NodeState nodeState = (NodeState) state;
- if (nodeState.getUUID() != null) {
- uuid2NodeState.remove(nodeState.getUUID());
- }
- }
- }
- }
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java Thu Oct 26 04:02:02 2006
@@ -238,28 +238,6 @@
//-----------------------------< Inform ChangeLog about Success/Failure >---
/**
- * After the states have actually been persisted, update their
- * internal states and notify listeners.
- */
- public void persisted() {
- Iterator iter = modifiedStates();
- while (iter.hasNext()) {
- ItemState state = (ItemState) iter.next();
- state.setStatus(Status.EXISTING);
- }
- iter = deletedStates();
- while (iter.hasNext()) {
- ItemState state = (ItemState) iter.next();
- state.setStatus(Status.REMOVED);
- }
- iter = addedStates();
- while (iter.hasNext()) {
- ItemState state = (ItemState) iter.next();
- state.setStatus(Status.EXISTING);
- }
- }
-
- /**
* Reset this change log, removing all members inside the
* maps we built.
*/
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java Thu Oct 26 04:02:02 2006
@@ -31,6 +31,8 @@
import javax.jcr.RepositoryException;
import java.util.Collection;
import java.util.Set;
+import java.util.Iterator;
+import java.util.Collections;
/**
* <code>ItemState</code> represents the state of an <code>Item</code>.
@@ -44,7 +46,7 @@
/**
* Flag used to distinguish workspace states from session states. The first
- * accepts call to {@link #refresh(Event, ChangeLog)}, while the latter
+ * accepts call to {@link #refresh(Event)}, while the latter
* will be able to handle the various methods related to transient
* modifications.
*/
@@ -67,6 +69,12 @@
final IdFactory idFactory;
/**
+ * The <code>ItemStateFactory</code> which is used to create new
+ * <code>ItemState</code> instances.
+ */
+ final ItemStateFactory isf;
+
+ /**
* The parent <code>NodeState</code> or <code>null</code> if this
* instance represents the root node.
*/
@@ -83,7 +91,7 @@
* @param parent
* @param initialStatus the initial status of the item state object
*/
- protected ItemState(NodeState parent, int initialStatus, IdFactory idFactory,
+ protected ItemState(NodeState parent, int initialStatus, ItemStateFactory isf, IdFactory idFactory,
boolean isWorkspaceState) {
switch (initialStatus) {
case Status.EXISTING:
@@ -99,6 +107,7 @@
overlayedState = null;
this.idFactory = idFactory;
+ this.isf = isf;
this.isWorkspaceState = isWorkspaceState;
}
@@ -110,7 +119,7 @@
* @param initialStatus the initial status of the new <code>ItemState</code> instance
*/
protected ItemState(ItemState overlayedState, NodeState parent,
- int initialStatus, IdFactory idFactory) {
+ int initialStatus, ItemStateFactory isf, IdFactory idFactory) {
switch (initialStatus) {
case Status.EXISTING:
case Status.EXISTING_MODIFIED:
@@ -124,6 +133,7 @@
}
this.parent = parent;
this.idFactory = idFactory;
+ this.isf = isf;
this.isWorkspaceState = false;
connect(overlayedState);
@@ -141,7 +151,7 @@
* @return
*/
public boolean isValid() {
- return status == Status.EXISTING || status == Status.EXISTING_MODIFIED || status == Status.NEW;
+ return Status.isValid(getStatus());
}
/**
@@ -174,7 +184,7 @@
*/
public Path getQPath() throws ItemNotFoundException, RepositoryException {
// shortcut for root state
- if (getParent() == null) {
+ if (parent == null) {
return Path.ROOT;
}
@@ -183,14 +193,6 @@
Path.PathBuilder builder = new Path.PathBuilder();
buildPath(builder, this);
return builder.getPath();
- } catch (NoSuchItemStateException e) {
- String msg = "Failed to build path of " + this;
- log.debug(msg);
- throw new ItemNotFoundException(msg, e);
- } catch (ItemStateException e) {
- String msg = "Failed to build path of " + this;
- log.debug(msg);
- throw new RepositoryException(msg, e);
} catch (MalformedPathException e) {
String msg = "Failed to build path of " + this;
throw new RepositoryException(msg, e);
@@ -205,7 +207,7 @@
* @param state item to find path of
*/
private void buildPath(Path.PathBuilder builder, ItemState state)
- throws ItemStateException, RepositoryException {
+ throws ItemNotFoundException {
NodeState parentState = state.getParent();
// shortcut for root state
if (parentState == null) {
@@ -269,7 +271,7 @@
return;
}
- if (Status.isTerminalStatus(oldStatus)) {
+ if (Status.isTerminal(oldStatus)) {
throw new IllegalStateException("State is already in terminal status " + oldStatus);
}
if (Status.isValidStatusChange(oldStatus, newStatus, isWorkspaceState)) {
@@ -284,8 +286,8 @@
la = (ItemStateLifeCycleListener[]) listeners.toArray(new ItemStateLifeCycleListener[listeners.size()]);
}
for (int i = 0; i < la.length; i++) {
- if (la[i] instanceof ItemStateLifeCycleListener) {
- ((ItemStateLifeCycleListener) la[i]).statusChanged(this, oldStatus);
+ if (la[i] != null) {
+ la[i].statusChanged(this, oldStatus);
}
}
if (status == Status.MODIFIED) {
@@ -304,7 +306,6 @@
*/
public void addListener(ItemStateLifeCycleListener listener) {
synchronized (listeners) {
- assert (!listeners.contains(listener));
listeners.add(listener);
}
}
@@ -320,6 +321,53 @@
}
}
+ /**
+ * Unmodifiable iterator over the listeners present on this item state.
+ *
+ * @return
+ */
+ public Iterator getListeners() {
+ return Collections.unmodifiableCollection(listeners).iterator();
+ }
+ //-----------------------------------------< ItemStateLifeCycleListener >---
+ /**
+ *
+ * @param state
+ * @param previousStatus
+ */
+ public void statusChanged(ItemState state, int previousStatus) {
+ checkIsSessionState();
+
+ // the given state is the overlayed state this state (session) is listening to.
+ if (state == overlayedState) {
+ switch (state.getStatus()) {
+ case Status.MODIFIED:
+ // underlying state has been modified by external changes
+ if (status == Status.EXISTING) {
+ synchronized (this) {
+ reset();
+ }
+ } else if (status == Status.EXISTING_MODIFIED) {
+ setStatus(Status.STALE_MODIFIED);
+ }
+ // else: this status is EXISTING_REMOVED => ignore.
+ // no other status is possible.
+ break;
+ case Status.REMOVED:
+ if (status == Status.EXISTING_MODIFIED) {
+ setStatus(Status.STALE_DESTROYED);
+ } else {
+ setStatus(Status.REMOVED);
+ }
+ break;
+ default:
+ // Should never occur, since 'setStatus(int)' already validates
+ log.error("Workspace state cannot have its state changed to " + state.getStatus());
+ break;
+ }
+ }
+ }
+
//--------------------------------------------------------< State types >---
/**
* @return true if this state is a workspace state.
@@ -367,28 +415,52 @@
public boolean hasOverlayedState() {
return overlayedState != null;
}
+
//--------------------------------------------------< Workspace - State >---
/**
* Used on 'workspace' states in order to update the state according to
- * the given event (and ev. changelog).
+ * an external modification indicated by the given event.
*
* @param event
- * @param changeLog
* @throws IllegalStateException if this state is a 'session' state.
*/
- abstract void refresh(Event event, ChangeLog changeLog);
+ abstract void refresh(Event event);
+ /**
+ * Returns the overlaying item state or <code>null</code> if that state
+ * has not been created yet or has been disconnected.
+ *
+ * @return
+ */
+ ItemState getSessionState() {
+ checkIsWorkspaceState();
+ ItemStateLifeCycleListener[] la;
+ synchronized (listeners) {
+ la = (ItemStateLifeCycleListener[]) listeners.toArray(new ItemStateLifeCycleListener[listeners.size()]);
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] instanceof ItemState) {
+ return (ItemState) la[i];
+ }
+ }
+ return null;
+ }
//----------------------------------------------------< Session - State >---
/**
- * Copy all state information from overlayed state to this state
+ * Used on the target state of a save call AFTER the changelog has been
+ * successfully submitted to the SPI..
+ *
+ * @param events
+ * @param changeLog
+ * @throws IllegalStateException if this state is a 'session' state.
*/
- abstract void reset();
+ abstract void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException;
/**
- * Merge the state information from the overlayed state into this state
+ * Copy all state information from overlayed state to this state
*/
- abstract void merge();
+ abstract void reset();
/**
* Connect this state to some underlying overlayed state.
@@ -405,18 +477,6 @@
}
/**
- * Returns <code>true</code> if this item state represents new or modified
- * state or <code>false</code> if it represents existing, unmodified state.
- *
- * @return <code>true</code> if this item state is modified or new,
- * otherwise <code>false</code>
- */
- private boolean isTransient() {
- checkIsSessionState();
- return status == Status.EXISTING_MODIFIED || status == Status.NEW;
- }
-
- /**
* Removes this item state. This will change the status of this property
* state to either {@link Status#EXISTING_REMOVED} or {@link
* Status#REMOVED} depending on the current status.
@@ -440,14 +500,12 @@
* Checks if this <code>ItemState</code> is transiently modified or new and
* adds itself to the <code>Set</code> of <code>transientStates</code> if
* that is the case. It this <code>ItemState</code> has children it will
- * call the method {@link #collectTransientStates(java.util.Set)} on those
+ * call the method {@link #collectTransientStates(Collection)} on those
* <code>ItemState</code>s.
*
* @param transientStates the <code>Set</code> of transient <code>ItemState</code>,
- * collected while the <code>ItemState</code>
- * hierarchy is traversed.
*/
- abstract void collectTransientStates(Set transientStates);
+ abstract void collectTransientStates(Collection transientStates);
/**
* Marks this item state as modified.
@@ -477,46 +535,19 @@
throw new IllegalStateException(msg);
}
}
- //-----------------------------------------< ItemStateLifeCycleListener >---
+
+ //--------------------------------------------------------------------------
/**
*
- * @param state
- * @param previousStatus
+ * @param events
+ * @param processedState
*/
- public void statusChanged(ItemState state, int previousStatus) {
- // workspace-states never are listening to another state
- checkIsSessionState();
- state.checkIsWorkspaceState();
-
- switch (state.getStatus()) {
- case Status.EXISTING:
- // nothing to do
- break;
- case Status.MODIFIED:
- if (previousStatus == Status.EXISTING) {
- // underlying state has been modified
- if (isTransient()) {
- setStatus(Status.STALE_MODIFIED);
- } else {
- synchronized (this) {
- // this instance represents existing state, update it
- merge();
- setStatus(Status.EXISTING);
- }
- }
- }
- break;
- case Status.REMOVED:
- if (isTransient()) {
- setStatus(Status.STALE_DESTROYED);
- } else {
- setStatus(Status.REMOVED);
- }
- break;
- default:
- // Should never occur, since 'setStatus(int)' already validates
- log.error("Workspace state cannot have its state changed to " + state.getStatus());
+ static void removeEvent(Collection events, ItemState processedState) {
+ for (Iterator it = events.iterator(); it.hasNext();) {
+ if (((Event)it.next()).getItemId().equals(processedState.getId())) {
+ it.remove();
break;
+ }
}
}
}
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java?view=auto&rev=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java Thu Oct 26 04:02:02 2006
@@ -0,0 +1,96 @@
+/*
+ * 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.jcr2spi.state;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.NodeId;
+
+import java.util.Map;
+
+/**
+ * <code>ItemStateCache</code>...
+ */
+public class ItemStateCache implements ItemStateCreationListener {
+
+ private static Logger log = LoggerFactory.getLogger(ItemStateCache.class);
+
+ /**
+ * Maps a String uuid to a {@link NodeState}.
+ */
+ private final Map uuid2NodeState;
+
+ /**
+ * Creates a new <code>CachingItemStateManager</code>.
+ *
+ */
+ public ItemStateCache() {
+ this.uuid2NodeState = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+ }
+
+
+ public NodeState getNodeState(String uuid) {
+ return (NodeState) uuid2NodeState.get(uuid);
+ }
+
+ public NodeState getNodeState(NodeId nodeId) {
+ String uuid = nodeId.getUUID();
+ if (uuid != null && nodeId.getPath() == null) {
+ return getNodeState(uuid);
+ } else {
+ // TODO: missing caching for NodeState that are not only identified by uuid.
+ return null;
+ }
+ }
+
+ public PropertyState getPropertyState(PropertyId propertyId) {
+ // TODO: missing caching.
+ return null;
+ }
+ //------------------------------------------< ItemStateCreationListener >---
+
+ public void statusChanged(ItemState state, int previousStatus) {
+ if (Status.isTerminal(state.getStatus())) {
+ if (state.isNode()) {
+ NodeState nodeState = (NodeState) state;
+ String uuid = nodeState.getUUID();
+ if (uuid != null) {
+ uuid2NodeState.remove(uuid);
+ }
+ }
+ state.removeListener(this);
+ } else {
+ putToCache(state);
+ }
+ }
+
+ public void created(ItemState state) {
+ putToCache(state);
+ }
+
+ private void putToCache(ItemState state) {
+ if (state.isNode() && (state.getStatus() == Status.EXISTING || state.getStatus() == Status.MODIFIED)) {
+ NodeState nodeState = (NodeState) state;
+ String uuid = nodeState.getUUID();
+ if (uuid != null) {
+ uuid2NodeState.put(uuid, nodeState);
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java?view=auto&rev=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java Thu Oct 26 04:02:02 2006
@@ -0,0 +1,29 @@
+/*
+ * 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.jcr2spi.state;
+
+/**
+ * <code>ItemStateCreationListener</code>...
+ */
+public interface ItemStateCreationListener extends ItemStateLifeCycleListener {
+
+ /**
+ *
+ * @param state
+ */
+ public void created(ItemState state);
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCreationListener.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateFactory.java Thu Oct 26 04:02:02 2006
@@ -26,6 +26,12 @@
*/
public interface ItemStateFactory {
+ /**
+ *
+ * @param ism
+ * @return
+ * @throws ItemStateException
+ */
public NodeState createRootState(ItemStateManager ism) throws ItemStateException;
/**
@@ -71,4 +77,13 @@
public PropertyState createPropertyState(PropertyId propertyId,
NodeState parent)
throws NoSuchItemStateException, ItemStateException;
+
+
+ /**
+ * Set the cache used to retrieve item states that have already been
+ * built before.
+ *
+ * @param cache
+ */
+ public void setCache(ItemStateCache cache);
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java Thu Oct 26 04:02:02 2006
@@ -92,6 +92,7 @@
*/
public static final int CHECK_COLLISION = 32;
+ public static final int CHECK_NONE = 0;
public static final int CHECK_ALL = CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_COLLISION | CHECK_REFERENCES;
/**
@@ -769,16 +770,7 @@
if (ent.includesNodeType(QName.MIX_REFERENCEABLE)) {
ItemStateManager stateMgr = mgrProvider.getItemStateManager();
if (stateMgr.hasReferingStates(targetState)) {
- try {
- if (!stateMgr.getReferingStates(targetState).isEmpty()) {
- throw new ReferentialIntegrityException(safeGetJCRPath(targetState)
- + ": cannot remove node with references");
- }
- } catch (ItemStateException ise) {
- String msg = "internal error: failed to check references on " + safeGetJCRPath(targetState);
- log.error(msg, ise);
- throw new RepositoryException(msg, ise);
- }
+ throw new ReferentialIntegrityException(safeGetJCRPath(targetState) + ": cannot remove node with references");
}
}
}