use of org.apache.jackrabbit.core.state.ChildNodeEntry in project jackrabbit by apache.
the class MultiIndex method createIndex.
/**
* Recursively creates an index starting with the NodeState
* <code>node</code>.
*
* @param node the current NodeState.
* @param path the path of the current <code>node</code> state.
* @param stateMgr the shared item state manager.
* @param count the number of nodes already indexed.
* @return the number of nodes indexed so far.
* @throws IOException if an error occurs while writing to the
* index.
* @throws ItemStateException if an node state cannot be found.
* @throws RepositoryException if any other error occurs
*/
private long createIndex(NodeState node, Path path, ItemStateManager stateMgr, long count) throws IOException, ItemStateException, RepositoryException {
NodeId id = node.getNodeId();
if (excludedIDs.contains(id)) {
return count;
}
executeAndLog(new AddNode(getTransactionId(), id));
if (++count % 100 == 0) {
PathResolver resolver = new DefaultNamePathResolver(handler.getContext().getNamespaceRegistry());
log.info("indexing... {} ({})", resolver.getJCRPath(path), count);
}
if (count % 10 == 0) {
checkIndexingQueue(true);
}
checkVolatileCommit();
for (ChildNodeEntry child : node.getChildNodeEntries()) {
Path childPath = PATH_FACTORY.create(path, child.getName(), child.getIndex(), false);
NodeState childState = null;
try {
childState = (NodeState) stateMgr.getItemState(child.getId());
} catch (NoSuchItemStateException e) {
handler.getOnWorkspaceInconsistencyHandler().handleMissingChildNode(e, handler, path, node, child);
} catch (ItemStateException e) {
// JCR-3268 log bundle corruption and continue
handler.getOnWorkspaceInconsistencyHandler().logError(e, handler, childPath, node, child);
}
if (childState != null) {
count = createIndex(childState, childPath, stateMgr, count);
}
}
return count;
}
use of org.apache.jackrabbit.core.state.ChildNodeEntry in project jackrabbit by apache.
the class NodeImpl method getIndex.
/**
* {@inheritDoc}
*/
public int getIndex() throws RepositoryException {
// check state of this instance
sanityCheck();
NodeId parentId = getParentId();
if (parentId == null) {
// the root node cannot have same-name siblings; always return 1
return 1;
}
try {
NodeState parent = (NodeState) stateMgr.getItemState(parentId);
ChildNodeEntry parentEntry = parent.getChildNodeEntry(getNodeId());
return parentEntry.getIndex();
} catch (ItemStateException ise) {
// should never get here...
String msg = "internal error: failed to determine index";
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
use of org.apache.jackrabbit.core.state.ChildNodeEntry in project jackrabbit by apache.
the class NodeImpl method clone.
/**
* Create a child node that is a clone of a shareable node.
*
* @param src shareable source node
* @param name name of new node
* @return child node
* @throws ItemExistsException if there already is a child node with the
* name given and the definition does not allow creating another one
* @throws VersionException if this node is not checked out
* @throws ConstraintViolationException if no definition is found in this
* node that would allow creating the child node
* @throws LockException if this node is locked
* @throws RepositoryException if some other error occurs
*/
public synchronized NodeImpl clone(NodeImpl src, Name name) throws ItemExistsException, VersionException, ConstraintViolationException, LockException, RepositoryException {
Path nodePath;
try {
nodePath = PathFactoryImpl.getInstance().create(getPrimaryPath(), name, true);
} catch (MalformedPathException e) {
// should never happen
String msg = "internal error: invalid path " + this;
log.debug(msg);
throw new RepositoryException(msg, e);
}
// (1) make sure that parent node is checked-out
// (2) check lock status
// (3) check protected flag of parent (i.e. this) node
int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS;
sessionContext.getItemValidator().checkModify(this, options, Permission.NONE);
// (4) check for name collisions
NodeDefinitionImpl def;
try {
def = getApplicableChildNodeDefinition(name, null);
} catch (RepositoryException re) {
String msg = "no definition found in parent node's node type for new node";
log.debug(msg);
throw new ConstraintViolationException(msg, re);
}
NodeState thisState = data.getNodeState();
ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1);
if (cne != null) {
// check same-name sibling setting of new node
if (!def.allowsSameNameSiblings()) {
throw new ItemExistsException(itemMgr.safeGetJCRPath(nodePath));
}
// check same-name sibling setting of existing node
NodeId newId = cne.getId();
if (!((NodeImpl) itemMgr.getItem(newId)).getDefinition().allowsSameNameSiblings()) {
throw new ItemExistsException(itemMgr.safeGetJCRPath(nodePath));
}
}
// (5) do clone operation
NodeId parentId = getNodeId();
src.addShareParent(parentId);
// (6) modify the state of 'this', i.e. the parent node
NodeId srcId = src.getNodeId();
thisState = (NodeState) getOrCreateTransientItemState();
// add new child node entry
thisState.addChildNodeEntry(name, srcId);
return itemMgr.getNode(srcId, parentId);
}
use of org.apache.jackrabbit.core.state.ChildNodeEntry in project jackrabbit by apache.
the class NodeImpl method orderBefore.
/**
* Same as <code>{@link Node#orderBefore(String, String)}</code> except that
* this method takes a <code>Path.Element</code> arguments instead of
* <code>String</code>s.
*
* @param srcName
* @param dstName
* @throws UnsupportedRepositoryOperationException
* @throws VersionException
* @throws ConstraintViolationException
* @throws ItemNotFoundException
* @throws LockException
* @throws RepositoryException
*/
public synchronized void orderBefore(Path.Element srcName, Path.Element dstName) throws UnsupportedRepositoryOperationException, VersionException, ConstraintViolationException, ItemNotFoundException, LockException, RepositoryException {
// check state of this instance
sanityCheck();
if (!getPrimaryNodeType().hasOrderableChildNodes()) {
throw new UnsupportedRepositoryOperationException("child node ordering not supported on " + this);
}
// check arguments
if (srcName.equals(dstName)) {
// there's nothing to do
return;
}
// check existence
if (!hasNode(srcName.getName(), srcName.getIndex())) {
String name;
try {
Path.Element[] path = new Path.Element[] { srcName };
name = sessionContext.getJCRPath(new PathBuilder(path).getPath());
} catch (NameException e) {
name = srcName.toString();
} catch (NamespaceException e) {
name = srcName.toString();
}
throw new ItemNotFoundException(this + " has no child node with name " + name);
}
if (dstName != null && !hasNode(dstName.getName(), dstName.getIndex())) {
String name;
try {
Path.Element[] path = new Path.Element[] { dstName };
name = sessionContext.getJCRPath(new PathBuilder(path).getPath());
} catch (NameException e) {
name = dstName.toString();
} catch (NamespaceException e) {
name = dstName.toString();
}
throw new ItemNotFoundException(this + " has no child node with name " + name);
}
// make sure this node is checked-out and neither protected nor locked
int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS;
sessionContext.getItemValidator().checkModify(this, options, Permission.NONE);
/*
make sure the session is allowed to reorder child nodes.
since there is no specific privilege for reordering child nodes,
test if the the node to be reordered can be removed and added,
i.e. treating reorder similar to a move.
TODO: properly deal with sns in which case the index would change upon reorder.
*/
AccessManager acMgr = sessionContext.getAccessManager();
PathBuilder pb = new PathBuilder(getPrimaryPath());
pb.addLast(srcName.getName(), srcName.getIndex());
Path childPath = pb.getPath();
if (!acMgr.isGranted(childPath, Permission.MODIFY_CHILD_NODE_COLLECTION)) {
String msg = "Not allowed to reorder child node " + sessionContext.getJCRPath(childPath) + ".";
log.debug(msg);
throw new AccessDeniedException(msg);
}
ArrayList<ChildNodeEntry> list = new ArrayList<ChildNodeEntry>(data.getNodeState().getChildNodeEntries());
int srcInd = -1, destInd = -1;
for (int i = 0; i < list.size(); i++) {
ChildNodeEntry entry = list.get(i);
if (srcInd == -1) {
if (entry.getName().equals(srcName.getName()) && (entry.getIndex() == srcName.getIndex() || srcName.getIndex() == 0 && entry.getIndex() == 1)) {
srcInd = i;
}
}
if (destInd == -1 && dstName != null) {
if (entry.getName().equals(dstName.getName()) && (entry.getIndex() == dstName.getIndex() || dstName.getIndex() == 0 && entry.getIndex() == 1)) {
destInd = i;
if (srcInd != -1) {
break;
}
}
} else {
if (srcInd != -1) {
break;
}
}
}
// check if resulting order would be different to current order
if (destInd == -1) {
if (srcInd == list.size() - 1) {
// no change, we're done
return;
}
} else {
if ((destInd - srcInd) == 1) {
// no change, we're done
return;
}
}
// reorder list
if (destInd == -1) {
list.add(list.remove(srcInd));
} else {
if (srcInd < destInd) {
list.add(destInd, list.get(srcInd));
list.remove(srcInd);
} else {
list.add(destInd, list.remove(srcInd));
}
}
// modify the state of 'this', i.e. the parent node
NodeState thisState = (NodeState) getOrCreateTransientItemState();
thisState.setChildNodeEntries(list);
}
use of org.apache.jackrabbit.core.state.ChildNodeEntry in project jackrabbit by apache.
the class NodeImpl method onRemove.
protected void onRemove(NodeId parentId) throws RepositoryException {
// modify the state of 'this', i.e. the target node
NodeState thisState = (NodeState) getOrCreateTransientItemState();
// remove this node from its shared set
if (thisState.isShareable()) {
if (thisState.removeShare(parentId) > 0) {
// this state is still connected to some parents, so
// leave the child node entries and properties
// set state of this instance to 'invalid'
data.setStatus(STATUS_INVALIDATED);
// notify the item manager that this instance has been
// temporarily invalidated
itemMgr.itemInvalidated(id, data);
return;
}
}
if (thisState.hasChildNodeEntries()) {
// remove child nodes
// use temp array to avoid ConcurrentModificationException
ArrayList<ChildNodeEntry> tmp = new ArrayList<ChildNodeEntry>(thisState.getChildNodeEntries());
// remove from tail to avoid problems with same-name siblings
for (int i = tmp.size() - 1; i >= 0; i--) {
ChildNodeEntry entry = tmp.get(i);
// recursively remove child node
NodeId childId = entry.getId();
//NodeImpl childNode = (NodeImpl) itemMgr.getItem(childId);
try {
/* omit the read-permission check upon retrieving the
child item as this is an internal call to remove the
subtree which may contain (protected) child items which
are not visible to the caller of the removal. the actual
validation of the remove permission however is only
executed during Item.save().
*/
NodeImpl childNode = itemMgr.getNode(childId, getNodeId(), false);
childNode.onRemove(thisState.getNodeId());
// remove the child node entry
} catch (ItemNotFoundException e) {
boolean ignoreError = false;
if (parentId != null && sessionContext.getSessionImpl().autoFixCorruptions()) {
// it might be an access right problem
// we need to check if the item doesn't exist in the ism
ItemStateManager ism = sessionContext.getItemStateManager();
if (!ism.hasItemState(childId)) {
log.warn("Child named " + entry.getName() + " (index " + entry.getIndex() + ", " + "node id " + childId + ") " + "not found when trying to remove " + getPath() + " " + "(node id " + getNodeId() + ") - ignored", e);
ignoreError = true;
}
}
if (!ignoreError) {
throw e;
}
}
thisState.removeChildNodeEntry(childId);
}
}
// remove properties
// use temp set to avoid ConcurrentModificationException
HashSet<Name> tmp = new HashSet<Name>(thisState.getPropertyNames());
for (Name propName : tmp) {
// remove the property entry
thisState.removePropertyName(propName);
// remove property
PropertyId propId = new PropertyId(thisState.getNodeId(), propName);
/* omit the read-permission check upon retrieving the
child item as this is an internal call to remove the
subtree which may contain (protected) child items which
are not visible to the caller of the removal. the actual
validation of the remove permission however is only
executed during Item.save().
*/
itemMgr.getItem(propId, false).setRemoved();
}
// finally remove this node
thisState.setParentId(null);
setRemoved();
}
Aggregations