use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class BatchedItemOperations method verifyCheckedOut.
//----------------------------------------------------< protected methods >
/**
* Verifies that the node at <code>nodePath</code> is checked-out; throws a
* <code>VersionException</code> if that's not the case.
* <p>
* A node is considered <i>checked-out</i> if it is versionable and
* checked-out, or is non-versionable but its nearest versionable ancestor
* is checked-out, or is non-versionable and there are no versionable
* ancestors.
*
* @param nodePath
* @throws PathNotFoundException
* @throws VersionException
* @throws RepositoryException
*/
protected void verifyCheckedOut(Path nodePath) throws PathNotFoundException, VersionException, RepositoryException {
// search nearest ancestor that is versionable, start with node at nodePath
/**
* FIXME should not only rely on existence of jcr:isCheckedOut property
* but also verify that node.isNodeType("mix:versionable")==true;
* this would have a negative impact on performance though...
*/
NodeState nodeState = getNodeState(nodePath);
while (!nodeState.hasPropertyName(NameConstants.JCR_ISCHECKEDOUT)) {
if (nodePath.denotesRoot()) {
return;
}
nodePath = nodePath.getAncestor(1);
nodeState = getNodeState(nodePath);
}
PropertyId propId = new PropertyId(nodeState.getNodeId(), NameConstants.JCR_ISCHECKEDOUT);
PropertyState propState;
try {
propState = (PropertyState) stateMgr.getItemState(propId);
} catch (ItemStateException ise) {
String msg = "internal error: failed to retrieve state of " + safeGetJCRPath(propId);
log.debug(msg);
throw new RepositoryException(msg, ise);
}
boolean checkedOut = propState.getValues()[0].getBoolean();
if (!checkedOut) {
throw new VersionException(safeGetJCRPath(nodePath) + " is checked-in");
}
}
use of org.apache.jackrabbit.core.state.NodeState 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.NodeState in project jackrabbit by apache.
the class PersistenceCopier method copy.
/**
* Copies the given node state and all associated property states
* to the target persistence manager.
*
* @param sourceNode source node state
* @throws RepositoryException if the copy operation fails
*/
private void copy(NodeState sourceNode) throws RepositoryException {
try {
ChangeLog changes = new ChangeLog();
// Copy the node state
NodeState targetNode = target.createNew(sourceNode.getNodeId());
targetNode.setParentId(sourceNode.getParentId());
targetNode.setNodeTypeName(sourceNode.getNodeTypeName());
targetNode.setMixinTypeNames(sourceNode.getMixinTypeNames());
targetNode.setPropertyNames(sourceNode.getPropertyNames());
targetNode.setChildNodeEntries(sourceNode.getChildNodeEntries());
if (target.exists(targetNode.getNodeId())) {
changes.modified(targetNode);
} else {
changes.added(targetNode);
}
// Copy all associated property states
for (Name name : sourceNode.getPropertyNames()) {
PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
PropertyState sourceState = source.load(id);
PropertyState targetState = target.createNew(id);
targetState.setType(sourceState.getType());
targetState.setMultiValued(sourceState.isMultiValued());
InternalValue[] values = sourceState.getValues();
if (sourceState.getType() == PropertyType.BINARY) {
for (int i = 0; i < values.length; i++) {
InputStream stream = values[i].getStream();
try {
values[i] = InternalValue.create(stream, store);
} finally {
stream.close();
}
}
}
targetState.setValues(values);
if (target.exists(targetState.getPropertyId())) {
changes.modified(targetState);
} else {
changes.added(targetState);
}
}
// Copy all node references
if (source.existsReferencesTo(sourceNode.getNodeId())) {
changes.modified(source.loadReferencesTo(sourceNode.getNodeId()));
} else if (target.existsReferencesTo(sourceNode.getNodeId())) {
NodeReferences references = target.loadReferencesTo(sourceNode.getNodeId());
references.clearAllReferences();
changes.modified(references);
}
// Persist the copied states
target.store(changes);
} catch (IOException e) {
throw new RepositoryException("Unable to copy binary values of " + sourceNode, e);
} catch (ItemStateException e) {
throw new RepositoryException("Unable to copy " + sourceNode, e);
}
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class DatabasePersistenceManager method load.
/**
* {@inheritDoc}
*/
public NodeState load(NodeId id) throws NoSuchItemStateException, ItemStateException {
if (!initialized) {
throw new IllegalStateException("not initialized");
}
synchronized (nodeStateSelectSQL) {
ResultSet rs = null;
InputStream in = null;
try {
Statement stmt = executeStmt(nodeStateSelectSQL, new Object[] { id.toString() });
rs = stmt.getResultSet();
if (!rs.next()) {
throw new NoSuchItemStateException(id.toString());
}
in = rs.getBinaryStream(1);
NodeState state = createNew(id);
Serializer.deserialize(state, in);
return state;
} catch (Exception e) {
if (e instanceof NoSuchItemStateException) {
throw (NoSuchItemStateException) e;
}
String msg = "failed to read node state: " + id;
log.error(msg, e);
throw new ItemStateException(msg, e);
} finally {
IOUtils.closeQuietly(in);
closeResultSet(rs);
}
}
}
use of org.apache.jackrabbit.core.state.NodeState in project jackrabbit by apache.
the class SimpleExcerptProvider method getExcerpt.
/**
* {@inheritDoc}
*/
public String getExcerpt(NodeId id, int maxFragments, int maxFragmentSize) throws IOException {
StringBuffer text = new StringBuffer();
try {
NodeState nodeState = (NodeState) ism.getItemState(id);
String separator = "";
Iterator<Name> it = nodeState.getPropertyNames().iterator();
while (it.hasNext() && text.length() < maxFragmentSize) {
PropertyId propId = new PropertyId(id, it.next());
PropertyState propState = (PropertyState) ism.getItemState(propId);
if (propState.getType() == PropertyType.STRING) {
text.append(separator);
separator = " ... ";
InternalValue[] values = propState.getValues();
for (InternalValue value : values) {
text.append(value.toString());
}
}
}
} catch (ItemStateException e) {
// ignore
}
if (text.length() > maxFragmentSize) {
int lastSpace = text.lastIndexOf(" ", maxFragmentSize);
if (lastSpace != -1) {
text.setLength(lastSpace);
} else {
text.setLength(maxFragmentSize);
}
text.append(" ...");
}
return "<excerpt><fragment>" + text.toString() + "</fragment></excerpt>";
}
Aggregations