use of org.exquery.restxq.RestXqService in project exist by eXist-db.
the class RestXqTrigger method after.
private void after(final DBBroker broker, final DocumentImpl document) throws TriggerException {
final ExistXqueryRegistry xqueryRegistry = ExistXqueryRegistry.getInstance();
if (xqueryRegistry.isXquery(document)) {
try {
final List<RestXqService> services = xqueryRegistry.findServices(broker, document);
xqueryRegistry.registerServices(broker, services);
} catch (final ExQueryException eqe) {
throw new TriggerException(eqe.getMessage(), eqe);
}
}
}
use of org.exquery.restxq.RestXqService in project exist by eXist-db.
the class XQueryInspector method findServices.
public static List<RestXqService> findServices(final CompiledXQuery compiled) throws ExQueryException {
final List<RestXqService> services = new ArrayList<>();
try {
// look at each function
final Iterator<UserDefinedFunction> itFunctions = compiled.getContext().localFunctions();
final Set<URI> xqueryLocations = new HashSet<>();
while (itFunctions.hasNext()) {
final UserDefinedFunction function = itFunctions.next();
final Annotation[] annotations = function.getSignature().getAnnotations();
Set<org.exquery.xquery3.Annotation> functionRestAnnotations = null;
// process the function annotations
for (final Annotation annotation : annotations) {
if (RestAnnotationFactory.isRestXqAnnotation(annotation.getName().toJavaQName())) {
final org.exquery.xquery3.Annotation restAnnotation = RestAnnotationFactory.getAnnotation(new AnnotationAdapter(annotation));
if (functionRestAnnotations == null) {
functionRestAnnotations = new HashSet<>();
}
functionRestAnnotations.add(restAnnotation);
}
}
if (functionRestAnnotations != null) {
final ResourceFunction resourceFunction = ResourceFunctionFactory.create(new URI(compiled.getSource().path()), functionRestAnnotations);
final RestXqService service = new RestXqServiceImpl(resourceFunction, compiled.getContext().getBroker().getBrokerPool());
// record the xquerylocation
xqueryLocations.add(resourceFunction.getXQueryLocation());
// add the service to the list of services for this query
services.add(service);
}
}
for (final URI xqueryLocation : xqueryLocations) {
// add service location and compiled query to the cache
RestXqServiceCompiledXQueryCacheImpl.getInstance().returnCompiledQuery(xqueryLocation, compiled);
}
} catch (final URISyntaxException | AnnotationException use) {
throw new ExQueryException(use.getMessage(), use);
}
return services;
}
use of org.exquery.restxq.RestXqService in project exist by eXist-db.
the class RestXqServlet method service.
@Override
protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
// authenticate
final Subject user = authenticate(request, response);
if (user == null) {
// "Permission denied: unknown user or password");
return;
}
try (final DBBroker broker = getPool().get(Optional.of(user))) {
final Configuration configuration = broker.getConfiguration();
final HttpRequest requestAdapter = new HttpServletRequestAdapter(request, () -> (String) configuration.getProperty(Configuration.BINARY_CACHE_CLASS_PROPERTY));
final RestXqService service = getRegistry().findService(requestAdapter);
if (service != null) {
if (log.isTraceEnabled()) {
log.trace("Received {} request for \"{}\" and found Resource Function \"{}\" in module \"{}\"", requestAdapter.getMethod().name(), requestAdapter.getPath(), service.getResourceFunction().getFunctionSignature(), service.getResourceFunction().getXQueryLocation());
}
service.service(requestAdapter, new HttpServletResponseAdapter(response), new ResourceFunctionExecutorImpl(getPool(), request.getContextPath() + request.getServletPath(), request.getRequestURI()), new RestXqServiceSerializerImpl(getPool()));
} else {
if (log.isTraceEnabled()) {
log.trace("Received {} request for \"{}\" but no suitable Resource Function found!", requestAdapter.getMethod().name(), requestAdapter.getPath());
}
super.service(request, response);
}
} catch (final EXistException e) {
getLog().error(e.getMessage(), e);
throw new ServletException(e.getMessage(), e);
} catch (final RestXqServiceException e) {
if (e.getCause() instanceof PermissionDeniedException) {
getAuthenticator().sendChallenge(request, response);
} else {
// TODO should probably be caught higher up and returned as a HTTP Response? maybe need two different types of exception to differentiate critical vs processing exception
getLog().error(e.getMessage(), e);
throw new ServletException(e.getMessage(), e);
}
}
}
use of org.exquery.restxq.RestXqService in project exist by eXist-db.
the class RestXqServiceRegistryPersistence method loadRegistry.
private void loadRegistry(final Path fRegistry) {
log.info("Loading RESTXQ registry from: {}", fRegistry.toAbsolutePath().toString());
try (final LineNumberReader reader = new LineNumberReader(Files.newBufferedReader(fRegistry));
final DBBroker broker = getBrokerPool().getBroker()) {
// read version line first
String line = reader.readLine();
final String versionStr = line.substring(line.indexOf(VERSION_LABEL) + VERSION_LABEL.length() + LABEL_SEP.length());
if (REGISTRY_FILE_VERSION != Integer.parseInt(versionStr)) {
log.error("Unable to load RESTXQ registry file: {}. Expected version: " + REGISTRY_FILE_VERSION + " but saw version: {}", fRegistry.toAbsolutePath().toString(), versionStr);
} else {
while ((line = reader.readLine()) != null) {
final String xqueryLocation = line.substring(0, line.indexOf(FIELD_SEP));
final CompiledXQuery xquery = XQueryCompiler.compile(broker, new URI(xqueryLocation));
final List<RestXqService> services = XQueryInspector.findServices(xquery);
getRegistry().register(services);
}
}
} catch (final ExQueryException | IOException | EXistException | URISyntaxException eqe) {
log.error(eqe.getMessage(), eqe);
}
log.info("RESTXQ registry loaded.");
}
use of org.exquery.restxq.RestXqService in project exist by eXist-db.
the class RestXqServiceRegistryPersistence method updateRegistryOnDisk.
private synchronized void updateRegistryOnDisk(final RestXqService restXqService, final UpdateAction updateAction) {
// we can ignore the change in service provided to this function as args, as we just write the details of all
// services to disk, overwriting the old registry
final Optional<Path> optTmpNewRegistry = getRegistryFile(true);
if (!optTmpNewRegistry.isPresent()) {
log.error("Could not save RESTXQ Registry to disk!");
} else {
final Path tmpNewRegistry = optTmpNewRegistry.get();
log.info("Preparing new RESTXQ registry on disk: {}", tmpNewRegistry.toAbsolutePath().toString());
try {
try (final PrintWriter writer = new PrintWriter(Files.newBufferedWriter(tmpNewRegistry, StandardOpenOption.TRUNCATE_EXISTING))) {
writer.println(VERSION_LABEL + LABEL_SEP + REGISTRY_FILE_VERSION);
// get details of RESTXQ functions in XQuery modules
final Map<URI, List<FunctionSignature>> xqueryServices = new HashMap<>();
for (final RestXqService service : getRegistry()) {
List<FunctionSignature> fnNames = xqueryServices.get(service.getResourceFunction().getXQueryLocation());
if (fnNames == null) {
fnNames = new ArrayList<>();
}
fnNames.add(service.getResourceFunction().getFunctionSignature());
xqueryServices.put(service.getResourceFunction().getXQueryLocation(), fnNames);
}
// iterate and save to disk
for (final Entry<URI, List<FunctionSignature>> xqueryServiceFunctions : xqueryServices.entrySet()) {
writer.print(xqueryServiceFunctions.getKey() + FIELD_SEP);
final List<FunctionSignature> fnSigs = xqueryServiceFunctions.getValue();
for (final FunctionSignature fnSig : fnSigs) {
writer.print(qnameToClarkNotation(fnSig.getName()) + ARITY_SEP + fnSig.getArgumentCount());
}
writer.println();
}
}
final Optional<Path> optRegistry = getRegistryFile(false);
if (optRegistry.isPresent()) {
final Path registry = optRegistry.get();
// replace the original registry with the new registry
final Path localTmpNewRegistry = Files.copy(tmpNewRegistry, registry.getParent().resolve(tmpNewRegistry.getFileName()));
Files.move(localTmpNewRegistry, registry, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
log.info("Replaced RESTXQ registry: {} -> {}", FileUtils.fileName(tmpNewRegistry), FileUtils.fileName(registry));
} else {
throw new IOException("Unable to retrieve existing RESTXQ registry");
}
} catch (final IOException ioe) {
log.error(ioe.getMessage(), ioe);
} finally {
TemporaryFileManager.getInstance().returnTemporaryFile(tmpNewRegistry);
}
}
}
Aggregations