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 [3/3] - in
/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi:
./ state/ version/
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java Thu Oct 26 04:02:02 2006
@@ -59,6 +59,8 @@
private final SessionInfo sessionInfo;
private final WorkspaceManager wspManager;
+ private ItemStateCache cache;
+
public WorkspaceItemStateFactory(RepositoryService service, SessionInfo sessionInfo, WorkspaceManager wspManager) {
this.service = service;
this.sessionInfo = sessionInfo;
@@ -93,7 +95,11 @@
NodeId parentId = (info.getParentId() != null) ? info.getParentId() : null;
NodeState parent = (parentId != null) ? (NodeState) ism.getItemState(parentId) : null;
- return createNodeState(info, parent);
+ if (parent != null) {
+ return parent.getChildNodeEntry(info.getQName(), info.getIndex()).getNodeState();
+ } else {
+ return createNodeState(info, parent);
+ }
} catch (ItemNotFoundException e) {
throw new NoSuchItemStateException(e.getMessage(), e);
} catch (RepositoryException e) {
@@ -157,7 +163,7 @@
if (childInfo.getId().getPath() == null) {
childUUID = childInfo.getId().getUUID();
}
- childNodeEntries.add(new CNE(childInfo.getQName(), childUUID));
+ childNodeEntries.add(new CNE(childInfo.getQName(), childInfo.getIndex(), childUUID));
}
// names of child property entries
@@ -167,29 +173,24 @@
propNames.add(pId.getQName());
}
- // If the uuid is not null, the state could include mix:referenceable.
- // Therefore build a NodeReference instance and add it to the state.
- NodeReferences nodeRefs = null;
- if (uuid != null) {
- PropertyId[] references = info.getReferences();
- nodeRefs = new NodeReferencesImpl(info.getId(), references);
- }
+ // Build node-references object even if the state is not refereceable yet.
+ PropertyId[] references = info.getReferences();
+ NodeReferences nodeRefs = new NodeReferencesImpl(state, references);
state.init(info.getMixins(), childNodeEntries, propNames, nodeRefs);
- // copied from local-state-mgr TODO... check
- // register as listener
- // TODO check if needed
- //state.addListener(this);
+ state.addListener(cache);
+ cache.created(state);
+
return state;
} catch (PathNotFoundException e) {
throw new NoSuchItemStateException(e.getMessage(), e);
} catch (NodeTypeConflictException e) {
- String msg = "internal error: failed to retrieve node definition.";
+ String msg = "Internal error: failed to retrieve node definition.";
log.debug(msg);
throw new ItemStateException(msg, e);
} catch (ConstraintViolationException e) {
- String msg = "internal error: failed to retrieve node definition.";
+ String msg = "Internal error: failed to retrieve node definition.";
log.debug(msg);
throw new ItemStateException(msg, e);
} catch (NoSuchNodeTypeException e) {
@@ -231,9 +232,8 @@
* @throws ItemStateException if an error occurs while retrieving the
* <code>PropertyState</code>.
*/
- private PropertyState createPropertyState(PropertyInfo info,
- NodeState parent)
- throws ItemStateException {
+ private PropertyState createPropertyState(PropertyInfo info, NodeState parent)
+ throws ItemStateException {
try {
// retrieve property definition
@@ -242,7 +242,7 @@
// build the PropertyState
PropertyState state = new PropertyState(info.getQName(), parent,
- def, Status.EXISTING, service.getIdFactory(), true);
+ def, Status.EXISTING, this, service.getIdFactory(), true);
QValue[] qValues;
if (info.getType() == PropertyType.BINARY) {
@@ -260,37 +260,42 @@
}
state.init(info.getType(), qValues);
+ state.addListener(cache);
+ cache.created(state);
- // register as listener
- // TODO check if needed
- // state.addListener(this);
return state;
} catch (IOException e) {
throw new ItemStateException(e.getMessage(), e);
} catch (NodeTypeConflictException e) {
- String msg = "internal error: failed to retrieve property definition.";
- log.debug(msg);
- throw new ItemStateException(msg, e);
- } catch (ConstraintViolationException e) {
- String msg = "internal error: failed to retrieve property definition.";
+ String msg = "internal error: failed to build property state.";
log.debug(msg);
throw new ItemStateException(msg, e);
- } catch (NoSuchNodeTypeException e) {
- String msg = "internal error: failed to retrieve property definition.";
+ } catch (RepositoryException e) {
+ String msg = "internal error: failed to build property state.";
log.debug(msg);
throw new ItemStateException(msg, e);
}
}
+ /**
+ *
+ * @param cache
+ * @see ItemStateFactory#setCache(ItemStateCache)
+ */
+ public void setCache(ItemStateCache cache) {
+ this.cache = cache;
+ }
//------------------------------------------------------< ChildNodeEntry >---
private class CNE implements ChildNodeEntry {
private final QName name;
+ private final int index;
private final String uuid;
- private CNE(QName name, String uuid) {
+ private CNE(QName name, int index, String uuid) {
this.name = name;
+ this.index = index;
this.uuid = uuid;
}
@@ -307,7 +312,7 @@
}
public int getIndex() {
- throw new UnsupportedOperationException();
+ return index;
}
public NodeState getNodeState() throws NoSuchItemStateException, ItemStateException {
@@ -325,21 +330,16 @@
*/
private class NodeReferencesImpl implements NodeReferences {
- /**
- * Identifier of this <code>NodeReferences</code> instance. Since the
- * id of target state consists of a UUID and contains not relative
- * path, the id will be stable and can be stored.
- */
- private NodeId nodeId;
+ private NodeState nodeState;
/**
* Private constructor
*
- * @param nodeId
+ * @param nodeState
* @param referenceIds
*/
- private NodeReferencesImpl(NodeId nodeId, PropertyId[] referenceIds) {
- this.nodeId = nodeId;
+ private NodeReferencesImpl(NodeState nodeState, PropertyId[] referenceIds) {
+ this.nodeState = nodeState;
// TODO: modify in order to make usage of the references returned
// with NodeInfo that was just retrieved and implement a notification
@@ -352,8 +352,14 @@
* @see NodeReferences#isEmpty()
*/
public boolean isEmpty() {
+ // shortcut
+ if (nodeState.getUUID() == null) {
+ return true;
+ }
+ // nodestate has a uuid and is potentially mix:referenceable
+ // => try to retrieve references
try {
- NodeInfo info = service.getNodeInfo(sessionInfo, nodeId);
+ NodeInfo info = service.getNodeInfo(sessionInfo, nodeState.getNodeId());
return info.getReferences().length > 0;
} catch (RepositoryException e) {
log.error("Internal error.",e);
@@ -365,8 +371,14 @@
* @see NodeReferences#iterator()
*/
public Iterator iterator() {
+ // shortcut
+ if (nodeState.getUUID() == null) {
+ return Collections.EMPTY_SET.iterator();
+ }
+ // nodestate has a uuid and is potentially mix:referenceable
+ // => try to retrieve references
try {
- NodeInfo info = service.getNodeInfo(sessionInfo, nodeId);
+ NodeInfo info = service.getNodeInfo(sessionInfo, nodeState.getNodeId());
if (info.getReferences().length > 0) {
Set referenceIds = new HashSet();
referenceIds.addAll(Arrays.asList(info.getReferences()));
@@ -375,7 +387,7 @@
return Collections.EMPTY_SET.iterator();
}
} catch (RepositoryException e) {
- log.error("Internal error.",e);
+ log.error("Internal error.", e);
return Collections.EMPTY_SET.iterator();
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java Thu Oct 26 04:02:02 2006
@@ -18,17 +18,17 @@
import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
import org.apache.jackrabbit.spi.EventIterator;
-import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.IdFactory;
-import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
-import java.util.Iterator;
/**
* <code>WorkspaceItemStateManager</code>
@@ -54,47 +54,83 @@
* @param isLocal
*/
public void onEvent(EventIterator events, boolean isLocal) {
- onEvent(events, isLocal, null);
+ pushEvents(getEventCollection(events));
}
+ /**
+ *
+ * @param events
+ * @param changeLog
+ */
public void onEvent(EventIterator events, ChangeLog changeLog) {
if (changeLog == null) {
throw new IllegalArgumentException("ChangeLog must not be null.");
}
- // inform all transient states, that they have been persisted and must
- // connect to their workspace state (and eventually reload the data).
- // TODO: TOBEFIXED. only used to set status to EXISTING in order (which is probably wrong)
- changeLog.persisted();
-
- // inform all existing workspace states about the transient modifications
- // that have been persisted now.
- onEvent(events, true, changeLog);
+ Collection evs = getEventCollection(events);
+ // TODO: make sure, that events only contain events related to the modifications submitted with the changelog.
+
+ // inform the changelog target state about the transient modifications
+ // that have been persisted now: NEW-states will be connected to their
+ // overlayed state, EXISTING_REMOVED states will be definitely removed,
+ // EXISTING_MODIFIED states are merged with their workspace-state.
+ changeLog.getTarget().refresh(evs, changeLog);
+ // all events not covered by the changelog must not be handled on the
+ // session-states -> treat the same way as events returned by
+ // workspace operations.
+ pushEvents(evs);
}
- private void onEvent(EventIterator events, boolean isLocal, ChangeLog changeLog) {
+ private void pushEvents(Collection events) {
+ if (events.isEmpty()) {
+ return;
+ }
// collect set of removed node ids
- Set removedNodeIds = new HashSet();
- List addEventList = new ArrayList();
- List eventList = new ArrayList();
- while (events.hasNext()) {
- Event event = events.nextEvent();
+ Set removedEvents = new HashSet();
+ // separately collect the add events
+ Set addEvents = new HashSet();
+
+ for (Iterator it = events.iterator(); it.hasNext();) {
+ Event event = (Event) it.next();
int type = event.getType();
- if (type == Event.NODE_ADDED || event.getType() == Event.PROPERTY_ADDED) {
- addEventList.add(event);
- } else if (type == Event.NODE_REMOVED) {
+ if (type == Event.NODE_REMOVED) {
// remember removed nodes separately for proper handling later on.
- removedNodeIds.add(event.getItemId());
- eventList.add(event);
- } else {
- eventList.add(event);
+ removedEvents.add(event.getItemId());
+ } else if (type == Event.NODE_ADDED || type == Event.PROPERTY_ADDED) {
+ addEvents.add(event);
+ it.remove();
}
}
- if (eventList.isEmpty() && addEventList.isEmpty()) {
- return;
+
+ /* Process ADD-events.
+ In case of persisting transients modifications, the event-set may
+ still contain events that are not covered by the changeLog such as
+ new version-history or other autocreated properties and nodes.
+
+ Add events need to be processed hierarchically, since its not possible
+ to add a new child reference to a state that is not yet present in
+ the state manager.
+ The 'progress' flag is used to make sure, that during each loop at
+ least one event has been processed and removed from the iterator.
+ If this is not the case, there are not parent states present in the
+ state manager that need to be updated and the remaining events may
+ be ignored.
+ */
+ boolean progress = true;
+ while (!addEvents.isEmpty() && progress) {
+ progress = false;
+ for (Iterator it = addEvents.iterator(); it.hasNext();) {
+ Event ev = (Event) it.next();
+ NodeState parent = (ev.getParentId() != null) ? (NodeState) lookup(ev.getParentId()) : null;
+ if (parent != null) {
+ parent.refresh(ev);
+ it.remove();
+ progress = true;
+ }
+ }
}
- /* process remove and change events */
- for (Iterator it = eventList.iterator(); it.hasNext(); ) {
+ /* process all other events (removal, property changed) */
+ for (Iterator it = events.iterator(); it.hasNext(); ) {
Event event = (Event) it.next();
int type = event.getType();
@@ -103,62 +139,35 @@
if (type == Event.NODE_REMOVED || type == Event.PROPERTY_REMOVED) {
if (state != null) {
- state.refresh(event, changeLog);
+ state.refresh(event);
}
if (parent != null) {
// invalidate parent only if it has not been removed
// with the same event bundle.
- if (!removedNodeIds.contains(event.getParentId())) {
- parent.refresh(event, changeLog);
+ if (!removedEvents.contains(event.getParentId())) {
+ parent.refresh(event);
}
}
} else if (type == Event.PROPERTY_CHANGED) {
if (state != null) {
- try {
- // TODO: improve.
- /* retrieve property value and type from server even if
- changes were issued from this session (changelog).
- this is currently the only way to update the workspace
- state, which is not connected to its overlaying session-state.
- */
- PropertyState tmp = getItemStateFactory().createPropertyState((PropertyId) state.getId(), state.getParent());
- ((PropertyState) state).init(tmp.getType(), tmp.getValues());
- state.refresh(event, changeLog);
- } catch (ItemStateException e) {
- log.error("Unexpected error while updating modified property state.", e);
- }
+ state.refresh(event);
}
// TODO: check again. parent must be notified if mixintypes or jcr:uuid prop is changed.
if (parent != null) {
- parent.refresh(event, changeLog);
+ parent.refresh(event);
}
} else {
// should never occur
throw new IllegalArgumentException("Invalid event type: " + event.getType());
}
}
+ }
- /* Add events need to be processed hierarchically, since its not possible
- to add a new child reference to a state that is not yet present in
- the state manager.
- The 'progress' flag is used to make sure, that during each loop at
- least one event has been processed and removed from the iterator.
- If this is not the case, there are not parent states present in the
- state manager that need to be updated and the remaining events may
- be ignored.
- */
- boolean progress = true;
- while (!addEventList.isEmpty() && progress) {
- progress = false;
- for (Iterator it = addEventList.iterator(); it.hasNext();) {
- Event event = (Event) it.next();
- NodeState parent = (NodeState) lookup(event.getParentId());
- if (parent != null) {
- parent.refresh(event, changeLog);
- it.remove();
- progress = true;
- }
- }
+ private static Collection getEventCollection(EventIterator events) {
+ List evs = new ArrayList();
+ while (events.hasNext()) {
+ evs.add(events.nextEvent());
}
+ return evs;
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java Thu Oct 26 04:02:02 2006
@@ -45,6 +45,7 @@
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.ConstraintViolationException;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
@@ -311,6 +312,18 @@
return vhState.getUUID().equals(other.vhState.getUUID());
}
return false;
+ }
+
+ //-----------------------------------------------------------< ItemImpl >---
+ /**
+ *
+ * @throws UnsupportedRepositoryOperationException
+ * @throws ConstraintViolationException
+ * @throws RepositoryException
+ */
+ protected void checkIsWritable() throws UnsupportedRepositoryOperationException, ConstraintViolationException, RepositoryException {
+ super.checkIsWritable();
+ throw new ConstraintViolationException("VersionHistory is protected");
}
//------------------------------------------------------------< private >---
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java?view=diff&rev=467956&r1=467955&r2=467956
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java Thu Oct 26 04:02:02 2006
@@ -31,7 +31,9 @@
import javax.jcr.Value;
import javax.jcr.Node;
import javax.jcr.Item;
+import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.ConstraintViolationException;
import java.util.Calendar;
/**
@@ -108,6 +110,19 @@
}
return false;
}
+
+ //-----------------------------------------------------------< ItemImpl >---
+ /**
+ *
+ * @throws UnsupportedRepositoryOperationException
+ * @throws ConstraintViolationException
+ * @throws RepositoryException
+ */
+ protected void checkIsWritable() throws UnsupportedRepositoryOperationException, ConstraintViolationException, RepositoryException {
+ super.checkIsWritable();
+ throw new ConstraintViolationException("Version is protected");
+ }
+
//------------------------------------------------------------< private >---
/**
*