Search in sources :

Example 41 with MemTreeBuilder

use of org.exist.dom.memtree.MemTreeBuilder in project exist by eXist-db.

the class ElementConstructor method eval.

@Override
public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException {
    context.expressionStart(this);
    context.pushInScopeNamespaces();
    if (newDocumentContext) {
        context.pushDocumentContext();
    }
    try {
        final MemTreeBuilder builder = context.getDocumentBuilder();
        // declare namespaces
        if (namespaceDecls != null) {
            for (QName namespaceDecl : namespaceDecls) {
                // if ("".equals(namespaceDecls[i].getNamespaceURI())) {
                // TODO: the specs are unclear here: should we throw XQST0085 or not?
                // context.inScopeNamespaces.remove(namespaceDecls[i].getLocalPart());
                // if (context.inScopeNamespaces.remove(namespaceDecls[i].getLocalPart()) == null)
                // throw new XPathException(getAS      TNode(), "XQST0085 : can not undefine '" + namespaceDecls[i] + "'");
                // } else
                context.declareInScopeNamespace(namespaceDecl.getLocalPart(), namespaceDecl.getNamespaceURI());
            }
        }
        // process attributes
        final AttributesImpl attrs = new AttributesImpl();
        if (attributes != null) {
            // first, search for xmlns attributes and declare in-scope namespaces
            for (final AttributeConstructor constructor : attributes) {
                if (constructor.isNamespaceDeclaration()) {
                    final int p = constructor.getQName().indexOf(':');
                    if (p == Constants.STRING_NOT_FOUND) {
                        context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, constructor.getLiteralValue());
                    } else {
                        final String prefix = constructor.getQName().substring(p + 1);
                        context.declareInScopeNamespace(prefix, constructor.getLiteralValue());
                    }
                }
            }
            String v = null;
            // process the remaining attributes
            for (int i = 0; i < attributes.length; i++) {
                context.proceed(this, builder);
                final AttributeConstructor constructor = attributes[i];
                final Sequence attrValues = constructor.eval(contextSequence, contextItem);
                QName attrQName;
                try {
                    attrQName = QName.parse(context, constructor.getQName(), XMLConstants.NULL_NS_URI);
                } catch (final QName.IllegalQNameException e) {
                    throw new XPathException(this, ErrorCodes.XPTY0004, "'" + constructor.getQName() + "' is not a valid attribute name");
                }
                final String namespaceURI = attrQName.getNamespaceURI();
                if (namespaceURI != null && !namespaceURI.isEmpty() && attrQName.getPrefix() == null) {
                    String prefix = context.getPrefixForURI(namespaceURI);
                    if (prefix != null) {
                        attrQName = new QName(attrQName.getLocalPart(), attrQName.getNamespaceURI(), prefix);
                    } else {
                        // generate prefix
                        for (final int n = 1; i < 100; i++) {
                            prefix = "eXnsp" + n;
                            if (context.getURIForPrefix(prefix) == null) {
                                attrQName = new QName(attrQName.getLocalPart(), attrQName.getNamespaceURI(), prefix);
                                break;
                            }
                            prefix = null;
                        }
                        if (prefix == null) {
                            throw new XPathException(this, "Prefix can't be generated.");
                        }
                    }
                }
                if (attrs.getIndex(attrQName.getNamespaceURI(), attrQName.getLocalPart()) != -1) {
                    throw new XPathException(this, ErrorCodes.XQST0040, "'" + attrQName.getLocalPart() + "' is a duplicate attribute name");
                }
                v = DynamicAttributeConstructor.normalize(this, attrQName, attrValues.getStringValue());
                attrs.addAttribute(attrQName.getNamespaceURI(), attrQName.getLocalPart(), attrQName.getStringValue(), "CDATA", v);
            }
        }
        context.proceed(this, builder);
        // create the element
        final Sequence qnameSeq = qnameExpr.eval(contextSequence, contextItem);
        if (!qnameSeq.hasOne()) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "Type error: the node name should evaluate to a single item");
        }
        final Item qnitem = qnameSeq.itemAt(0);
        QName qn;
        if (qnitem instanceof QNameValue) {
            qn = ((QNameValue) qnitem).getQName();
        } else {
            // Do we have the same result than Atomize there ? -pb
            try {
                qn = QName.parse(context, qnitem.getStringValue());
            } catch (final QName.IllegalQNameException e) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "'" + qnitem.getStringValue() + "' is not a valid element name");
            } catch (final XPathException e) {
                e.setLocation(getLine(), getColumn(), getSource());
                throw e;
            }
            /*
                 if (qn.getPrefix() == null && context.inScopeNamespaces.get("xmlns") != null) {
                     qn.setNamespaceURI((String)context.inScopeNamespaces.get("xmlns"));
                 }
                 */
            if (qn.getPrefix() == null && context.getInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX) != null) {
                qn = new QName(qn.getLocalPart(), context.getInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX), qn.getPrefix());
            }
        }
        // Not in the specs but... makes sense
        if (!XMLNames.isName(qn.getLocalPart())) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "'" + qnitem.getStringValue() + "' is not a valid element name");
        }
        // add namespace declaration nodes
        final int nodeNr = builder.startElement(qn, attrs);
        if (namespaceDecls != null) {
            for (QName namespaceDecl : namespaceDecls) {
                builder.namespaceNode(namespaceDecl);
            }
        }
        // do we need to add a namespace declaration for the current node?
        if (qn.hasNamespace()) {
            if (context.getInScopePrefix(qn.getNamespaceURI()) == null) {
                String prefix = qn.getPrefix();
                if (prefix == null) {
                    prefix = XMLConstants.DEFAULT_NS_PREFIX;
                }
                context.declareInScopeNamespace(prefix, qn.getNamespaceURI());
                builder.namespaceNode(new QName(prefix, qn.getNamespaceURI(), XMLConstants.XMLNS_ATTRIBUTE));
            }
        } else if ((qn.getPrefix() == null || qn.getPrefix().length() == 0) && context.getInheritedNamespace(XMLConstants.DEFAULT_NS_PREFIX) != null) {
            context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI);
            builder.namespaceNode(new QName("", XMLConstants.NULL_NS_URI, XMLConstants.XMLNS_ATTRIBUTE));
        } else if (qn.getPrefix() == null || qn.getPrefix().length() == 0) {
            context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI);
        }
        // process element contents
        if (content != null) {
            content.eval(contextSequence, contextItem);
        }
        builder.endElement();
        final NodeImpl node = builder.getDocument().getNode(nodeNr);
        return node;
    } finally {
        context.popInScopeNamespaces();
        if (newDocumentContext) {
            context.popDocumentContext();
        }
        context.expressionEnd(this);
    }
}
Also used : Item(org.exist.xquery.value.Item) AttributesImpl(org.xml.sax.helpers.AttributesImpl) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) NodeImpl(org.exist.dom.memtree.NodeImpl) QName(org.exist.dom.QName) QNameValue(org.exist.xquery.value.QNameValue) Sequence(org.exist.xquery.value.Sequence)

Example 42 with MemTreeBuilder

use of org.exist.dom.memtree.MemTreeBuilder in project exist by eXist-db.

the class EnclosedExpr method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.StaticContext,
     * org.exist.dom.persistent.DocumentSet, org.exist.xquery.value.Sequence)
     */
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();
    }
    // evaluate the expression
    Sequence result;
    context.enterEnclosedExpr();
    try {
        context.pushDocumentContext();
        try {
            result = super.eval(contextSequence, null);
        } finally {
            context.popDocumentContext();
        }
        // create the output
        final MemTreeBuilder builder = context.getDocumentBuilder();
        final DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder);
        receiver.setCheckNS(true);
        try {
            // flatten all arrays in the input sequence
            result = ArrayType.flatten(result);
            final SequenceIterator i = result.iterate();
            Item next = i.nextItem();
            StringBuilder buf = null;
            boolean allowAttribs = true;
            while (next != null) {
                context.proceed(this, builder);
                if (Type.subTypeOf(next.getType(), Type.FUNCTION_REFERENCE)) {
                    throw new XPathException(this, ErrorCodes.XQTY0105, "Enclosed expression contains function item");
                // if item is an atomic value, collect the string values of all
                // following atomic values and separate them by a space.
                } else if (Type.subTypeOf(next.getType(), Type.ATOMIC)) {
                    if (buf == null) {
                        buf = new StringBuilder();
                    } else if (buf.length() > 0) {
                        buf.append(' ');
                    }
                    buf.append(next.getStringValue());
                    allowAttribs = false;
                    next = i.nextItem();
                // If the item is a node, flush any collected character data and
                // copy the node to the target doc.
                } else if (Type.subTypeOf(next.getType(), Type.NODE)) {
                    // such a text node will be deleted or merged with another text node.
                    if (next instanceof TextImpl && ((TextImpl) next).getStringValue().isEmpty()) {
                        next = i.nextItem();
                        continue;
                    }
                    if (buf != null && buf.length() > 0) {
                        receiver.characters(buf);
                        buf.setLength(0);
                    }
                    if (next.getType() == Type.ATTRIBUTE && !allowAttribs) {
                        throw new XPathException(this, ErrorCodes.XQTY0024, "An attribute may not appear after another child node.");
                    }
                    try {
                        receiver.setCheckNS(false);
                        next.copyTo(context.getBroker(), receiver);
                        receiver.setCheckNS(true);
                    } catch (DOMException e) {
                        if (e.code == DOMException.NAMESPACE_ERR) {
                            throw new XPathException(this, ErrorCodes.XQDY0102, e.getMessage());
                        } else {
                            throw new XPathException(this, e.getMessage(), e);
                        }
                    }
                    allowAttribs = next.getType() == Type.ATTRIBUTE || next.getType() == Type.NAMESPACE;
                    next = i.nextItem();
                }
            }
            // flush remaining character data
            if (buf != null && buf.length() > 0) {
                receiver.characters(buf);
            }
        } catch (final SAXException e) {
            LOG.warn("SAXException during serialization: {}", e.getMessage(), e);
            throw new XPathException(this, e);
        }
    } finally {
        context.exitEnclosedExpr();
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : DOMException(org.w3c.dom.DOMException) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) DocumentBuilderReceiver(org.exist.dom.memtree.DocumentBuilderReceiver) TextImpl(org.exist.dom.memtree.TextImpl) SAXException(org.xml.sax.SAXException)

Example 43 with MemTreeBuilder

use of org.exist.dom.memtree.MemTreeBuilder in project exist by eXist-db.

the class DocumentConstructor method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.Expression#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());
        }
    }
    context.pushDocumentContext();
    final Sequence contentSeq = content.eval(contextSequence, contextItem);
    context.popDocumentContext();
    context.pushDocumentContext();
    final MemTreeBuilder builder = context.getDocumentBuilder(true);
    final DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder);
    try {
        if (!contentSeq.isEmpty()) {
            StringBuilder buf = null;
            final SequenceIterator i = contentSeq.iterate();
            Item next = i.nextItem();
            while (next != null) {
                context.proceed(this, builder);
                if (next.getType() == Type.ATTRIBUTE || next.getType() == Type.NAMESPACE) {
                    throw new XPathException(this, "Found a node of type " + Type.getTypeName(next.getType()) + " inside a document constructor");
                }
                // following atomic values and seperate them by a space.
                if (Type.subTypeOf(next.getType(), Type.ATOMIC)) {
                    if (buf == null) {
                        buf = new StringBuilder();
                    } else if (buf.length() > 0) {
                        buf.append(' ');
                    }
                    buf.append(next.getStringValue());
                    next = i.nextItem();
                // if item is a node, flush any collected character data and
                // copy the node to the target doc.
                } else if (next.getType() == Type.DOCUMENT) {
                    if (buf != null && buf.length() > 0) {
                        receiver.characters(buf);
                        buf.setLength(0);
                    }
                    next.copyTo(context.getBroker(), receiver);
                    next = i.nextItem();
                } else if (Type.subTypeOf(next.getType(), Type.NODE)) {
                    if (buf != null && buf.length() > 0) {
                        receiver.characters(buf);
                        buf.setLength(0);
                    }
                    next.copyTo(context.getBroker(), receiver);
                    next = i.nextItem();
                }
            }
            // flush remaining character data
            if (buf != null && buf.length() > 0) {
                receiver.characters(buf);
                buf.setLength(0);
            }
        }
    } catch (final SAXException e) {
        throw new XPathException(this, "Encountered SAX exception while processing document constructor: " + ExpressionDumper.dump(this));
    }
    context.popDocumentContext();
    final NodeImpl node = builder.getDocument();
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", node);
    }
    return node;
}
Also used : Item(org.exist.xquery.value.Item) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) SequenceIterator(org.exist.xquery.value.SequenceIterator) NodeImpl(org.exist.dom.memtree.NodeImpl) Sequence(org.exist.xquery.value.Sequence) DocumentBuilderReceiver(org.exist.dom.memtree.DocumentBuilderReceiver) SAXException(org.xml.sax.SAXException)

Example 44 with MemTreeBuilder

use of org.exist.dom.memtree.MemTreeBuilder in project exist by eXist-db.

the class CDATAConstructor method eval.

@Override
public Sequence eval(final Sequence contextSequence, final 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 (newDocumentContext) {
        context.pushDocumentContext();
    }
    try {
        final MemTreeBuilder builder = context.getDocumentBuilder();
        final NodeImpl node = builder.getDocument().getNode(builder.cdataSection(cdata));
        if (context.getProfiler().isEnabled()) {
            context.getProfiler().end(this, "", node);
        }
        return node;
    } finally {
        if (newDocumentContext) {
            context.popDocumentContext();
        }
    }
}
Also used : MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) NodeImpl(org.exist.dom.memtree.NodeImpl)

Example 45 with MemTreeBuilder

use of org.exist.dom.memtree.MemTreeBuilder in project exist by eXist-db.

the class ExecuteFunctionTest method testEmptyParameters.

@Test
public void testEmptyParameters() throws SQLException, XPathException {
    // mocks a simple SQL prepared statement with one parameter
    // is filled with an empty xsl:param element
    XQueryContext context = new XQueryContextStub();
    ExecuteFunction execute = new ExecuteFunction(context, signatureByArity(ExecuteFunction.FS_EXECUTE, functionName, 3));
    // this is what an empty xsl:param element of type varchar should use to fill prepared statement parameters
    final String emptyStringValue = "";
    final Integer emptyIntValue = null;
    final String sql = "SELECT ? AS COL1, ? AS COL2";
    // create mock objects
    Connection connection = mock(Connection.class);
    PreparedStatement preparedStatement = mock(PreparedStatement.class);
    ResultSet rs = mock(ResultSet.class);
    ResultSetMetaData rsmd = mock(ResultSetMetaData.class);
    Object[] mocks = new Object[] { connection, preparedStatement, rs, rsmd };
    // register mocked connection and prepared statement
    final long connId = SQLModule.storeConnection(context, connection);
    final long stmtId = SQLModule.storePreparedStatement(context, new PreparedStatementWithSQL(sql, preparedStatement));
    // mock behavior
    preparedStatement.setObject(1, emptyStringValue, Types.VARCHAR);
    preparedStatement.setObject(2, emptyIntValue, Types.INTEGER);
    expect(preparedStatement.getConnection()).andReturn(connection);
    expect(preparedStatement.execute()).andReturn(true);
    expect(preparedStatement.getResultSet()).andReturn(rs);
    expect(preparedStatement.getUpdateCount()).andReturn(-1);
    expect(rs.next()).andReturn(true).andReturn(false);
    expect(rs.getRow()).andReturn(1);
    expect(rs.getString(1)).andReturn(emptyStringValue);
    expect(rs.wasNull()).andReturn(emptyStringValue == null);
    expect(rs.getString(2)).andReturn(null);
    expect(rs.wasNull()).andReturn(emptyIntValue == null);
    expect(rs.getMetaData()).andStubReturn(rsmd);
    expect(rsmd.getColumnCount()).andStubReturn(2);
    expect(rsmd.getColumnLabel(1)).andStubReturn("COL1");
    expect(rsmd.getColumnLabel(2)).andStubReturn("COL2");
    expect(rsmd.getColumnTypeName(1)).andStubReturn("VARCHAR");
    expect(rsmd.getColumnTypeName(2)).andStubReturn("INTEGER");
    expect(rsmd.getColumnType(1)).andStubReturn(Types.VARCHAR);
    expect(rsmd.getColumnType(2)).andStubReturn(Types.INTEGER);
    rs.close();
    replay(mocks);
    // execute function
    MemTreeBuilder paramBuilder = new MemTreeBuilder(context);
    paramBuilder.startDocument();
    paramBuilder.startElement(new QName("parameters", SQLModule.NAMESPACE_URI), null);
    paramBuilder.startElement(new QName("param", SQLModule.NAMESPACE_URI), null);
    paramBuilder.addAttribute(new QName("type", SQLModule.NAMESPACE_URI), "varchar");
    paramBuilder.endElement();
    paramBuilder.startElement(new QName("param", SQLModule.NAMESPACE_URI), null);
    paramBuilder.addAttribute(new QName("type", SQLModule.NAMESPACE_URI), "integer");
    paramBuilder.endElement();
    paramBuilder.endElement();
    paramBuilder.endDocument();
    final ElementImpl sqlParams = (ElementImpl) paramBuilder.getDocument().getFirstChild();
    execute.eval(new Sequence[] { new IntegerValue(connId), new IntegerValue(stmtId), sqlParams, new BooleanValue(false) }, Sequence.EMPTY_SEQUENCE);
    // assert expectations
    verify(preparedStatement);
}
Also used : QName(org.exist.dom.QName) XQueryContext(org.exist.xquery.XQueryContext) ElementImpl(org.exist.dom.memtree.ElementImpl) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) Test(org.junit.Test)

Aggregations

MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)82 QName (org.exist.dom.QName)29 XPathException (org.exist.xquery.XPathException)23 Sequence (org.exist.xquery.value.Sequence)19 DocumentBuilderReceiver (org.exist.dom.memtree.DocumentBuilderReceiver)17 SAXException (org.xml.sax.SAXException)16 NodeValue (org.exist.xquery.value.NodeValue)15 IOException (java.io.IOException)14 NodeImpl (org.exist.dom.memtree.NodeImpl)14 Item (org.exist.xquery.value.Item)8 SequenceIterator (org.exist.xquery.value.SequenceIterator)8 Test (org.junit.Test)8 XQueryContext (org.exist.xquery.XQueryContext)7 ValueSequence (org.exist.xquery.value.ValueSequence)7 AttributesImpl (org.xml.sax.helpers.AttributesImpl)7 DocumentImpl (org.exist.dom.memtree.DocumentImpl)6 BrokerPool (org.exist.storage.BrokerPool)6 InputSource (org.xml.sax.InputSource)6 MalformedURLException (java.net.MalformedURLException)5 Path (java.nio.file.Path)5