use of org.exist.dom.memtree.ElementImpl in project exist by eXist-db.
the class RESTServer method doGet.
/**
* Handle GET request. In the simplest case just returns the document or
* binary resource specified in the path. If the path leads to a collection,
* a listing of the collection contents is returned. If it resolves to a
* binary resource with mime-type "application/xquery", this resource will
* be loaded and executed by the XQuery engine.
*
* The method also recognizes a number of predefined parameters:
*
* <ul> <li>_xpath or _query: if specified, the given query is executed on
* the current resource or collection.</li>
*
* <li>_howmany: defines how many items from the query result will be
* returned.</li>
*
* <li>_start: a start offset into the result set.</li>
*
* <li>_wrap: if set to "yes", the query results will be wrapped into a
* exist:result element.</li>
*
* <li>_indent: if set to "yes", the returned XML will be pretty-printed.
* </li>
*
* <li>_source: if set to "yes" and a resource with mime-type
* "application/xquery" is requested then the xquery will not be executed,
* instead the source of the document will be returned. Must be enabled in
* descriptor.xml with the following syntax
* <pre>{@code
* <xquery-app>
* <allow-source>
* <xquery path="/db/mycollection/myquery.xql"/>
* </allow-source>
* </xquery-app>
* }</pre>
* </li>
*
* <li>_xsl: an URI pointing to an XSL stylesheet that will be applied to
* the returned XML.</li>
* </ul>
*
* @param broker the database broker
* @param transaction the database transaction
* @param request the request
* @param response the response
* @param path the path of the request
*
* @throws BadRequestException if a bad request is made
* @throws PermissionDeniedException if the request has insufficient permissions
* @throws NotFoundException if the request resource cannot be found
* @throws IOException if an I/O error occurs
*/
public void doGet(final DBBroker broker, final Txn transaction, final HttpServletRequest request, final HttpServletResponse response, final String path) throws BadRequestException, PermissionDeniedException, NotFoundException, IOException {
// if required, set character encoding
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding(formEncoding);
}
String option;
if ((option = getParameter(request, Release)) != null) {
final int sessionId = Integer.parseInt(option);
sessionManager.release(sessionId);
if (LOG.isDebugEnabled()) {
LOG.debug("Released session {}", sessionId);
}
response.setStatus(HttpServletResponse.SC_OK);
return;
}
// Process special parameters
int howmany = 10;
int start = 1;
boolean typed = false;
boolean wrap = true;
boolean source = false;
boolean cache = false;
final Properties outputProperties = new Properties(defaultOutputKeysProperties);
String query = null;
if (!safeMode) {
query = getParameter(request, XPath);
if (query == null) {
query = getParameter(request, Query);
}
}
final String _var = getParameter(request, Variables);
List /*<Namespace>*/
namespaces = null;
ElementImpl variables = null;
try {
if (_var != null) {
final NamespaceExtractor nsExtractor = new NamespaceExtractor();
variables = parseXML(broker.getBrokerPool(), _var, nsExtractor);
namespaces = nsExtractor.getNamespaces();
}
} catch (final SAXException e) {
final XPathException x = new XPathException(e.toString());
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, "UTF-8", query, path, x);
}
if ((option = getParameter(request, HowMany)) != null) {
try {
howmany = Integer.parseInt(option);
} catch (final NumberFormatException nfe) {
throw new BadRequestException("Parameter _howmany should be an int");
}
}
if ((option = getParameter(request, Start)) != null) {
try {
start = Integer.parseInt(option);
} catch (final NumberFormatException nfe) {
throw new BadRequestException("Parameter _start should be an int");
}
}
if ((option = getParameter(request, Typed)) != null) {
if ("yes".equals(option.toLowerCase())) {
typed = true;
}
}
if ((option = getParameter(request, Wrap)) != null) {
wrap = "yes".equals(option);
outputProperties.setProperty("_wrap", option);
}
if ((option = getParameter(request, Cache)) != null) {
cache = "yes".equals(option);
}
if ((option = getParameter(request, Indent)) != null) {
outputProperties.setProperty(OutputKeys.INDENT, option);
}
if ((option = getParameter(request, Source)) != null && !safeMode) {
source = "yes".equals(option);
}
if ((option = getParameter(request, Session)) != null) {
outputProperties.setProperty(Serializer.PROPERTY_SESSION_ID, option);
}
String stylesheet;
if ((stylesheet = getParameter(request, XSL)) != null) {
if ("no".equals(stylesheet)) {
outputProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "no");
outputProperties.remove(EXistOutputKeys.STYLESHEET);
stylesheet = null;
} else {
outputProperties.setProperty(EXistOutputKeys.STYLESHEET, stylesheet);
}
} else {
outputProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "yes");
}
LOG.debug("stylesheet = {}", stylesheet);
LOG.debug("query = {}", query);
String encoding;
if ((encoding = getParameter(request, Encoding)) != null) {
outputProperties.setProperty(OutputKeys.ENCODING, encoding);
} else {
encoding = "UTF-8";
}
final String mimeType = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
if (query != null) {
// query parameter specified, search method does all the rest of the work
try {
search(broker, transaction, query, path, namespaces, variables, howmany, start, typed, outputProperties, wrap, cache, request, response);
} catch (final XPathException e) {
if (MimeType.XML_TYPE.getName().equals(mimeType)) {
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
} else {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
}
}
return;
}
// Process the request
LockedDocument lockedDocument = null;
DocumentImpl resource = null;
final XmldbURI pathUri = XmldbURI.createInternal(path);
try {
// check if path leads to an XQuery resource
final String xquery_mime_type = MimeType.XQUERY_TYPE.getName();
final String xproc_mime_type = MimeType.XPROC_TYPE.getName();
lockedDocument = broker.getXMLResource(pathUri, LockMode.READ_LOCK);
resource = lockedDocument == null ? null : lockedDocument.getDocument();
if (null != resource && !isExecutableType(resource)) {
// return regular resource that is not an xquery and not is xproc
writeResourceAs(resource, broker, transaction, stylesheet, encoding, null, outputProperties, request, response);
return;
}
if (resource == null) {
// no document: check if path points to a collection
try (final Collection collection = broker.openCollection(pathUri, LockMode.READ_LOCK)) {
if (collection != null) {
if (safeMode || !collection.getPermissionsNoLock().validate(broker.getCurrentSubject(), Permission.READ)) {
throw new PermissionDeniedException("Not allowed to read collection");
}
// return a listing of the collection contents
try {
writeCollection(response, encoding, broker, collection);
return;
} catch (final LockException le) {
if (MimeType.XML_TYPE.getName().equals(mimeType)) {
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, new XPathException(le.getMessage(), le));
} else {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, new XPathException(le.getMessage(), le));
}
}
} else if (source) {
// on a possible xquery resource that was not found
throw new NotFoundException("Document " + path + " not found");
}
}
}
XmldbURI servletPath = pathUri;
// xquery or xproc resource
while (null == resource) {
// traverse up the path looking for xquery objects
servletPath = servletPath.removeLastSegment();
if (servletPath == XmldbURI.EMPTY_URI) {
break;
}
lockedDocument = broker.getXMLResource(servletPath, LockMode.READ_LOCK);
resource = lockedDocument == null ? null : lockedDocument.getDocument();
if (null != resource && isExecutableType(resource)) {
break;
} else if (null != resource) {
// moving up the path, so bail out now
throw new NotFoundException("Document " + path + " not found");
}
}
if (null == resource) {
// path search failed
throw new NotFoundException("Document " + path + " not found");
}
// found an XQuery or XProc resource, fixup request values
final String pathInfo = pathUri.trimFromBeginning(servletPath).toString();
// Should we display the source of the XQuery or XProc or execute it
final Descriptor descriptor = Descriptor.getDescriptorSingleton();
if (source) {
// descriptor.xml
if ((null != descriptor) && descriptor.allowSource(path) && resource.getPermissions().validate(broker.getCurrentSubject(), Permission.READ)) {
if (xquery_mime_type.equals(resource.getMimeType())) {
// Show the source of the XQuery
writeResourceAs(resource, broker, transaction, stylesheet, encoding, MimeType.TEXT_TYPE.getName(), outputProperties, request, response);
} else if (xproc_mime_type.equals(resource.getMimeType())) {
// Show the source of the XProc
writeResourceAs(resource, broker, transaction, stylesheet, encoding, MimeType.XML_TYPE.getName(), outputProperties, request, response);
}
} else {
// we are not allowed to show the source - query not
// allowed in descriptor.xml
// or descriptor not found, so assume source view not
// allowed
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission to view XQuery source for: " + path + " denied. Must be explicitly defined in descriptor.xml");
return;
}
} else {
try {
if (xquery_mime_type.equals(resource.getMimeType())) {
// Execute the XQuery
executeXQuery(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
} else if (xproc_mime_type.equals(resource.getMimeType())) {
// Execute the XProc
executeXProc(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
}
} catch (final XPathException e) {
if (LOG.isDebugEnabled()) {
LOG.debug(e.getMessage(), e);
}
if (MimeType.XML_TYPE.getName().equals(mimeType)) {
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
} else {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
}
}
}
} finally {
if (lockedDocument != null) {
lockedDocument.close();
}
}
}
Aggregations