Search in sources :

Example 6 with StoredNode

use of org.exist.dom.persistent.StoredNode in project exist by eXist-db.

the class Insert method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
     */
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
        if (contextItem != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
        }
    }
    if (contextItem != null) {
        contextSequence = contextItem.toSequence();
    }
    Sequence contentSeq = value.eval(contextSequence);
    if (contentSeq.isEmpty()) {
        throw new XPathException(this, Messages.getMessage(Error.UPDATE_EMPTY_CONTENT));
    }
    final Sequence inSeq = select.eval(contextSequence);
    /* If we try and Insert a node at an invalid location,
         * trap the error in a context variable,
         * this is then accessible from xquery via. the context extension module - deliriumsky
         * TODO: This trapping could be expanded further - basically where XPathException is thrown from thiss class
         * TODO: Maybe we could provide more detailed messages in the trap, e.g. couldnt insert node `xyz` into `abc` becuase... this would be nicer for the end user of the xquery application 
         */
    if (!Type.subTypeOf(inSeq.getItemType(), Type.NODE)) {
        // Indicate the failure to perform this update by adding it to the sequence in the context variable XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR
        ValueSequence prevUpdateErrors = null;
        final XPathException xpe = new XPathException(this, Messages.getMessage(Error.UPDATE_SELECT_TYPE));
        final Object ctxVarObj = context.getAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR);
        if (ctxVarObj == null) {
            prevUpdateErrors = new ValueSequence();
        } else {
            prevUpdateErrors = (ValueSequence) XPathUtil.javaObjectToXPath(ctxVarObj, context);
        }
        prevUpdateErrors.add(new StringValue(xpe.getMessage()));
        context.setAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR, prevUpdateErrors);
        if (!inSeq.isEmpty()) {
            // TODO: should we trap this instead of throwing an exception - deliriumsky?
            throw xpe;
        }
    }
    if (!inSeq.isEmpty()) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Found: {} nodes", inSeq.getItemCount());
        }
        context.pushInScopeNamespaces();
        contentSeq = deepCopy(contentSeq);
        // start a transaction
        try (final Txn transaction = getTransaction()) {
            final StoredNode[] ql = selectAndLock(transaction, inSeq);
            final NotificationService notifier = context.getBroker().getBrokerPool().getNotificationService();
            final NodeList contentList = seq2nodeList(contentSeq);
            for (final StoredNode node : ql) {
                final DocumentImpl doc = node.getOwnerDocument();
                if (!doc.getPermissions().validate(context.getSubject(), Permission.WRITE)) {
                    throw new PermissionDeniedException("User '" + context.getSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
                }
                // update the document
                if (mode == INSERT_APPEND) {
                    node.appendChildren(transaction, contentList, -1);
                } else {
                    final NodeImpl parent = (NodeImpl) getParent(node);
                    switch(mode) {
                        case INSERT_BEFORE:
                            parent.insertBefore(transaction, contentList, node);
                            break;
                        case INSERT_AFTER:
                            parent.insertAfter(transaction, contentList, node);
                            break;
                    }
                }
                doc.setLastModified(System.currentTimeMillis());
                modifiedDocuments.add(doc);
                context.getBroker().storeXMLResource(transaction, doc);
                notifier.notifyUpdate(doc, UpdateListener.UPDATE);
            }
            finishTriggers(transaction);
            // commit the transaction
            transaction.commit();
        } catch (final PermissionDeniedException | EXistException | LockException | TriggerException e) {
            throw new XPathException(this, e.getMessage(), e);
        } finally {
            unlockDocuments();
            context.popInScopeNamespaces();
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", Sequence.EMPTY_SEQUENCE);
    }
    return Sequence.EMPTY_SEQUENCE;
}
Also used : NodeImpl(org.exist.dom.persistent.NodeImpl) XPathException(org.exist.xquery.XPathException) NodeList(org.w3c.dom.NodeList) NotificationService(org.exist.storage.NotificationService) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) Txn(org.exist.storage.txn.Txn) EXistException(org.exist.EXistException) DocumentImpl(org.exist.dom.persistent.DocumentImpl) LockException(org.exist.util.LockException) ValueSequence(org.exist.xquery.value.ValueSequence) PermissionDeniedException(org.exist.security.PermissionDeniedException) StringValue(org.exist.xquery.value.StringValue) TriggerException(org.exist.collections.triggers.TriggerException) StoredNode(org.exist.dom.persistent.StoredNode)

Example 7 with StoredNode

use of org.exist.dom.persistent.StoredNode in project exist by eXist-db.

the class Update method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
     */
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
        if (contextItem != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
        }
    }
    if (contextItem != null) {
        contextSequence = contextItem.toSequence();
    }
    final Sequence contentSeq = value.eval(contextSequence);
    if (contentSeq.isEmpty()) {
        throw new XPathException(this, Messages.getMessage(Error.UPDATE_EMPTY_CONTENT));
    }
    final Sequence inSeq = select.eval(contextSequence);
    /* If we try and Update a node at an invalid location,
         * trap the error in a context variable,
         * this is then accessible from xquery via. the context extension module - deliriumsky
         * TODO: This trapping could be expanded further - basically where XPathException is thrown from thiss class
         * TODO: Maybe we could provide more detailed messages in the trap, e.g. couldnt update node `xyz` into `abc` becuase... this would be nicer for the end user of the xquery application
         */
    if (!Type.subTypeOf(inSeq.getItemType(), Type.NODE)) {
        // Indicate the failure to perform this update by adding it to the sequence in the context variable XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR
        ValueSequence prevUpdateErrors = null;
        final XPathException xpe = new XPathException(this, Messages.getMessage(Error.UPDATE_SELECT_TYPE));
        final Object ctxVarObj = context.getAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR);
        if (ctxVarObj == null) {
            prevUpdateErrors = new ValueSequence();
        } else {
            prevUpdateErrors = (ValueSequence) XPathUtil.javaObjectToXPath(ctxVarObj, context);
        }
        prevUpdateErrors.add(new StringValue(xpe.getMessage()));
        context.setAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR, prevUpdateErrors);
        if (!inSeq.isEmpty()) {
            // TODO: should we trap this instead of throwing an exception - deliriumsky?
            throw xpe;
        }
    }
    if (!inSeq.isEmpty()) {
        context.pushInScopeNamespaces();
        // start a transaction
        try (final Txn transaction = getTransaction()) {
            final NotificationService notifier = context.getBroker().getBrokerPool().getNotificationService();
            final StoredNode[] ql = selectAndLock(transaction, inSeq);
            for (final StoredNode node : ql) {
                final DocumentImpl doc = node.getOwnerDocument();
                if (!doc.getPermissions().validate(context.getSubject(), Permission.WRITE)) {
                    throw new XPathException(this, "User '" + context.getSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
                }
                // update the document
                switch(node.getNodeType()) {
                    case Node.ELEMENT_NODE:
                        final NodeListImpl content = new NodeListImpl();
                        for (final SequenceIterator j = contentSeq.iterate(); j.hasNext(); ) {
                            final Item next = j.nextItem();
                            if (Type.subTypeOf(next.getType(), Type.NODE)) {
                                content.add(((NodeValue) next).getNode());
                            } else {
                                final TextImpl text = new TextImpl(next.getStringValue());
                                content.add(text);
                            }
                        }
                        ((ElementImpl) node).update(transaction, content);
                        break;
                    case Node.TEXT_NODE:
                        final ElementImpl textParent = (ElementImpl) node.getParentNode();
                        final TextImpl text = new TextImpl(contentSeq.getStringValue());
                        text.setOwnerDocument(doc);
                        textParent.updateChild(transaction, node, text);
                        break;
                    case Node.ATTRIBUTE_NODE:
                        final ElementImpl attrParent = (ElementImpl) ((Attr) node).getOwnerElement();
                        if (attrParent == null) {
                            LOG.warn("parent node not found for {}", node.getNodeId());
                            break;
                        }
                        final AttrImpl attr = (AttrImpl) node;
                        final AttrImpl attribute = new AttrImpl(attr.getQName(), contentSeq.getStringValue(), context.getBroker().getBrokerPool().getSymbols());
                        attribute.setOwnerDocument(doc);
                        attrParent.updateChild(transaction, node, attribute);
                        break;
                    default:
                        throw new XPathException(this, "unsupported node-type");
                }
                doc.setLastModified(System.currentTimeMillis());
                modifiedDocuments.add(doc);
                context.getBroker().storeXMLResource(transaction, doc);
                notifier.notifyUpdate(doc, UpdateListener.UPDATE);
            }
            finishTriggers(transaction);
            // commit the transaction
            transaction.commit();
        } catch (final LockException | EXistException | TriggerException e) {
            throw new XPathException(this, e.getMessage(), e);
        } finally {
            unlockDocuments();
            context.popInScopeNamespaces();
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", Sequence.EMPTY_SEQUENCE);
    }
    return Sequence.EMPTY_SEQUENCE;
}
Also used : NodeListImpl(org.exist.dom.NodeListImpl) XPathException(org.exist.xquery.XPathException) NotificationService(org.exist.storage.NotificationService) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) Txn(org.exist.storage.txn.Txn) AttrImpl(org.exist.dom.persistent.AttrImpl) EXistException(org.exist.EXistException) DocumentImpl(org.exist.dom.persistent.DocumentImpl) TextImpl(org.exist.dom.persistent.TextImpl) Item(org.exist.xquery.value.Item) ElementImpl(org.exist.dom.persistent.ElementImpl) SequenceIterator(org.exist.xquery.value.SequenceIterator) LockException(org.exist.util.LockException) ValueSequence(org.exist.xquery.value.ValueSequence) StringValue(org.exist.xquery.value.StringValue) TriggerException(org.exist.collections.triggers.TriggerException) StoredNode(org.exist.dom.persistent.StoredNode)

Example 8 with StoredNode

use of org.exist.dom.persistent.StoredNode in project exist by eXist-db.

the class Replace method process.

@Override
public long process(Txn transaction) throws PermissionDeniedException, LockException, EXistException, XPathException, TriggerException {
    final NodeList children = content;
    if (children.getLength() == 0) {
        return 0;
    }
    if (children.getLength() > 1) {
        throw new EXistException("xupdate:replace requires exactly one content node");
    }
    LOG.debug("processing replace ...");
    int modifications = children.getLength();
    try {
        final StoredNode[] ql = selectAndLock(transaction);
        final NotificationService notifier = broker.getBrokerPool().getNotificationService();
        Node temp;
        TextImpl text;
        AttrImpl attribute;
        ElementImpl parent;
        for (final StoredNode node : ql) {
            if (node == null) {
                LOG.warn("select {} returned empty node set", selectStmt);
                continue;
            }
            final DocumentImpl doc = node.getOwnerDocument();
            if (!doc.getPermissions().validate(broker.getCurrentSubject(), Permission.WRITE)) {
                throw new PermissionDeniedException("User '" + broker.getCurrentSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
            }
            parent = (ElementImpl) node.getParentStoredNode();
            if (parent == null) {
                throw new EXistException("The root element of a document can not be replaced with 'xu:replace'. " + "Please consider removing the document or use 'xu:update' to just replace the children of the root.");
            }
            switch(node.getNodeType()) {
                case Node.ELEMENT_NODE:
                    if (modifications == 0) {
                        modifications = 1;
                    }
                    temp = children.item(0);
                    parent.replaceChild(transaction, temp, node);
                    break;
                case Node.TEXT_NODE:
                    temp = children.item(0);
                    text = new TextImpl(temp.getNodeValue());
                    modifications = 1;
                    text.setOwnerDocument(doc);
                    parent.updateChild(transaction, node, text);
                    break;
                case Node.ATTRIBUTE_NODE:
                    final AttrImpl attr = (AttrImpl) node;
                    temp = children.item(0);
                    attribute = new AttrImpl(attr.getQName(), temp.getNodeValue(), broker.getBrokerPool().getSymbols());
                    attribute.setOwnerDocument(doc);
                    parent.updateChild(transaction, node, attribute);
                    break;
                default:
                    throw new EXistException("unsupported node-type");
            }
            doc.setLastModified(System.currentTimeMillis());
            modifiedDocuments.add(doc);
            broker.storeXMLResource(transaction, doc);
            notifier.notifyUpdate(doc, UpdateListener.UPDATE);
        }
        checkFragmentation(transaction, modifiedDocuments);
    } finally {
        unlockDocuments(transaction);
    }
    return modifications;
}
Also used : ElementImpl(org.exist.dom.persistent.ElementImpl) NodeList(org.w3c.dom.NodeList) StoredNode(org.exist.dom.persistent.StoredNode) Node(org.w3c.dom.Node) NotificationService(org.exist.storage.NotificationService) PermissionDeniedException(org.exist.security.PermissionDeniedException) EXistException(org.exist.EXistException) AttrImpl(org.exist.dom.persistent.AttrImpl) DocumentImpl(org.exist.dom.persistent.DocumentImpl) TextImpl(org.exist.dom.persistent.TextImpl) StoredNode(org.exist.dom.persistent.StoredNode)

Example 9 with StoredNode

use of org.exist.dom.persistent.StoredNode in project exist by eXist-db.

the class Serializer method serialize.

public void serialize(DocumentImpl doc, Writer writer, boolean prepareStylesheet) throws SAXException {
    if (prepareStylesheet) {
        try {
            prepareStylesheets(doc);
        } catch (final TransformerConfigurationException e) {
            throw new SAXException(e.getMessage(), e);
        }
    }
    if (templates != null) {
        applyXSLHandler(writer);
    } else {
        // looking for serializer properties in <?exist-serialize?>
        final NodeList children = doc.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            final StoredNode node = (StoredNode) children.item(i);
            if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && "exist-serialize".equals(node.getNodeName())) {
                final String[] params = ((ProcessingInstructionImpl) node).getData().split(" ");
                for (final String param : params) {
                    final String[] opt = Option.parseKeyValuePair(param);
                    if (opt != null) {
                        outputProperties.setProperty(opt[0], opt[1]);
                    }
                }
            }
        }
        setPrettyPrinter(writer, "no".equals(outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")), null, // setPrettyPrinter(writer, false);
        true);
    }
    serializeToReceiver(doc, true);
    releasePrettyPrinter();
}
Also used : TransformerConfigurationException(javax.xml.transform.TransformerConfigurationException) NodeList(org.w3c.dom.NodeList) SAXException(org.xml.sax.SAXException) StoredNode(org.exist.dom.persistent.StoredNode)

Example 10 with StoredNode

use of org.exist.dom.persistent.StoredNode in project exist by eXist-db.

the class GetFragmentBetween method getFragmentBetween.

/**
 * Fetch the fragment between two nodes (normally milestones) in an XML document
 *
 * @param node1 first node from which down to the node node2 the XML fragment is delivered as a string
 * @param node2 the node to which down the XML fragment is delivered as a string
 *
 * @return fragment between the two nodes
 *
 * @throws XPathException
 */
private StringBuilder getFragmentBetween(final Node node1, final Optional<Node> node2) throws XPathException {
    final StoredNode storedNode1 = (StoredNode) node1;
    final Optional<StoredNode> storedNode2 = node2.map(n -> (StoredNode) n);
    final NodeId node1NodeId = storedNode1.getNodeId();
    final Optional<NodeId> node2NodeId = storedNode2.map(StoredNode::getNodeId);
    final DocumentImpl docImpl = (DocumentImpl) node1.getOwnerDocument();
    final StringBuilder resultFragment = new StringBuilder();
    Optional<NodeId> actualNodeId = Optional.empty();
    boolean getFragmentMode = false;
    try {
        final BrokerPool brokerPool = docImpl.getBrokerPool();
        try (final DBBroker dbBroker = brokerPool.getBroker()) {
            final NodeList children = docImpl.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                final StoredNode docChildStoredNode = (StoredNode) children.item(i);
                final int docChildStoredNodeType = docChildStoredNode.getNodeType();
                final IEmbeddedXMLStreamReader reader = dbBroker.getXMLStreamReader(docChildStoredNode, false);
                while (reader.hasNext() && !node2NodeId.equals(actualNodeId) && docChildStoredNodeType != Node.PROCESSING_INSTRUCTION_NODE && docChildStoredNodeType != Node.COMMENT_NODE) {
                    final int status = reader.next();
                    switch(status) {
                        case XMLStreamReader.START_DOCUMENT:
                        case XMLStreamReader.END_DOCUMENT:
                            break;
                        case XMLStreamReader.START_ELEMENT:
                            actualNodeId = Optional.of(reader.getNode().getNodeId());
                            if (actualNodeId.map(node1NodeId::equals).orElse(false)) {
                                getFragmentMode = true;
                            }
                            if (actualNodeId.equals(node2NodeId)) {
                                getFragmentMode = false;
                            }
                            if (getFragmentMode) {
                                final String startElementTag = getStartElementTag(reader);
                                resultFragment.append(startElementTag);
                            }
                            break;
                        case XMLStreamReader.END_ELEMENT:
                            if (getFragmentMode) {
                                final String endElementTag = getEndElementTag(reader);
                                resultFragment.append(endElementTag);
                            }
                            break;
                        case XMLStreamReader.CHARACTERS:
                            if (getFragmentMode) {
                                final String characters = getCharacters(reader);
                                resultFragment.append(characters);
                            }
                            break;
                        case XMLStreamReader.CDATA:
                            if (getFragmentMode) {
                                final String cdata = getCDataTag(reader);
                                resultFragment.append(cdata);
                            }
                            break;
                        case XMLStreamReader.COMMENT:
                            if (getFragmentMode) {
                                final String comment = getCommentTag(reader);
                                resultFragment.append(comment);
                            }
                            break;
                        case XMLStreamReader.PROCESSING_INSTRUCTION:
                            if (getFragmentMode) {
                                final String piTag = getPITag(reader);
                                resultFragment.append(piTag);
                            }
                            break;
                    }
                }
            }
        }
    } catch (final EXistException | XMLStreamException | IOException e) {
        throw new XPathException(this, "An error occurred while getFragmentBetween: " + e.getMessage(), e);
    }
    return resultFragment;
}
Also used : NodeList(org.w3c.dom.NodeList) EXistException(org.exist.EXistException) IOException(java.io.IOException) IEmbeddedXMLStreamReader(org.exist.stax.IEmbeddedXMLStreamReader) DocumentImpl(org.exist.dom.persistent.DocumentImpl) DBBroker(org.exist.storage.DBBroker) XMLStreamException(javax.xml.stream.XMLStreamException) NodeId(org.exist.numbering.NodeId) BrokerPool(org.exist.storage.BrokerPool) StoredNode(org.exist.dom.persistent.StoredNode)

Aggregations

StoredNode (org.exist.dom.persistent.StoredNode)13 DocumentImpl (org.exist.dom.persistent.DocumentImpl)12 NotificationService (org.exist.storage.NotificationService)9 EXistException (org.exist.EXistException)8 PermissionDeniedException (org.exist.security.PermissionDeniedException)8 NodeList (org.w3c.dom.NodeList)8 TriggerException (org.exist.collections.triggers.TriggerException)4 AttrImpl (org.exist.dom.persistent.AttrImpl)4 ElementImpl (org.exist.dom.persistent.ElementImpl)4 NodeImpl (org.exist.dom.persistent.NodeImpl)4 TextImpl (org.exist.dom.persistent.TextImpl)4 Txn (org.exist.storage.txn.Txn)4 LockException (org.exist.util.LockException)4 XPathException (org.exist.xquery.XPathException)4 Sequence (org.exist.xquery.value.Sequence)4 StringValue (org.exist.xquery.value.StringValue)4 ValueSequence (org.exist.xquery.value.ValueSequence)4 Item (org.exist.xquery.value.Item)3 Node (org.w3c.dom.Node)3 DefaultDocumentSet (org.exist.dom.persistent.DefaultDocumentSet)2