use of org.exist.xquery.value.Item in project exist by eXist-db.
the class XSLTServlet method doPost.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String uri = (String) request.getAttribute(REQ_ATTRIBUTE_STYLESHEET);
if (uri == null) {
throw new ServletException("No stylesheet source specified!");
}
Item inputNode = null;
final String sourceAttrib = (String) request.getAttribute(REQ_ATTRIBUTE_INPUT);
if (sourceAttrib != null) {
Object sourceObj = request.getAttribute(sourceAttrib);
if (sourceObj != null) {
if (sourceObj instanceof ValueSequence) {
final ValueSequence seq = (ValueSequence) sourceObj;
if (seq.size() == 1) {
sourceObj = seq.itemAt(0);
}
}
if (sourceObj instanceof Item) {
inputNode = (Item) sourceObj;
if (!Type.subTypeOf(inputNode.getType(), Type.NODE)) {
throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + sourceAttrib);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Taking XSLT input from request attribute {}", sourceAttrib);
}
} else {
throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + sourceAttrib);
}
}
}
try {
pool = BrokerPool.getInstance();
} catch (final EXistException e) {
throw new ServletException(e.getMessage(), e);
}
Subject user = pool.getSecurityManager().getGuestSubject();
Subject requestUser = HttpAccount.getUserFromServletRequest(request);
if (requestUser != null) {
user = requestUser;
}
// Retrieve username / password from HTTP request attributes
final String userParam = (String) request.getAttribute("xslt.user");
final String passwd = (String) request.getAttribute("xslt.password");
if (userParam != null) {
try {
user = pool.getSecurityManager().authenticate(userParam, passwd);
} catch (final AuthenticationException e1) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Wrong password or user");
return;
}
}
final Stylesheet stylesheet = stylesheet(uri, request, response);
if (stylesheet == null) {
return;
}
// do the transformation
try (final DBBroker broker = pool.get(Optional.of(user))) {
final TransformerHandler handler = stylesheet.newTransformerHandler(broker, errorListener);
setTransformerParameters(request, handler.getTransformer());
final Properties properties = handler.getTransformer().getOutputProperties();
setOutputProperties(request, properties);
String encoding = properties.getProperty("encoding");
if (encoding == null) {
encoding = "UTF-8";
}
response.setCharacterEncoding(encoding);
final String mediaType = properties.getProperty("media-type");
if (mediaType != null) {
// check, do mediaType have "charset"
if (!mediaType.contains("charset")) {
response.setContentType(mediaType + "; charset=" + encoding);
} else {
response.setContentType(mediaType);
}
}
final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
final Writer writer = new BufferedWriter(response.getWriter());
sax.setOutput(writer, properties);
final SAXResult result = new SAXResult(sax);
handler.setResult(result);
final Serializer serializer = broker.borrowSerializer();
Receiver receiver = new ReceiverToSAX(handler);
try {
XIncludeFilter xinclude = new XIncludeFilter(serializer, receiver);
receiver = xinclude;
String baseUri;
final String base = (String) request.getAttribute(REQ_ATTRIBUTE_BASE);
if (base != null) {
baseUri = getServletContext().getRealPath(base);
} else if (uri.startsWith("xmldb:exist://")) {
baseUri = XmldbURI.xmldbUriFor(uri).getCollectionPath();
} else {
baseUri = getCurrentDir(request).toAbsolutePath().toString();
}
xinclude.setModuleLoadPath(baseUri);
serializer.setReceiver(receiver);
if (inputNode != null) {
serializer.toSAX((NodeValue) inputNode);
} else {
final SAXToReceiver saxreceiver = new SAXToReceiver(receiver);
final XMLReader reader = pool.getParserPool().borrowXMLReader();
try {
reader.setContentHandler(saxreceiver);
// Handle gziped input stream
InputStream stream;
InputStream inStream = new BufferedInputStream(request.getInputStream());
inStream.mark(10);
try {
stream = new GZIPInputStream(inStream);
} catch (final IOException e) {
inStream.reset();
stream = inStream;
}
reader.parse(new InputSource(stream));
} finally {
pool.getParserPool().returnXMLReader(reader);
}
}
} catch (final SAXParseException e) {
LOG.error(e.getMessage());
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (final SAXException e) {
throw new ServletException("SAX exception while transforming node: " + e.getMessage(), e);
} finally {
SerializerPool.getInstance().returnObject(sax);
broker.returnSerializer(serializer);
}
writer.flush();
response.flushBuffer();
} catch (final IOException e) {
throw new ServletException("IO exception while transforming node: " + e.getMessage(), e);
} catch (final TransformerException e) {
throw new ServletException("Exception while transforming node: " + e.getMessage(), e);
} catch (final Throwable e) {
LOG.error(e);
throw new ServletException("An error occurred: " + e.getMessage(), e);
}
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class Predicate method evalBoolean.
/**
* Evaluate the inner part of the predicate as a boolean.
*
* @param contextSequence the context sequence
* @param inner the inner expression
*
* @return The result of the boolean evaluation of the predicate.
*
* @throws XPathException if an error occurs
*/
private Sequence evalBoolean(final Sequence contextSequence, final Expression inner, final int mode) throws XPathException {
final Sequence result = new ValueSequence();
int p;
if (contextSequence instanceof NodeSet && ((NodeSet) contextSequence).getProcessInReverseOrder()) {
// This one may be expensive...
p = contextSequence.getItemCount();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p--) {
// 0-based
context.setContextSequencePosition(p - 1, contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.effectiveBooleanValue()) {
result.add(item);
}
}
} else {
// 0-based
p = 0;
final boolean reverseAxis = Type.subTypeOf(contextSequence.getItemType(), Type.NODE) && (mode == Constants.ANCESTOR_AXIS || mode == Constants.ANCESTOR_SELF_AXIS || mode == Constants.PARENT_AXIS || mode == Constants.PRECEDING_AXIS || mode == Constants.PRECEDING_SIBLING_AXIS);
// ... but grab some context positions ! -<8-P
if (Type.subTypeOfUnion(inner.returnsType(), Type.NUMBER) && Dependency.dependsOn(inner, Dependency.CONTEXT_ITEM)) {
final Set<NumericValue> positions = new TreeSet<>();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p++) {
context.setContextSequencePosition(p, contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.hasOne()) {
final NumericValue nv = (NumericValue) innerSeq.itemAt(0);
// Non integers return... nothing, not even an error !
if (!nv.hasFractionalPart() && !nv.isZero()) {
positions.add(nv);
}
}
// XXX: else error or nothing?
}
for (final NumericValue pos : positions) {
final int position = (reverseAxis ? contextSequence.getItemCount() - pos.getInt() : pos.getInt() - 1);
// TODO : move this test above ?
if (position <= contextSequence.getItemCount()) {
result.add(contextSequence.itemAt(position));
}
}
} else {
final Set<NumericValue> positions = new TreeSet<>();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p++) {
context.setContextSequencePosition((reverseAxis ? contextSequence.getItemCount() - p - 1 : p), contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.hasOne() && Type.subTypeOfUnion(innerSeq.getItemType(), Type.NUMBER)) {
// TODO : introduce a check in innerSeq.hasOne() ?
final NumericValue nv = (NumericValue) innerSeq;
// Non integers return... nothing, not even an error !
if (!nv.hasFractionalPart() && !nv.isZero()) {
positions.add(nv);
}
} else if (innerSeq.effectiveBooleanValue()) {
result.add(item);
}
}
for (final NumericValue pos : positions) {
final int position = (reverseAxis ? contextSequence.getItemCount() - pos.getInt() : pos.getInt() - 1);
// TODO : move this test above ?
if (position <= contextSequence.getItemCount()) {
result.add(contextSequence.itemAt(position));
}
}
}
}
return result;
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class QuantifiedExpression method eval.
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());
}
}
final LocalVariable var;
try {
var = new LocalVariable(QName.parse(context, varName, null));
} catch (final QName.IllegalQNameException e) {
throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + varName);
}
final Sequence inSeq = inputSequence.eval(contextSequence, contextItem);
if (sequenceType != null) {
// Type.EMPTY is *not* a subtype of other types ; the tests below would fail without this prior cardinality check
if (!inSeq.isEmpty() && !Type.subTypeOf(inSeq.getItemType(), sequenceType.getPrimaryType())) {
throw new XPathException(this, ErrorCodes.XPTY0004, "Invalid type for variable $" + varName + ". Expected " + Type.getTypeName(sequenceType.getPrimaryType()) + ", got " + Type.getTypeName(inSeq.getItemType()), inSeq);
}
}
boolean found = (mode == EVERY) ? true : false;
boolean canDecide = (mode == EVERY) ? true : false;
for (final SequenceIterator i = inSeq.iterate(); i.hasNext(); ) {
canDecide = true;
final Item item = i.nextItem();
// set variable value to current item
var.setValue(item.toSequence());
if (sequenceType == null) // ... because is makes some conversions
{
var.checkType();
}
Sequence satisfiesSeq = null;
// Binds the variable : now in scope
final LocalVariable mark = context.markLocalVariables(false);
try {
context.declareVariableBinding(var);
// Evaluate the return clause for the current value of the variable
satisfiesSeq = returnExpr.eval(contextSequence, contextItem);
} finally {
// Unbind the variable until the next iteration : now out of scope
context.popLocalVariables(mark, satisfiesSeq);
}
if (sequenceType != null) {
// TODO : ignore nodes right now ; they are returned as xs:untypedAtomicType
if (!Type.subTypeOf(sequenceType.getPrimaryType(), Type.NODE)) {
if (!Type.subTypeOf(item.toSequence().getItemType(), sequenceType.getPrimaryType())) {
throw new XPathException(this, ErrorCodes.XPTY0004, "Invalid type for variable $" + varName + ". Expected " + Type.getTypeName(sequenceType.getPrimaryType()) + ", got " + Type.getTypeName(contextItem.toSequence().getItemType()), inSeq);
}
} else if (!Type.subTypeOf(item.getType(), Type.NODE)) {
throw new XPathException(this, ErrorCodes.XPTY0004, "Invalid type for variable $" + varName + ". Expected " + Type.getTypeName(Type.NODE) + " (or more specific), got " + Type.getTypeName(item.getType()), inSeq);
} else // trigger the old behaviour
{
var.checkType();
}
}
found = satisfiesSeq.effectiveBooleanValue();
if ((mode == SOME) && found) {
break;
}
if ((mode == EVERY) && !found) {
break;
}
}
final Sequence result = canDecide && found ? BooleanValue.TRUE : BooleanValue.FALSE;
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class GeneralComparison method quickNodeSetCompare.
/**
* Optimized implementation: first checks if a range index is defined on the nodes in the left argument.
* Otherwise, fall back to {@link #nodeSetCompare(NodeSet, Sequence)}.
*
* @param contextSequence DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws XPathException DOCUMENT ME!
*/
protected Sequence quickNodeSetCompare(Sequence contextSequence) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "quickNodeSetCompare");
}
final long start = System.currentTimeMillis();
// get the NodeSet on the left
final Sequence leftSeq = getLeft().eval(contextSequence);
if (!leftSeq.isPersistentSet()) {
return (genericCompare(leftSeq, contextSequence, null));
}
final NodeSet nodes = leftSeq.isEmpty() ? NodeSet.EMPTY_SET : (NodeSet) leftSeq;
// nothing on the left, so nothing to do
if (!(nodes instanceof VirtualNodeSet) && nodes.isEmpty()) {
// Well, we might discuss this one ;-)
hasUsedIndex = true;
return (Sequence.EMPTY_SEQUENCE);
}
// get the Sequence on the right
final Sequence rightSeq = getRight().eval(contextSequence);
// nothing on the right, so nothing to do
if (rightSeq.isEmpty()) {
// Well, we might discuss this one ;-)
hasUsedIndex = true;
return (Sequence.EMPTY_SEQUENCE);
}
// get the type of a possible index
final int indexType = nodes.getIndexType();
// remember that Type.ITEM means... no index ;-)
if (indexType != Type.ITEM) {
if (LOG.isTraceEnabled()) {
LOG.trace("found an index of type: {}", Type.getTypeName(indexType));
}
boolean indexScan = false;
boolean indexMixed = false;
QName myContextQName = contextQName;
if (contextSequence != null) {
final IndexFlags iflags = checkForQNameIndex(idxflags, context, contextSequence, myContextQName);
boolean indexFound = false;
if (!iflags.indexOnQName) {
// if myContextQName != null and no index is defined on
// myContextQName, we don't need to scan other QName indexes
// and can just use the generic range index
indexFound = myContextQName != null;
if (iflags.partialIndexOnQName) {
indexMixed = true;
} else {
// set myContextQName to null so the index lookup below is not
// restricted to that QName
myContextQName = null;
}
}
if (!indexFound && (myContextQName == null)) {
// we need to check them all
if (iflags.hasIndexOnQNames) {
indexScan = true;
}
// else use range index defined on path by default
}
} else {
return (nodeSetCompare(nodes, contextSequence));
}
// Get the documents from the node set
final DocumentSet docs = nodes.getDocumentSet();
// Holds the result
NodeSet result = null;
// Iterate through the right hand sequence
for (final SequenceIterator itRightSeq = Atomize.atomize(rightSeq).iterate(); itRightSeq.hasNext(); ) {
// Get the index key
Item key = itRightSeq.nextItem();
// if key has truncation, convert it to string
if (truncation != StringTruncationOperator.NONE) {
if (!Type.subTypeOf(key.getType(), Type.STRING)) {
LOG.info("Truncated key. Converted from {} to xs:string", Type.getTypeName(key.getType()));
// truncation is only possible on strings
key = key.convertTo(Type.STRING);
}
} else // TODO : use Type.isSubType() ??? -pb
if (key.getType() != indexType) {
// try to convert the key to the index type
try {
key = key.convertTo(indexType);
} catch (final XPathException xpe) {
// Could not convert the key to a suitable type for the index, fallback to nodeSetCompare()
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (" + xpe.getMessage() + ")");
}
if (LOG.isTraceEnabled()) {
LOG.trace("Cannot convert key: {} to required index type: {}", Type.getTypeName(key.getType()), Type.getTypeName(indexType));
}
return (nodeSetCompare(nodes, contextSequence));
}
}
// If key implements org.exist.storage.Indexable, we can use the index
if (key instanceof Indexable) {
if (LOG.isTraceEnabled()) {
LOG.trace("Checking if range index can be used for key: {}", key.getStringValue());
}
final Collator collator = ((collationArg != null) ? getCollator(contextSequence) : null);
if (Type.subTypeOf(key.getType(), indexType)) {
if (truncation == StringTruncationOperator.NONE) {
if (LOG.isTraceEnabled()) {
LOG.trace("Using range index for key: {}", key.getStringValue());
}
// key without truncation, find key
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() + "' to find key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
NodeSet ns;
if (indexScan) {
ns = context.getBroker().getValueIndex().findAll(context.getWatchDog(), relation, docs, nodes, NodeSet.ANCESTOR, (Indexable) key);
} else {
ns = context.getBroker().getValueIndex().find(context.getWatchDog(), relation, docs, nodes, NodeSet.ANCESTOR, myContextQName, (Indexable) key, indexMixed);
}
hasUsedIndex = true;
if (result == null) {
result = ns;
} else {
result = result.union(ns);
}
} else {
// key with truncation, match key
if (LOG.isTraceEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() + "' to match key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
}
if (LOG.isTraceEnabled()) {
LOG.trace("Using range index for key: {}", key.getStringValue());
}
try {
NodeSet ns;
final String matchString = key.getStringValue();
final int matchType = getMatchType(truncation);
if (indexScan) {
ns = context.getBroker().getValueIndex().matchAll(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, matchString, matchType, 0, true, collator, truncation);
} else {
ns = context.getBroker().getValueIndex().match(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, matchString, myContextQName, matchType, collator, truncation);
}
hasUsedIndex = true;
if (result == null) {
result = ns;
} else {
result = result.union(ns);
}
} catch (final EXistException e) {
throw (new XPathException(this, e));
}
}
} else {
// our key does is not of the correct type
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is of type: " + Type.getTypeName(key.getType()) + ") whereas index is of type '" + Type.getTypeName(indexType) + "'");
}
if (LOG.isTraceEnabled()) {
LOG.trace("Cannot use range index: key is of type: {}) whereas index is of type '{}", Type.getTypeName(key.getType()), Type.getTypeName(indexType));
}
return (nodeSetCompare(nodes, contextSequence));
}
} else {
// our key does not implement org.exist.storage.Indexable
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is not an indexable type: " + key.getClass().getName());
}
if (LOG.isTraceEnabled()) {
LOG.trace("Cannot use key which is of type '{}", key.getClass().getName());
}
return (nodeSetCompare(nodes, contextSequence));
}
}
if (context.getProfiler().traceFunctions()) {
context.getProfiler().traceIndexUsage(context, PerformanceStats.RANGE_IDX_TYPE, this, PerformanceStats.BASIC_INDEX, System.currentTimeMillis() - start);
}
return (result);
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("No suitable index found for key: {}", rightSeq.getStringValue());
}
// no range index defined on the nodes in this sequence, so fallback to nodeSetCompare
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "falling back to nodeSetCompare (no index available)");
}
return (nodeSetCompare(nodes, contextSequence));
}
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class DynamicCommentConstructor 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());
}
}
if (newDocumentContext) {
context.pushDocumentContext();
}
Sequence result;
try {
final Sequence contentSeq = content.eval(contextSequence, contextItem);
if (contentSeq.isEmpty()) {
result = Sequence.EMPTY_SEQUENCE;
} else {
final MemTreeBuilder builder = context.getDocumentBuilder();
context.proceed(this, builder);
final StringBuilder buf = new StringBuilder();
for (final SequenceIterator i = Atomize.atomize(contentSeq).iterate(); i.hasNext(); ) {
context.proceed(this, builder);
final Item next = i.nextItem();
if (buf.length() > 0) {
buf.append(' ');
}
buf.append(next.toString());
}
if (buf.indexOf("--") != Constants.STRING_NOT_FOUND || buf.toString().endsWith("-")) {
throw new XPathException(this, ErrorCodes.XQDY0072, "'" + buf.toString() + "' is not a valid comment");
}
final int nodeNr = builder.comment(buf.toString());
result = builder.getDocument().getNode(nodeNr);
}
} finally {
if (newDocumentContext) {
context.popDocumentContext();
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
Aggregations