Search in sources :

Example 1 with RestXqService

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);
        }
    }
}
Also used : RestXqService(org.exquery.restxq.RestXqService) ExQueryException(org.exquery.ExQueryException) TriggerException(org.exist.collections.triggers.TriggerException)

Example 2 with RestXqService

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;
}
Also used : AnnotationAdapter(org.exist.extensions.exquery.restxq.impl.adapters.AnnotationAdapter) UserDefinedFunction(org.exist.xquery.UserDefinedFunction) ExQueryException(org.exquery.ExQueryException) ArrayList(java.util.ArrayList) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) Annotation(org.exist.xquery.Annotation) RestXqService(org.exquery.restxq.RestXqService) ResourceFunction(org.exquery.restxq.ResourceFunction) AnnotationException(org.exquery.annotation.AnnotationException) HashSet(java.util.HashSet)

Example 3 with RestXqService

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);
        }
    }
}
Also used : HttpRequest(org.exquery.http.HttpRequest) HttpServletResponseAdapter(org.exist.extensions.exquery.restxq.impl.adapters.HttpServletResponseAdapter) RestXqServiceException(org.exquery.restxq.RestXqServiceException) Configuration(org.exist.util.Configuration) EXistException(org.exist.EXistException) Subject(org.exist.security.Subject) ServletException(javax.servlet.ServletException) RestXqService(org.exquery.restxq.RestXqService) DBBroker(org.exist.storage.DBBroker) HttpServletRequestAdapter(org.exist.extensions.exquery.restxq.impl.adapters.HttpServletRequestAdapter) PermissionDeniedException(org.exist.security.PermissionDeniedException)

Example 4 with RestXqService

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.");
}
Also used : RestXqService(org.exquery.restxq.RestXqService) DBBroker(org.exist.storage.DBBroker) ExQueryException(org.exquery.ExQueryException) CompiledXQuery(org.exist.xquery.CompiledXQuery) IOException(java.io.IOException) EXistException(org.exist.EXistException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) LineNumberReader(java.io.LineNumberReader)

Example 5 with RestXqService

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);
        }
    }
}
Also used : Path(java.nio.file.Path) IOException(java.io.IOException) URI(java.net.URI) FunctionSignature(org.exquery.xquery3.FunctionSignature) RestXqService(org.exquery.restxq.RestXqService) PrintWriter(java.io.PrintWriter)

Aggregations

RestXqService (org.exquery.restxq.RestXqService)9 ExQueryException (org.exquery.ExQueryException)5 URI (java.net.URI)3 PermissionDeniedException (org.exist.security.PermissionDeniedException)3 IOException (java.io.IOException)2 URISyntaxException (java.net.URISyntaxException)2 EXistException (org.exist.EXistException)2 DocumentImpl (org.exist.dom.persistent.DocumentImpl)2 DBBroker (org.exist.storage.DBBroker)2 ResourceFunction (org.exquery.restxq.ResourceFunction)2 LineNumberReader (java.io.LineNumberReader)1 PrintWriter (java.io.PrintWriter)1 Path (java.nio.file.Path)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 ServletException (javax.servlet.ServletException)1 TriggerException (org.exist.collections.triggers.TriggerException)1 ExistXqueryRegistry (org.exist.extensions.exquery.restxq.impl.ExistXqueryRegistry)1 AnnotationAdapter (org.exist.extensions.exquery.restxq.impl.adapters.AnnotationAdapter)1 HttpServletRequestAdapter (org.exist.extensions.exquery.restxq.impl.adapters.HttpServletRequestAdapter)1