use of org.exist.xquery.value.NodeValue in project exist by eXist-db.
the class XQueryURLRewrite method service.
@Override
protected void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
if (rewriteConfig == null) {
configure();
rewriteConfig = new RewriteConfig(this);
}
final long start = System.currentTimeMillis();
if (LOG.isTraceEnabled()) {
LOG.trace(request.getRequestURI());
}
final Descriptor descriptor = Descriptor.getDescriptorSingleton();
if (descriptor != null && descriptor.requestsFiltered()) {
final String attr = (String) request.getAttribute("XQueryURLRewrite.forwarded");
if (attr == null) {
// logs the request if specified in the descriptor
descriptor.doLogRequestInReplayLog(request);
request.setAttribute("XQueryURLRewrite.forwarded", "true");
}
}
Subject user = defaultUser;
Subject requestUser = HttpAccount.getUserFromServletRequest(request);
if (requestUser != null) {
user = requestUser;
} else {
// Secondly try basic authentication
final String auth = request.getHeader("Authorization");
if (auth != null) {
requestUser = authenticator.authenticate(request, response, sendChallenge);
if (requestUser != null) {
user = requestUser;
}
}
}
try {
configure();
// checkCache(user);
final RequestWrapper modifiedRequest = new RequestWrapper(request);
final URLRewrite staticRewrite = rewriteConfig.lookup(modifiedRequest);
if (staticRewrite != null && !staticRewrite.isControllerForward()) {
modifiedRequest.setPaths(staticRewrite.resolve(modifiedRequest), staticRewrite.getPrefix());
if (LOG.isTraceEnabled()) {
LOG.trace("Forwarding to target: {}", staticRewrite.getTarget());
}
staticRewrite.doRewrite(modifiedRequest, response);
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("Processing request URI: {}", request.getRequestURI());
}
if (staticRewrite != null) {
// fix the request URI
staticRewrite.updateRequest(modifiedRequest);
}
// check if the request URI is already in the url cache
ModelAndView modelView = getFromCache(request.getHeader("Host") + request.getRequestURI(), user);
if (LOG.isDebugEnabled()) {
LOG.debug("Checked cache for URI: {} original: {}", modifiedRequest.getRequestURI(), request.getRequestURI());
}
// no: create a new model and view configuration
if (modelView == null) {
modelView = new ModelAndView();
// Execute the query
try (final DBBroker broker = pool.get(Optional.ofNullable(user))) {
modifiedRequest.setAttribute(RQ_ATTR_REQUEST_URI, request.getRequestURI());
final Properties outputProperties = new Properties();
outputProperties.setProperty(OutputKeys.INDENT, "yes");
outputProperties.setProperty(OutputKeys.ENCODING, "UTF-8");
outputProperties.setProperty(OutputKeys.MEDIA_TYPE, MimeType.XML_TYPE.getName());
final Sequence result = runQuery(broker, modifiedRequest, response, modelView, staticRewrite, outputProperties);
logResult(broker, result);
if (response.isCommitted()) {
return;
}
// process the query result
if (result.getItemCount() == 1) {
final Item resource = result.itemAt(0);
if (!Type.subTypeOf(resource.getType(), Type.NODE)) {
throw new ServletException("XQueryURLRewrite: urlrewrite query should return an element!");
}
Node node = ((NodeValue) resource).getNode();
if (node.getNodeType() == Node.DOCUMENT_NODE) {
node = ((Document) node).getDocumentElement();
}
if (node.getNodeType() != Node.ELEMENT_NODE) {
// throw new ServletException("Redirect XQuery should return an XML element!");
response(broker, response, outputProperties, result);
return;
}
Element elem = (Element) node;
final String ns = elem.getNamespaceURI();
if (!Namespaces.EXIST_NS.equals(ns)) {
response(broker, response, outputProperties, result);
return;
}
final String nsUri = elem.getNamespaceURI();
if (Namespaces.EXIST_NS.equals(nsUri) && "dispatch".equals(elem.getLocalName())) {
node = elem.getFirstChild();
while (node != null) {
final String nodeNs = node.getNamespaceURI();
if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(nodeNs)) {
final Element action = (Element) node;
if ("view".equals(action.getLocalName())) {
parseViews(modifiedRequest, action, modelView);
} else if ("error-handler".equals(action.getLocalName())) {
parseErrorHandlers(modifiedRequest, action, modelView);
} else if ("cache-control".equals(action.getLocalName())) {
final String option = action.getAttribute("cache");
modelView.setUseCache("yes".equals(option));
} else {
final URLRewrite urw = parseAction(modifiedRequest, action);
if (urw != null) {
modelView.setModel(urw);
}
}
}
node = node.getNextSibling();
}
if (modelView.getModel() == null) {
modelView.setModel(new PassThrough(config, elem, modifiedRequest));
}
} else if (nsUri != null && Namespaces.EXIST_NS.equals(elem.getNamespaceURI()) && "ignore".equals(elem.getLocalName())) {
modelView.setModel(new PassThrough(config, elem, modifiedRequest));
final NodeList nl = elem.getElementsByTagNameNS(Namespaces.EXIST_NS, "cache-control");
if (nl.getLength() > 0) {
elem = (Element) nl.item(0);
final String option = elem.getAttribute("cache");
modelView.setUseCache("yes".equals(option));
}
} else {
response(broker, response, outputProperties, result);
return;
}
} else if (result.getItemCount() > 1) {
response(broker, response, outputProperties, result);
return;
}
if (modelView.useCache()) {
LOG.debug("Caching request to {}", request.getRequestURI());
urlCache.put(modifiedRequest.getHeader("Host") + request.getRequestURI(), modelView);
}
}
// store the original request URI to org.exist.forward.request-uri
modifiedRequest.setAttribute(RQ_ATTR_REQUEST_URI, request.getRequestURI());
modifiedRequest.setAttribute(RQ_ATTR_SERVLET_PATH, request.getServletPath());
}
if (LOG.isTraceEnabled()) {
LOG.trace("URLRewrite took {}ms.", System.currentTimeMillis() - start);
}
final HttpServletResponse wrappedResponse = new CachingResponseWrapper(response, modelView.hasViews() || modelView.hasErrorHandlers());
if (modelView.getModel() == null) {
modelView.setModel(new PassThrough(config, modifiedRequest));
}
if (staticRewrite != null) {
if (modelView.getModel().doResolve()) {
staticRewrite.rewriteRequest(modifiedRequest);
} else {
modelView.getModel().setAbsolutePath(modifiedRequest);
}
}
modifiedRequest.allowCaching(!modelView.hasViews());
doRewrite(modelView.getModel(), modifiedRequest, wrappedResponse);
final int status = wrappedResponse.getStatus();
if (status == HttpServletResponse.SC_NOT_MODIFIED) {
response.flushBuffer();
} else if (status < HttpServletResponse.SC_BAD_REQUEST) {
if (modelView.hasViews()) {
applyViews(modelView, modelView.views, response, modifiedRequest, wrappedResponse);
} else {
((CachingResponseWrapper) wrappedResponse).flush();
}
} else {
// HTTP response code indicates an error
if (modelView.hasErrorHandlers()) {
final byte[] data = ((CachingResponseWrapper) wrappedResponse).getData();
if (data != null) {
modifiedRequest.setAttribute(RQ_ATTR_ERROR, new String(data, UTF_8));
}
applyViews(modelView, modelView.errorHandlers, response, modifiedRequest, wrappedResponse);
} else {
flushError(response, wrappedResponse);
}
}
}
} catch (final Throwable e) {
LOG.error("Error while processing {}: {}", request.getRequestURI(), e.getMessage(), e);
throw new ServletException("An error occurred while processing request to " + request.getRequestURI() + ": " + e.getMessage(), e);
}
}
use of org.exist.xquery.value.NodeValue in project exist by eXist-db.
the class RenderFunction method eval.
/*
* Actual implementation of the rendering process. When a function in this
* module is called, this method is executed with the given inputs. @param
* Sequence[] args (XSL-FO, mime-type, parameters) @param Sequence
* contextSequence (default sequence)
*
* @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[],
* org.exist.xquery.value.Sequence)
*/
@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
// process
if (args[0].isEmpty()) {
return Sequence.EMPTY_SEQUENCE;
}
final Item inputNode = args[0].itemAt(0);
// get media-type
final String mediaType = args[1].getStringValue();
// get parameters
final Properties parameters;
if (!args[2].isEmpty()) {
parameters = ParametersExtractor.parseParameters(((NodeValue) args[2].itemAt(0)).getNode());
} else {
parameters = new Properties();
}
ProcessorAdapter adapter = null;
try (final UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) {
adapter = ((XSLFOModule) getParentModule()).getProcessorAdapter();
final NodeValue processorConfig = args.length == 4 ? (NodeValue) args[3].itemAt(0) : null;
final ContentHandler contentHandler = adapter.getContentHandler(context.getBroker(), processorConfig, parameters, mediaType, baos);
// process the XSL-FO
contentHandler.startDocument();
inputNode.toSAX(context.getBroker(), contentHandler, new Properties());
contentHandler.endDocument();
// return the result
return BinaryValueFromInputStream.getInstance(context, new Base64BinaryValueType(), new ByteArrayInputStream(baos.toByteArray()));
} catch (final IOException | SAXException se) {
throw new XPathException(this, se.getMessage(), se);
} finally {
if (adapter != null) {
adapter.cleanup();
}
}
}
use of org.exist.xquery.value.NodeValue in project exist by eXist-db.
the class ContentFunctions method eval.
@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
// is argument the empty sequence?
if (args[0].isEmpty()) {
return Sequence.EMPTY_SEQUENCE;
}
ContentExtraction ce = new ContentExtraction();
if (isCalledAs("stream-content")) {
/* binary content */
BinaryValue binary = (BinaryValue) args[0].itemAt(0);
/* callback function */
FunctionReference ref = (FunctionReference) args[2].itemAt(0);
Map<String, String> mappings = new HashMap<>();
if (args[3].hasOne()) {
NodeValue namespaces = (NodeValue) args[3].itemAt(0);
parseMappings(namespaces, mappings);
}
return streamContent(ce, binary, args[1], ref, mappings, args[4]);
} else {
try {
if (isCalledAs("get-metadata")) {
context.pushDocumentContext();
try {
final MemTreeBuilder builder = context.getDocumentBuilder();
builder.startDocument();
builder.startElement(new QName("html", XHTML_NS), null);
builder.startElement(new QName("head", XHTML_NS), null);
final QName qnMeta = new QName("meta", XHTML_NS);
final Metadata metadata = ce.extractMetadata((BinaryValue) args[0].itemAt(0));
for (final String name : metadata.names()) {
for (final String value : metadata.getValues(name)) {
final AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute("", "name", "name", "string", name);
attributes.addAttribute("", "content", "content", "string", value);
builder.startElement(qnMeta, attributes);
builder.endElement();
}
}
builder.endElement();
builder.endElement();
builder.endDocument();
return builder.getDocument();
} finally {
context.popDocumentContext();
}
} else {
final DocumentBuilderReceiver builder = new DocumentBuilderReceiver();
builder.setSuppressWhitespace(false);
final Metadata metadata = ce.extractContentAndMetadata((BinaryValue) args[0].itemAt(0), (ContentHandler) builder);
return (NodeValue) builder.getDocument();
}
} catch (IOException | SAXException | ContentExtractionException ex) {
LOG.error(ex.getMessage(), ex);
throw new XPathException(this, ex.getMessage(), ex);
}
}
}
use of org.exist.xquery.value.NodeValue in project exist by eXist-db.
the class Serializer method itemToSAX.
private void itemToSAX(final Item item, final boolean typed, final boolean wrap) throws SAXException {
if (Type.subTypeOf(item.getType(), Type.NODE)) {
final NodeValue node = (NodeValue) item;
if (typed) {
// TODO the typed and wrapped stuff should ideally be replaced
// with Marshaller.marshallItem
// unfortrunately calling Marshaller.marshallItem(broker, item, new SAXToReceiver(receiver))
// results in a stack overflow
// TODO consider a full XDM serializer in place of this for these special needs
serializeTypePreNode(node);
if (node.getType() == Type.ATTRIBUTE) {
serializeTypeAttributeValue(node);
} else {
serializeToReceiver(node, false);
}
serializeTypePostNode(node);
} else {
serializeToReceiver(node, false);
}
} else {
if (wrap) {
final AttrList attrs = new AttrList();
attrs.addAttribute(ATTR_TYPE_QNAME, Type.getTypeName(item.getType()));
receiver.startElement(ELEM_VALUE_QNAME, attrs);
}
try {
receiver.characters(item.getStringValue());
} catch (final XPathException e) {
throw new SAXException(e.getMessage(), e);
}
if (wrap) {
receiver.endElement(ELEM_VALUE_QNAME);
}
}
}
use of org.exist.xquery.value.NodeValue in project exist by eXist-db.
the class XIncludeFilter method processXInclude.
/**
* @param href The resource to be xincluded
* @param xpointer The xpointer
* @return Optionally a ResourceError if it was not possible to retrieve the resource
* to be xincluded
* @throws SAXException If a SAX processing error occurs
*/
protected Optional<ResourceError> processXInclude(final String href, String xpointer) throws SAXException {
if (href == null) {
throw new SAXException("No href attribute found in XInclude include element");
}
// save some settings
DocumentImpl prevDoc = document;
boolean createContainerElements = serializer.createContainerElements;
serializer.createContainerElements = false;
// The following comments are the basis for possible external documents
XmldbURI docUri = null;
try {
docUri = XmldbURI.xmldbUriFor(href);
/*
if(!stylesheetUri.toCollectionPathURI().equals(stylesheetUri)) {
externalUri = stylesheetUri.getXmldbURI();
}
*/
} catch (final URISyntaxException e) {
// could be an external URI!
}
// parse the href attribute
LOG.debug("found href=\"{}\"", href);
// String xpointer = null;
// String docName = href;
Map<String, String> params = null;
DocumentImpl doc = null;
org.exist.dom.memtree.DocumentImpl memtreeDoc = null;
boolean xqueryDoc = false;
if (docUri != null) {
final String fragment = docUri.getFragment();
if (!(fragment == null || fragment.length() == 0)) {
throw new SAXException("Fragment identifiers must not be used in an xinclude href attribute. To specify an xpointer, use the xpointer attribute.");
}
// extract possible parameters in the URI
params = null;
final String paramStr = docUri.getQuery();
if (paramStr != null) {
params = processParameters(paramStr);
// strip query part
docUri = XmldbURI.create(docUri.getRawCollectionPath());
}
// Patch 1520454 start
if (!docUri.isAbsolute() && document != null) {
final String base = document.getCollection().getURI() + "/";
final String child = "./" + docUri.toString();
final URI baseUri = URI.create(base);
final URI childUri = URI.create(child);
final URI uri = baseUri.resolve(childUri);
docUri = XmldbURI.create(uri);
}
// retrieve the document
try {
doc = serializer.broker.getResource(docUri, Permission.READ);
} catch (final PermissionDeniedException e) {
return Optional.of(new ResourceError("Permission denied to read XInclude'd resource", e));
}
/* Check if the document is a stored XQuery */
if (doc != null && doc.getResourceType() == DocumentImpl.BINARY_FILE) {
xqueryDoc = "application/xquery".equals(doc.getMimeType());
}
}
// The document could not be found: check if it points to an external resource
if (docUri == null || (doc == null && !docUri.isAbsolute())) {
try {
URI externalUri = new URI(href);
final String scheme = externalUri.getScheme();
// XQuery context.
if (scheme == null && moduleLoadPath != null) {
final String path = externalUri.getSchemeSpecificPart();
Path f = Paths.get(path);
if (!f.isAbsolute()) {
if (moduleLoadPath.startsWith(XmldbURI.XMLDB_URI_PREFIX)) {
final XmldbURI parentUri = XmldbURI.create(moduleLoadPath);
docUri = parentUri.append(path);
doc = (DocumentImpl) serializer.broker.getXMLResource(docUri);
if (doc != null && !doc.getPermissions().validate(serializer.broker.getCurrentSubject(), Permission.READ)) {
throw new PermissionDeniedException("Permission denied to read XInclude'd resource");
}
} else {
f = Paths.get(moduleLoadPath, path);
externalUri = f.toUri();
}
}
}
if (doc == null) {
final Either<ResourceError, org.exist.dom.memtree.DocumentImpl> external = parseExternal(externalUri);
if (external.isLeft()) {
return Optional.of(external.left().get());
} else {
memtreeDoc = external.right().get();
}
}
} catch (final PermissionDeniedException e) {
return Optional.of(new ResourceError("Permission denied on XInclude'd resource", e));
} catch (final ParserConfigurationException | URISyntaxException e) {
throw new SAXException("XInclude: failed to parse document at URI: " + href + ": " + e.getMessage(), e);
}
}
/* if document has not been found and xpointer is
* null, throw an exception. If xpointer != null
* we retry below and interpret docName as
* a collection.
*/
if (doc == null && memtreeDoc == null && xpointer == null) {
return Optional.of(new ResourceError("document " + docUri + " not found"));
}
if (xpointer == null && !xqueryDoc) {
// no xpointer found - just serialize the doc
if (memtreeDoc == null) {
serializer.serializeToReceiver(doc, false);
} else {
serializer.serializeToReceiver(memtreeDoc, false);
}
} else {
// process the xpointer or the stored XQuery
Source source = null;
final XQueryPool pool = serializer.broker.getBrokerPool().getXQueryPool();
CompiledXQuery compiled = null;
try {
if (xpointer == null) {
source = new DBSource(serializer.broker, (BinaryDocument) doc, true);
} else {
xpointer = checkNamespaces(xpointer);
source = new StringSource(xpointer);
}
final XQuery xquery = serializer.broker.getBrokerPool().getXQueryService();
XQueryContext context;
compiled = pool.borrowCompiledXQuery(serializer.broker, source);
if (compiled == null) {
context = new XQueryContext(serializer.broker.getBrokerPool());
} else {
context = compiled.getContext();
context.prepareForReuse();
}
context.declareNamespaces(namespaces);
context.declareNamespace("xinclude", Namespaces.XINCLUDE_NS);
// setup the http context if known
if (serializer.httpContext != null) {
context.setHttpContext(serializer.httpContext);
}
// TODO: change these to putting the XmldbURI in, but we need to warn users!
if (document != null) {
context.declareVariable("xinclude:current-doc", document.getFileURI().toString());
context.declareVariable("xinclude:current-collection", document.getCollection().getURI().toString());
}
if (xpointer != null) {
if (doc != null) {
context.setStaticallyKnownDocuments(new XmldbURI[] { doc.getURI() });
} else if (docUri != null) {
context.setStaticallyKnownDocuments(new XmldbURI[] { docUri });
}
}
// pass parameters as variables
if (params != null) {
for (final Map.Entry<String, String> entry : params.entrySet()) {
context.declareVariable(entry.getKey(), entry.getValue());
}
}
if (compiled == null) {
try {
compiled = xquery.compile(context, source, xpointer != null);
} catch (final IOException e) {
throw new SAXException("I/O error while reading query for xinclude: " + e.getMessage(), e);
}
} else {
compiled.getContext().updateContext(context);
context.getWatchDog().reset();
}
LOG.info("xpointer query: {}", ExpressionDumper.dump((Expression) compiled));
Sequence contextSeq = null;
if (memtreeDoc != null) {
contextSeq = memtreeDoc;
}
try {
final Sequence seq = xquery.execute(serializer.broker, compiled, contextSeq);
if (Type.subTypeOf(seq.getItemType(), Type.NODE)) {
if (LOG.isDebugEnabled()) {
LOG.debug("xpointer found: {}", seq.getItemCount());
}
NodeValue node;
for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) {
node = (NodeValue) i.nextItem();
serializer.serializeToReceiver(node, false);
}
} else {
String val;
for (int i = 0; i < seq.getItemCount(); i++) {
val = seq.itemAt(i).getStringValue();
characters(val);
}
}
} finally {
context.runCleanupTasks();
}
} catch (final XPathException | PermissionDeniedException e) {
LOG.warn("xpointer error", e);
throw new SAXException("Error while processing XInclude expression: " + e.getMessage(), e);
} finally {
if (compiled != null) {
pool.returnCompiledXQuery(source, compiled);
}
}
}
// restore settings
document = prevDoc;
serializer.createContainerElements = createContainerElements;
return Optional.empty();
}
Aggregations