use of org.exist.stax.EmbeddedXMLStreamReader in project exist by eXist-db.
the class ConsistencyCheck method checkXMLTree.
/**
* Check the persistent DOM of a document. The method traverses the entire node tree and checks it for consistency, including node relationships,
* child and attribute counts etc.
*
* @param doc the document to check
* @return null if the document is consistent, an error report otherwise.
*/
public ErrorReport checkXMLTree(final DocumentImpl doc) {
final DOMFile domDb = ((NativeBroker) broker).getDOMFile();
return new DOMTransaction<ErrorReport>(this, domDb, () -> broker.getBrokerPool().getLockManager().acquireBtreeWriteLock(domDb.getLockName()), doc) {
public ErrorReport start() {
EmbeddedXMLStreamReader reader = null;
try {
final Node root = doc.getFirstChild();
reader = (EmbeddedXMLStreamReader) broker.getXMLStreamReader((NodeHandle) root, true);
boolean attribsAllowed = false;
int expectedAttribs = 0;
int attributeCount = 0;
while (reader.hasNext()) {
final int status = reader.next();
final NodeId nodeId = (NodeId) reader.getProperty(EmbeddedXMLStreamReader.PROPERTY_NODE_ID);
if ((status != XMLStreamReader.END_ELEMENT) && !elementStack.isEmpty()) {
final ElementNode parent = elementStack.peek();
parent.childCount++;
// test parent-child relation
if (!nodeId.isChildOf(parent.elem.getNodeId())) {
return new ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Node " + nodeId + " is not a child of " + parent.elem.getNodeId());
}
// test sibling relation
if ((parent.prevSibling != null) && !(nodeId.isSiblingOf(parent.prevSibling) && (nodeId.compareTo(parent.prevSibling) > 0))) {
return new ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_ID, "Node " + nodeId + " is not a sibling of " + parent.prevSibling);
}
parent.prevSibling = nodeId;
}
switch(status) {
case XMLStreamReader.ATTRIBUTE:
{
attributeCount++;
break;
}
case XMLStreamReader.END_ELEMENT:
{
if (elementStack.isEmpty()) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Error in node hierarchy: received END_ELEMENT event " + "but stack was empty!");
}
final ElementNode lastElem = elementStack.pop();
if (lastElem.childCount != lastElem.elem.getChildCount()) {
return new ErrorReport.ResourceError(org.exist.backup.ErrorReport.NODE_HIERARCHY, "Element reports incorrect child count: expected " + lastElem.elem.getChildCount() + " but found " + lastElem.childCount);
}
break;
}
case XMLStreamReader.START_ELEMENT:
{
if (nodeId.getTreeLevel() <= defaultIndexDepth) {
// check dom.dbx btree, which maps the node
// id to the node's storage address
// look up the node id and check if the
// returned storage address is correct
final NativeBroker.NodeRef nodeRef = new NativeBroker.NodeRef(doc.getDocId(), nodeId);
try {
final long p = domDb.findValue(nodeRef);
if (p != reader.getCurrentPosition()) {
final Value v = domDb.get(p);
if (v == null) {
return new ErrorReport.IndexError(ErrorReport.DOM_INDEX, "Failed to access node " + nodeId + " through dom.dbx index. Wrong storage address. Expected: " + p + "; got: " + reader.getCurrentPosition() + " - ", doc.getDocId());
}
}
} catch (final Exception e) {
e.printStackTrace();
return new ErrorReport.IndexError(ErrorReport.DOM_INDEX, "Failed to access node " + nodeId + " through dom.dbx index.", e, doc.getDocId());
}
}
final IStoredNode node = reader.getNode();
if (node.getNodeType() != Node.ELEMENT_NODE) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_TYPE, "Expected an element node, received node of type " + node.getNodeType());
}
elementStack.push(new ElementNode((ElementImpl) node));
attribsAllowed = true;
attributeCount = 0;
expectedAttribs = reader.getAttributeCount();
break;
}
default:
{
if (attribsAllowed) {
if (attributeCount != expectedAttribs) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_TYPE, "Wrong number of attributes. Expected: " + expectedAttribs + "; found: " + attributeCount);
}
}
attribsAllowed = false;
break;
}
}
}
if (!elementStack.isEmpty()) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Error in node hierarchy: reached end of tree but " + "stack was not empty!");
}
return null;
} catch (final IOException | XMLStreamException e) {
e.printStackTrace();
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.RESOURCE_ACCESS_FAILED, e.getMessage(), e);
} finally {
elementStack.clear();
if (reader != null) {
try {
reader.close();
} catch (final XMLStreamException e) {
e.printStackTrace();
}
}
}
}
}.run();
}
use of org.exist.stax.EmbeddedXMLStreamReader in project exist by eXist-db.
the class DOMFile method findValue.
/**
* Retrieve node at virtual address.
*
* @param broker the database broker
* @param node The virtual address
* @return The reference of the node
* @throws IOException if an I/O error occurs
* @throws BTreeException if an error occurs reading the tree
*/
protected long findValue(final DBBroker broker, final NodeProxy node) throws IOException, BTreeException {
if (LOG.isDebugEnabled() && !lockManager.isBtreeLocked(getLockName())) {
LOG.debug("The file doesn't own a lock");
}
final DocumentImpl doc = node.getOwnerDocument();
final NodeRef nodeRef = new NativeBroker.NodeRef(doc.getDocId(), node.getNodeId());
// first try to find the node in the index
final long pointer = findValue(nodeRef);
if (pointer == KEY_NOT_FOUND) {
// node not found in index: try to find the nearest available
// ancestor and traverse it
NodeId nodeID = node.getNodeId();
long parentPointer = KEY_NOT_FOUND;
do {
nodeID = nodeID.getParentId();
if (nodeID == null) {
SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":<null nodeID> not found.");
throw new BTreeException("Node not found.");
}
if (nodeID == NodeId.DOCUMENT_NODE) {
SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":" + nodeID + " not found.");
return KEY_NOT_FOUND;
}
final NativeBroker.NodeRef parentRef = new NativeBroker.NodeRef(doc.getDocId(), nodeID);
try {
parentPointer = findValue(parentRef);
} catch (final BTreeException bte) {
LOG.error("report me", bte);
}
} while (parentPointer == KEY_NOT_FOUND);
try {
final int thisLevel = nodeID.getTreeLevel();
// lazily initialized below
Integer childLevel = null;
final NodeProxy parent = new NodeProxy(doc, nodeID, parentPointer);
final EmbeddedXMLStreamReader reader = (EmbeddedXMLStreamReader) broker.getXMLStreamReader(parent, true);
while (reader.hasNext()) {
final int status = reader.next();
if (status != XMLStreamReader.END_ELEMENT) {
if (childLevel == null) {
childLevel = reader.getNode().getNodeType() == Node.ELEMENT_NODE ? thisLevel + 1 : thisLevel;
}
final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
if (otherId.equals(node.getNodeId())) {
return reader.getCurrentPosition();
}
}
if (status == XMLStreamConstants.END_ELEMENT) {
final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
final int otherLevel = otherId.getTreeLevel();
if (childLevel != null && childLevel != otherLevel && otherLevel == thisLevel) {
// exit-while
break;
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Node {} could not be found. Giving up. This is usually not an error.", node.getNodeId());
}
return KEY_NOT_FOUND;
} catch (final XMLStreamException e) {
SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":" + node.getNodeId() + " not found.");
throw new BTreeException("Node " + node.getNodeId() + " not found.");
}
} else {
return pointer;
}
}
use of org.exist.stax.EmbeddedXMLStreamReader in project exist by eXist-db.
the class NativeBroker method getXMLStreamReader.
@Override
public IEmbeddedXMLStreamReader getXMLStreamReader(final NodeHandle node, final boolean reportAttributes) throws IOException, XMLStreamException {
if (streamReader == null) {
final RawNodeIterator iterator = new RawNodeIterator(this, domDb, node);
streamReader = new EmbeddedXMLStreamReader(this, node.getOwnerDocument(), iterator, node, reportAttributes);
} else {
streamReader.reposition(this, node, reportAttributes);
}
return streamReader;
}
use of org.exist.stax.EmbeddedXMLStreamReader in project exist by eXist-db.
the class VirtualNodeSet method addChildren.
private void addChildren(final NodeProxy contextNode, final NodeSet result) {
try {
final EmbeddedXMLStreamReader reader = (EmbeddedXMLStreamReader) broker.getXMLStreamReader(contextNode, true);
int status = reader.next();
if (status != XMLStreamConstants.START_ELEMENT) {
return;
}
int level = 0;
while (reader.hasNext()) {
status = reader.next();
if (axis == Constants.ATTRIBUTE_AXIS && status != XMLStreamConstants.ATTRIBUTE) {
break;
}
switch(status) {
case XMLStreamConstants.END_ELEMENT:
if (--level < 0) {
return;
}
break;
case XMLStreamConstants.ATTRIBUTE:
if ((axis == Constants.ATTRIBUTE_AXIS && level == 0) || axis == Constants.DESCENDANT_ATTRIBUTE_AXIS) {
final AttrImpl attr = (AttrImpl) reader.getNode();
if (test.matches(attr)) {
final NodeProxy p = new NodeProxy(attr);
p.deepCopyContext(contextNode);
if (useSelfAsContext && inPredicate) {
p.addContextNode(contextId, p);
} else if (inPredicate) {
p.addContextNode(contextId, contextNode);
}
result.add(p);
}
}
break;
default:
if (((axis == Constants.CHILD_AXIS && level == 0) || axis == Constants.DESCENDANT_AXIS || axis == Constants.DESCENDANT_SELF_AXIS) && test.matches(reader)) {
final NodeId nodeId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
final NodeProxy p = new NodeProxy(contextNode.getOwnerDocument(), nodeId, reader.getNodeType(), reader.getCurrentPosition());
p.deepCopyContext(contextNode);
if (useSelfAsContext && inPredicate) {
p.addContextNode(contextId, p);
} else if (inPredicate) {
p.addContextNode(contextId, contextNode);
}
result.add(p);
}
break;
}
if (status == XMLStreamConstants.START_ELEMENT) {
++level;
}
}
} catch (final IOException | XMLStreamException e) {
LOG.error(e);
// TODO : throw exception ,
}
// TODO : throw exception ? -pb
}
Aggregations