use of org.apache.jackrabbit.core.state.ItemState in project jackrabbit by apache.
the class AbstractBundlePersistenceManager method storeInternal.
/**
* Stores the given changelog and updates the bundle cache.
*
* @param changeLog the changelog to store
* @throws ItemStateException on failure
*/
private void storeInternal(ChangeLog changeLog) throws ItemStateException {
// delete bundles
HashSet<ItemId> deleted = new HashSet<ItemId>();
for (ItemState state : changeLog.deletedStates()) {
if (state.isNode()) {
NodePropBundle bundle = getBundle((NodeId) state.getId());
if (bundle == null) {
throw new NoSuchItemStateException(state.getId().toString());
}
deleteBundle(bundle);
deleted.add(state.getId());
}
}
// gather added node states
HashMap<ItemId, NodePropBundle> modified = new HashMap<ItemId, NodePropBundle>();
for (ItemState state : changeLog.addedStates()) {
if (state.isNode()) {
NodePropBundle bundle = new NodePropBundle((NodeState) state);
modified.put(state.getId(), bundle);
}
}
// gather modified node states
for (ItemState state : changeLog.modifiedStates()) {
if (state.isNode()) {
NodeId nodeId = (NodeId) state.getId();
NodePropBundle bundle = modified.get(nodeId);
if (bundle == null) {
bundle = getBundle(nodeId);
if (bundle == null) {
throw new NoSuchItemStateException(nodeId.toString());
}
modified.put(nodeId, bundle);
}
bundle.update((NodeState) state);
} else {
PropertyId id = (PropertyId) state.getId();
// skip redundant primaryType and uuid properties
if (id.getName().equals(JCR_PRIMARYTYPE) || id.getName().equals(JCR_UUID)) {
continue;
}
NodeId nodeId = id.getParentId();
NodePropBundle bundle = modified.get(nodeId);
if (bundle == null) {
bundle = getBundle(nodeId);
if (bundle == null) {
throw new NoSuchItemStateException(nodeId.toString());
}
modified.put(nodeId, bundle);
}
bundle.addProperty((PropertyState) state, getBlobStore());
}
}
// add removed properties
for (ItemState state : changeLog.deletedStates()) {
if (state.isNode()) {
// check consistency
NodeId parentId = state.getParentId();
if (!modified.containsKey(parentId) && !deleted.contains(parentId)) {
log.warn("Deleted node state's parent is not modified or deleted: " + parentId + "/" + state.getId());
}
} else {
PropertyId id = (PropertyId) state.getId();
NodeId nodeId = id.getParentId();
if (!deleted.contains(nodeId)) {
NodePropBundle bundle = modified.get(nodeId);
if (bundle == null) {
// should actually not happen
log.warn("deleted property state's parent not modified!");
bundle = getBundle(nodeId);
if (bundle == null) {
throw new NoSuchItemStateException(nodeId.toString());
}
modified.put(nodeId, bundle);
}
bundle.removeProperty(id.getName(), getBlobStore());
}
}
}
// add added properties
for (ItemState state : changeLog.addedStates()) {
if (!state.isNode()) {
PropertyId id = (PropertyId) state.getId();
// skip primaryType and uuid properties
if (id.getName().equals(JCR_PRIMARYTYPE) || id.getName().equals(JCR_UUID)) {
continue;
}
NodeId nodeId = id.getParentId();
NodePropBundle bundle = modified.get(nodeId);
if (bundle == null) {
// should actually not happen
log.warn("added property state's parent not modified!");
bundle = getBundle(nodeId);
if (bundle == null) {
throw new NoSuchItemStateException(nodeId.toString());
}
modified.put(nodeId, bundle);
}
bundle.addProperty((PropertyState) state, getBlobStore());
}
}
// now store all modified bundles
long updateSize = 0;
for (NodePropBundle bundle : modified.values()) {
putBundle(bundle);
updateSize += bundle.getSize();
}
changeLog.setUpdateSize(updateSize);
// store the refs
for (NodeReferences refs : changeLog.modifiedRefs()) {
if (refs.hasReferences()) {
store(refs);
} else {
destroy(refs);
}
}
}
use of org.apache.jackrabbit.core.state.ItemState in project jackrabbit by apache.
the class EventStateCollection method createEventStates.
/**
* Creates {@link EventState} instances from <code>ItemState</code>
* <code>changes</code>.
*
* @param rootNodeId the id of the root node.
* @param changes the changes on <code>ItemState</code>s.
* @param stateMgr an <code>ItemStateManager</code> to provide <code>ItemState</code>
* of items that are not contained in the <code>changes</code> collection.
* @throws ItemStateException if an error occurs while creating events
* states for the item state changes.
*/
public void createEventStates(NodeId rootNodeId, ChangeLog changes, ItemStateManager stateMgr) throws ItemStateException {
// create a hierarchy manager, that is based on the ChangeLog and
// the ItemStateProvider
ChangeLogBasedHierarchyMgr hmgr = new ChangeLogBasedHierarchyMgr(rootNodeId, stateMgr, changes);
// 1. modified items
for (ItemState state : changes.modifiedStates()) {
if (state.isNode()) {
// node changed
// covers the following cases:
// 1) property added
// 2) property removed
// 3) child node added
// 4) child node removed
// 5) node moved/reordered
// 6) node reordered
// 7) shareable node added
// 8) shareable node removed
// cases 1) and 2) are detected with added and deleted states
// on the PropertyState itself.
// cases 3) and 4) are detected with added and deleted states
// on the NodeState itself.
// in case 5) two or three nodes change. two nodes are changed
// when a child node is renamed. three nodes are changed when
// a node is really moved. In any case we are only interested in
// the node that actually got moved.
// in case 6) only one node state changes. the state of the
// parent node.
// in case 7) parent of added shareable node has new child node
// entry.
// in case 8) parent of removed shareable node has removed child
// node entry.
NodeState n = (NodeState) state;
if (n.hasOverlayedState()) {
NodeId oldParentId = n.getOverlayedState().getParentId();
NodeId newParentId = n.getParentId();
if (newParentId != null && !oldParentId.equals(newParentId) && !n.isShareable()) {
Path oldPath = getZombiePath(n.getNodeId(), hmgr);
// node moved
// generate node removed & node added event
NodeState oldParent;
try {
oldParent = (NodeState) changes.get(oldParentId);
} catch (NoSuchItemStateException e) {
// old parent has been deleted, retrieve from
// shared item state manager
oldParent = (NodeState) stateMgr.getItemState(oldParentId);
}
if (oldParent != null) {
NodeTypeImpl oldParentNodeType = getNodeType(oldParent, session);
events.add(EventState.childNodeRemoved(oldParentId, getParent(oldPath), n.getNodeId(), oldPath.getLastElement(), oldParentNodeType.getQName(), oldParent.getMixinTypeNames(), session));
} else {
// JCR-2298: In some cases the old parent node
// state is no longer available anywhere. Log an
// error since in this case we can't generate the
// correct REMOVE event.
log.error("The old parent (node id " + oldParentId + ") of a moved node (old path " + oldPath + ") is no longer available." + " No REMOVE event generated!");
}
NodeState newParent = (NodeState) changes.get(newParentId);
NodeTypeImpl newParentNodeType = getNodeType(newParent, session);
Set<Name> mixins = newParent.getMixinTypeNames();
Path newPath = getPath(n.getNodeId(), hmgr);
events.add(EventState.childNodeAdded(newParentId, getParent(newPath), n.getNodeId(), newPath.getLastElement(), newParentNodeType.getQName(), mixins, session));
events.add(EventState.nodeMovedWithInfo(newParentId, newPath, n.getNodeId(), oldPath, newParentNodeType.getQName(), mixins, session, false));
} else {
// a moved node always has a modified parent node
NodeState parent = null;
try {
// root node does not have a parent UUID
if (state.getParentId() != null) {
parent = (NodeState) changes.get(state.getParentId());
}
} catch (NoSuchItemStateException e) {
// should never happen actually. this would mean
// the parent of this modified node is deleted
String msg = "Parent of node " + state.getId() + " is deleted.";
log.error(msg);
throw new ItemStateException(msg, e);
}
if (parent != null) {
// check if node has been renamed
ChildNodeEntry moved = null;
for (ChildNodeEntry child : parent.getRemovedChildNodeEntries()) {
if (child.getId().equals(n.getNodeId())) {
// found node re-added with different name
moved = child;
}
}
if (moved != null) {
NodeTypeImpl nodeType = getNodeType(parent, session);
Set<Name> mixins = parent.getMixinTypeNames();
Path newPath = getPath(state.getId(), hmgr);
Path parentPath = getParent(newPath);
Path oldPath;
try {
if (moved.getIndex() == 0) {
oldPath = PathFactoryImpl.getInstance().create(parentPath, moved.getName(), false);
} else {
oldPath = PathFactoryImpl.getInstance().create(parentPath, moved.getName(), moved.getIndex(), false);
}
} catch (RepositoryException e) {
// should never happen actually
String msg = "Malformed path for item: " + state.getId();
log.error(msg);
throw new ItemStateException(msg, e);
}
events.add(EventState.childNodeRemoved(parent.getNodeId(), parentPath, n.getNodeId(), oldPath.getLastElement(), nodeType.getQName(), mixins, session));
events.add(EventState.childNodeAdded(parent.getNodeId(), parentPath, n.getNodeId(), newPath.getLastElement(), nodeType.getQName(), mixins, session));
events.add(EventState.nodeMovedWithInfo(parent.getNodeId(), newPath, n.getNodeId(), oldPath, nodeType.getQName(), mixins, session, false));
}
}
}
}
// check if child nodes of modified node state have been reordered
List<ChildNodeEntry> reordered = n.getReorderedChildNodeEntries();
NodeTypeImpl nodeType = getNodeType(n, session);
Set<Name> mixins = n.getMixinTypeNames();
if (reordered.size() > 0) {
// reorder
for (ChildNodeEntry child : reordered) {
Path addedElem = getPathElement(child);
Path parentPath = getPath(n.getNodeId(), hmgr);
// get removed index
NodeState overlayed = (NodeState) n.getOverlayedState();
ChildNodeEntry entry = overlayed.getChildNodeEntry(child.getId());
if (entry == null) {
throw new ItemStateException("Unable to retrieve old child index for item: " + child.getId());
}
Path removedElem = getPathElement(entry);
events.add(EventState.childNodeRemoved(n.getNodeId(), parentPath, child.getId(), removedElem, nodeType.getQName(), mixins, session));
events.add(EventState.childNodeAdded(n.getNodeId(), parentPath, child.getId(), addedElem, nodeType.getQName(), mixins, session));
List<ChildNodeEntry> cne = n.getChildNodeEntries();
// index of the child node entry before which this
// child node entry was reordered
int idx = cne.indexOf(child) + 1;
Path beforeElem = null;
if (idx < cne.size()) {
beforeElem = getPathElement(cne.get(idx));
}
events.add(EventState.nodeReordered(n.getNodeId(), parentPath, child.getId(), addedElem, removedElem, beforeElem, nodeType.getQName(), mixins, session, false));
}
}
// create events if n is shareable
createShareableNodeEvents(n, changes, hmgr, stateMgr);
} else {
// property changed
Path path = getPath(state.getId(), hmgr);
NodeState parent = (NodeState) stateMgr.getItemState(state.getParentId());
NodeTypeImpl nodeType = getNodeType(parent, session);
Set<Name> mixins = parent.getMixinTypeNames();
events.add(EventState.propertyChanged(state.getParentId(), getParent(path), path.getLastElement(), nodeType.getQName(), mixins, session));
}
}
// 2. removed items
for (ItemState state : changes.deletedStates()) {
if (state.isNode()) {
// node deleted
NodeState n = (NodeState) state;
NodeState parent = (NodeState) stateMgr.getItemState(n.getParentId());
NodeTypeImpl nodeType = getNodeType(parent, session);
Set<Name> mixins = parent.getMixinTypeNames();
Path path = getZombiePath(state.getId(), hmgr);
events.add(EventState.childNodeRemoved(n.getParentId(), getParent(path), n.getNodeId(), path.getLastElement(), nodeType.getQName(), mixins, session));
// create events if n is shareable
createShareableNodeEvents(n, changes, hmgr, stateMgr);
} else {
// only create an event if node still exists
try {
NodeState n = (NodeState) changes.get(state.getParentId());
// node state exists -> only property removed
NodeTypeImpl nodeType = getNodeType(n, session);
Set<Name> mixins = n.getMixinTypeNames();
Path path = getZombiePath(state.getId(), hmgr);
events.add(EventState.propertyRemoved(state.getParentId(), getParent(path), path.getLastElement(), nodeType.getQName(), mixins, session));
} catch (NoSuchItemStateException e) {
// node removed as well -> do not create an event
}
}
}
// 3. added items
for (ItemState state : changes.addedStates()) {
if (state.isNode()) {
// node created
NodeState n = (NodeState) state;
NodeId parentId = n.getParentId();
// the parent of an added item is always modified or new
NodeState parent = (NodeState) changes.get(parentId);
if (parent == null) {
String msg = "Parent " + parentId + " must be changed as well.";
log.error(msg);
throw new ItemStateException(msg);
}
NodeTypeImpl nodeType = getNodeType(parent, session);
Set<Name> mixins = parent.getMixinTypeNames();
Path path = getPath(n.getNodeId(), hmgr);
events.add(EventState.childNodeAdded(parentId, getParent(path), n.getNodeId(), path.getLastElement(), nodeType.getQName(), mixins, session));
// create events if n is shareable
createShareableNodeEvents(n, changes, hmgr, stateMgr);
} else {
// property created / set
NodeState n = (NodeState) changes.get(state.getParentId());
if (n == null) {
String msg = "Node " + state.getParentId() + " must be changed as well.";
log.error(msg);
throw new ItemStateException(msg);
}
NodeTypeImpl nodeType = getNodeType(n, session);
Set<Name> mixins = n.getMixinTypeNames();
Path path = getPath(state.getId(), hmgr);
events.add(EventState.propertyAdded(state.getParentId(), getParent(path), path.getLastElement(), nodeType.getQName(), mixins, session));
}
}
}
use of org.apache.jackrabbit.core.state.ItemState in project jackrabbit by apache.
the class EventConsumer method prepareDeleted.
/**
* Checks for which deleted <code>ItemStates</code> this
* <code>EventConsumer</code> has enough access rights to see the event.
*
* @param events the collection of {@link EventState}s.
* @param deletedItems Iterator of deleted <code>ItemState</code>s.
*/
void prepareDeleted(EventStateCollection events, Iterable<ItemState> deletedItems) {
Set<ItemId> denied = null;
Set<ItemId> deletedIds = new HashSet<ItemId>();
for (ItemState state : deletedItems) {
deletedIds.add(state.getId());
}
for (Iterator<EventState> it = events.iterator(); it.hasNext(); ) {
EventState evState = it.next();
ItemId targetId = evState.getTargetId();
if (deletedIds.contains(targetId)) {
// check read permission
boolean granted = false;
try {
granted = canRead(evState);
} catch (RepositoryException e) {
log.warn("Unable to check access rights for item: " + targetId);
}
if (!granted) {
if (denied == null) {
denied = new HashSet<ItemId>();
}
denied.add(targetId);
}
}
}
if (denied != null) {
accessDenied.put(events, denied);
}
}
use of org.apache.jackrabbit.core.state.ItemState in project jackrabbit by apache.
the class VersionItemStateProvider method getItemState.
/**
* @inheritDoc
*/
public synchronized ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException {
ItemState item = (ItemState) items.get(id);
if (item == null) {
item = stateMgr.getItemState(id);
items.put(id, item);
}
return item;
}
use of org.apache.jackrabbit.core.state.ItemState in project jackrabbit by apache.
the class NodeStateEx method removeProperty.
/**
* removes the property with the given name
*
* @param name name of the property
* @return <code>true</code> if the property was removed.
* @throws RepositoryException if an error occurs
*/
public boolean removeProperty(Name name) throws RepositoryException {
try {
if (!nodeState.hasPropertyName(name)) {
return false;
} else {
PropertyId propId = new PropertyId(nodeState.getNodeId(), name);
ItemState state = stateMgr.getItemState(propId);
stateMgr.destroy(state);
nodeState.removePropertyName(name);
if (nodeState.getStatus() != ItemState.STATUS_NEW) {
nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
}
return true;
}
} catch (ItemStateException e) {
throw new RepositoryException(e);
}
}
Aggregations