use of org.apache.jackrabbit.core.id.NodeId in project jackrabbit by apache.
the class DescendantSelfAxisQuery method execute.
//------------------------< JackrabbitQuery >-------------------------------
/**
* {@inheritDoc}
*/
public QueryHits execute(final JackrabbitIndexSearcher searcher, final SessionImpl session, final Sort sort) throws IOException {
if (sort.getSort().length == 0 && subQueryMatchesAll()) {
// maps path String to ScoreNode
Map<String, ScoreNode> startingPoints = new TreeMap<String, ScoreNode>();
QueryHits result = searcher.evaluate(getContextQuery());
try {
// intermediate ChildNodesQueryHits are required.
for (int i = 2; i <= getMinLevels(); i++) {
result = new ChildNodesQueryHits(result, session);
}
ScoreNode sn;
while ((sn = result.nextScoreNode()) != null) {
NodeId id = sn.getNodeId();
try {
Node node = session.getNodeById(id);
startingPoints.put(node.getPath(), sn);
} catch (ItemNotFoundException e) {
// JCR-3001 access denied to score node, will just skip it
log.warn("Access denied to node id {}.", id);
} catch (RepositoryException e) {
throw Util.createIOException(e);
}
}
} finally {
result.close();
}
// prune overlapping starting points
String previousPath = null;
for (Iterator<String> it = startingPoints.keySet().iterator(); it.hasNext(); ) {
String path = it.next();
// current path is obsolete
if (previousPath != null && path.startsWith(previousPath)) {
it.remove();
} else {
previousPath = path;
}
}
final Iterator<ScoreNode> scoreNodes = startingPoints.values().iterator();
return new AbstractQueryHits() {
private NodeTraversingQueryHits currentTraversal;
{
fetchNextTraversal();
}
public void close() throws IOException {
if (currentTraversal != null) {
currentTraversal.close();
}
}
public ScoreNode nextScoreNode() throws IOException {
while (currentTraversal != null) {
ScoreNode sn = currentTraversal.nextScoreNode();
if (sn != null) {
return sn;
} else {
fetchNextTraversal();
}
}
// if we get here there are no more score nodes
return null;
}
private void fetchNextTraversal() throws IOException {
if (currentTraversal != null) {
currentTraversal.close();
}
currentTraversal = null;
// iterate until we find a good one
while (scoreNodes.hasNext()) {
ScoreNode sn = scoreNodes.next();
NodeId id = sn.getNodeId();
try {
Node node = session.getNodeById(id);
currentTraversal = new NodeTraversingQueryHits(node, getMinLevels() == 0);
break;
} catch (ItemNotFoundException e) {
// JCR-3001 node access denied, will just skip it
log.warn("Access denied to node id {}.", id);
} catch (RepositoryException e) {
throw Util.createIOException(e);
}
}
}
};
} else {
return null;
}
}
use of org.apache.jackrabbit.core.id.NodeId in project jackrabbit by apache.
the class ConsistencyCheck method checkIndexConsistency.
private void checkIndexConsistency() throws IOException {
log.info("Checking index consistency");
// Ids of multiple nodes in the index
Set<NodeId> multipleEntries = new HashSet<NodeId>();
CachingMultiIndexReader reader = index.getIndexReader();
try {
for (int i = 0; i < reader.maxDoc(); i++) {
if (i > 10 && i % (reader.maxDoc() / 5) == 0) {
long progress = Math.round((100.0 * (float) i) / ((float) reader.maxDoc() * 2f));
log.info("progress: " + progress + "%");
}
if (reader.isDeleted(i)) {
continue;
}
Document d = reader.document(i, FieldSelectors.UUID);
NodeId id = new NodeId(d.get(FieldNames.UUID));
if (!isIgnored(id)) {
boolean nodeExists = nodeIds.containsKey(id);
if (nodeExists) {
Boolean alreadyIndexed = nodeIds.put(id, Boolean.TRUE);
if (alreadyIndexed) {
multipleEntries.add(id);
}
} else {
errors.add(new NodeDeleted(id));
}
}
}
} finally {
reader.release();
}
// create multiple entries errors
for (NodeId id : multipleEntries) {
errors.add(new MultipleEntries(id));
}
reader = index.getIndexReader();
try {
// run through documents again and check parent
for (int i = 0; i < reader.maxDoc(); i++) {
if (i > 10 && i % (reader.maxDoc() / 5) == 0) {
long progress = Math.round((100.0 * (float) i) / ((float) reader.maxDoc() * 2f));
log.info("progress: " + (progress + 50) + "%");
}
if (reader.isDeleted(i)) {
continue;
}
Document d = reader.document(i, FieldSelectors.UUID_AND_PARENT);
NodeId id = new NodeId(d.get(FieldNames.UUID));
if (!nodeIds.containsKey(id) || isIgnored(id)) {
// this node is ignored or was already marked for deletion
continue;
}
String parent = d.get(FieldNames.PARENT);
if (parent == null || parent.isEmpty()) {
continue;
}
final NodeId parentId = new NodeId(parent);
boolean parentExists = nodeIds.containsKey(parentId);
boolean parentIndexed = parentExists && nodeIds.get(parentId);
if (parentIndexed) {
continue;
} else if (id.equals(RepositoryImpl.SYSTEM_ROOT_NODE_ID) && parentId.equals(RepositoryImpl.ROOT_NODE_ID)) {
// special case for the /jcr:system node
continue;
}
// parent is missing from index
if (parentExists) {
errors.add(new MissingAncestor(id, parentId));
} else {
try {
final ItemState itemState = stateMgr.getItemState(id);
if (parentId.equals(itemState.getParentId())) {
// orphaned node
errors.add(new UnknownParent(id, parentId));
} else {
errors.add(new WrongParent(id, parentId, itemState.getParentId()));
}
} catch (ItemStateException ignored) {
}
}
}
} finally {
reader.release();
}
}
use of org.apache.jackrabbit.core.id.NodeId in project jackrabbit by apache.
the class WorkspaceImporter method resolveUUIDConflict.
/**
* @param parent parent node state
* @param conflicting conflicting node state
* @param nodeInfo the node info
* @return the resolved node state
* @throws RepositoryException if an error occurs
*/
protected NodeState resolveUUIDConflict(NodeState parent, NodeState conflicting, NodeInfo nodeInfo) throws RepositoryException {
NodeState node;
if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) {
// create new with new uuid:
// check if new node can be added (check access rights &
// node type constraints only, assume locking & versioning status
// and retention/hold has already been checked on ancestor)
itemOps.checkAddNode(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_CONSTRAINTS);
node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null);
// remember uuid mapping
EffectiveNodeType ent = itemOps.getEffectiveNodeType(node);
if (ent.includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
refTracker.mappedId(nodeInfo.getId(), node.getNodeId());
}
} else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW) {
// new node and share with existing
if (conflicting.isShareable()) {
itemOps.clone(conflicting, parent, nodeInfo.getName());
return null;
}
String msg = "a node with uuid " + nodeInfo.getId() + " already exists!";
log.debug(msg);
throw new ItemExistsException(msg);
} else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING) {
// make sure conflicting node is not importTarget or an ancestor thereof
Path p0 = hierMgr.getPath(importTarget.getNodeId());
Path p1 = hierMgr.getPath(conflicting.getNodeId());
try {
if (p1.equals(p0) || p1.isAncestorOf(p0)) {
String msg = "cannot remove ancestor node";
log.debug(msg);
throw new ConstraintViolationException(msg);
}
} catch (MalformedPathException mpe) {
// should never get here...
String msg = "internal error: failed to determine degree of relationship";
log.error(msg, mpe);
throw new RepositoryException(msg, mpe);
}
// remove conflicting:
// check if conflicting can be removed
// (access rights, node type constraints, locking & versioning status)
itemOps.checkRemoveNode(conflicting, BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_LOCK | BatchedItemOperations.CHECK_CHECKED_OUT | BatchedItemOperations.CHECK_CONSTRAINTS | BatchedItemOperations.CHECK_HOLD | BatchedItemOperations.CHECK_RETENTION);
// do remove conflicting (recursive)
itemOps.removeNodeState(conflicting);
// create new with given uuid:
// check if new node can be added (check access rights &
// node type constraints only, assume locking & versioning status
// and retention/hold has already been checked on ancestor)
itemOps.checkAddNode(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_CONSTRAINTS);
// do create new node
node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), nodeInfo.getId());
} else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING) {
NodeId parentId = conflicting.getParentId();
if (parentId == null) {
String msg = "root node cannot be replaced";
log.debug(msg);
throw new RepositoryException(msg);
}
// 'replace' current parent with parent of conflicting
try {
parent = itemOps.getNodeState(parentId);
} catch (ItemNotFoundException infe) {
// should never get here...
String msg = "internal error: failed to retrieve parent state";
log.error(msg, infe);
throw new RepositoryException(msg, infe);
}
// remove conflicting:
// check if conflicting can be removed
// (access rights, node type constraints, locking & versioning status)
itemOps.checkRemoveNode(conflicting, BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_LOCK | BatchedItemOperations.CHECK_CHECKED_OUT | BatchedItemOperations.CHECK_CONSTRAINTS | BatchedItemOperations.CHECK_HOLD | BatchedItemOperations.CHECK_RETENTION);
// 'replace' is actually a 'remove existing/add new' operation;
// this unfortunately changes the order of the parent's
// child node entries (JCR-1055);
// => backup list of child node entries beforehand in order
// to restore it afterwards
ChildNodeEntry cneConflicting = parent.getChildNodeEntry(nodeInfo.getId());
List<ChildNodeEntry> cneList = new ArrayList<ChildNodeEntry>(parent.getChildNodeEntries());
// do remove conflicting (recursive)
itemOps.removeNodeState(conflicting);
// create new with given uuid at same location as conflicting:
// check if new node can be added at other location
// (access rights, node type constraints, locking & versioning
// status and retention/hold)
itemOps.checkAddNode(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_LOCK | BatchedItemOperations.CHECK_CHECKED_OUT | BatchedItemOperations.CHECK_CONSTRAINTS | BatchedItemOperations.CHECK_HOLD | BatchedItemOperations.CHECK_RETENTION);
// do create new node
node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), nodeInfo.getId());
// restore list of child node entries (JCR-1055)
if (cneConflicting.getName().equals(nodeInfo.getName())) {
// restore original child node list
parent.setChildNodeEntries(cneList);
} else {
// replace child node entry with different name
// but preserving original position
parent.removeAllChildNodeEntries();
for (ChildNodeEntry cne : cneList) {
if (cne.getId().equals(nodeInfo.getId())) {
// replace entry with different name
parent.addChildNodeEntry(nodeInfo.getName(), nodeInfo.getId());
} else {
parent.addChildNodeEntry(cne.getName(), cne.getId());
}
}
}
} else {
String msg = "unknown uuidBehavior: " + uuidBehavior;
log.debug(msg);
throw new RepositoryException(msg);
}
return node;
}
use of org.apache.jackrabbit.core.id.NodeId in project jackrabbit by apache.
the class AccessControlImporter method checkIdMixins.
private static void checkIdMixins(NodeInfo nInfo) throws ConstraintViolationException {
// neither explicit id NOR mixin types may be present.
Name[] mixins = nInfo.getMixinNames();
NodeId id = nInfo.getId();
if (id != null || mixins != null) {
throw new ConstraintViolationException("The node represented by NodeInfo " + nInfo + " may neither be referenceable nor have mixin types.");
}
}
use of org.apache.jackrabbit.core.id.NodeId in project jackrabbit by apache.
the class DocViewImportHandler method startElement.
//-------------------------------------------------------< ContentHandler >
/**
* {@inheritDoc}
* <p>
* See also {@link org.apache.jackrabbit.commons.xml.Exporter#exportProperties(Node)}
* regarding special handling of multi-valued properties on export.
*/
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
// process buffered character data
processCharacters();
try {
Name nodeName = NameFactoryImpl.getInstance().create(namespaceURI, localName);
// process node name
nodeName = processName(nodeName);
// properties
NodeId id = null;
Name nodeTypeName = null;
Name[] mixinTypes = null;
List<PropInfo> props = new ArrayList<PropInfo>(atts.getLength());
for (int i = 0; i < atts.getLength(); i++) {
if (atts.getURI(i).equals(Name.NS_XMLNS_URI)) {
// see http://issues.apache.org/jira/browse/JCR-620#action_12448164
continue;
}
Name propName = NameFactoryImpl.getInstance().create(atts.getURI(i), atts.getLocalName(i));
// process property name
propName = processName(propName);
// value(s)
String attrValue = atts.getValue(i);
TextValue[] propValues;
// always assume single-valued property for the time being
// until a way of properly serializing/detecting multi-valued
// properties on re-import is found (see JCR-325);
// see also DocViewSAXEventGenerator#leavingProperties(Node, int)
// todo proper multi-value serialization support
propValues = new TextValue[1];
propValues[0] = new StringValue(attrValue, resolver, valueFactory);
if (propName.equals(NameConstants.JCR_PRIMARYTYPE)) {
// jcr:primaryType
if (attrValue.length() > 0) {
try {
nodeTypeName = resolver.getQName(attrValue);
} catch (NameException ne) {
throw new SAXException("illegal jcr:primaryType value: " + attrValue, ne);
}
}
} else if (propName.equals(NameConstants.JCR_MIXINTYPES)) {
// jcr:mixinTypes
mixinTypes = parseNames(attrValue);
} else if (propName.equals(NameConstants.JCR_UUID)) {
// jcr:uuid
if (attrValue.length() > 0) {
id = NodeId.valueOf(attrValue);
}
} else {
props.add(new PropInfo(propName, PropertyType.UNDEFINED, propValues));
}
}
NodeInfo node = new NodeInfo(nodeName, nodeTypeName, mixinTypes, id);
// all information has been collected, now delegate to importer
importer.startNode(node, props);
// push current node data onto stack
stack.push(node);
} catch (RepositoryException re) {
throw new SAXException(re);
}
}
Aggregations