package org.basex.http.restxq;
import static org.basex.http.HTTPText.*;
import static org.basex.http.restxq.RestXqText.*;
import javax.servlet.http.*;
import org.basex.http.*;
import org.basex.query.*;
import org.basex.query.value.item.*;
import org.basex.util.*;
/**
* <p>This servlet receives and processes REST requests.
* The evaluated code is defined in XQuery modules, which are located in the web server's
* root directory (specified by the {@code HTTPPATH} option), and decorated with RESTXQ
* annotations.</p>
*
* <p>The implementation is based on Adam Retter's paper presented at XMLPrague 2012,
* titled "RESTful XQuery - Standardised XQuery 3.0 Annotations for REST".</p>
*
* @author BaseX Team 2005-17, BSD License
* @author Christian Gruen
*/
public final class RestXqServlet extends BaseXServlet {
@Override
protected void run(final HTTPConnection conn) throws Exception {
// no trailing slash: send redirect
if(conn.req.getPathInfo() == null) {
conn.redirect("/");
return;
}
// analyze input path
final RestXqModules rxm = RestXqModules.get(conn.context);
// initialize RESTXQ
if(conn.path().equals('/' + INIT)) {
rxm.init();
return;
}
// select function that closest matches the request
RestXqFunction func = rxm.find(conn, null);
if(func == null) throw HTTPCode.NO_XQUERY.get();
try {
// process function
func.process(conn, null);
} catch(final QueryException ex) {
// run optional error function
func = rxm.find(conn, ex.qname());
if(func == null) throw ex;
func.process(conn, ex);
}
}
@Override
public String username(final HTTPConnection http) {
// try to retrieve session id (DBA, global one)
final HttpSession session = http.req.getSession(false);
byte[] value = null;
if(session != null) {
value = token(session.getAttribute("id"));
if((http.path() + '/').contains('/' + DBA + '/')) value = token(session.getAttribute(DBA));
}
return value != null ? Token.string(Token.normalize(value)) : super.username(http);
}
/**
* Converts the specified session value to a string.
* @param value value
* @return return string, or {@code null}
*/
private static byte[] token(final Object value) {
if(value instanceof Str) return ((Str) value).string();
if(value instanceof Atm) return ((Atm) value).string(null);
return null;
}
}