All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.collaborationengine.SystemConnectionContext Maven / Gradle / Ivy

/*
 * Copyright 2020-2022 Vaadin Ltd.
 *
 * This program is available under Commercial Vaadin Runtime License 1.0
 * (CVRLv1).
 *
 * For the full License, see http://vaadin.com/license/cvrl-1
 */
package com.vaadin.collaborationengine;

import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

import com.vaadin.flow.internal.CurrentInstance;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.shared.Registration;

/**
 * A connection context that is always active. This context is intended to be
 * used in cases when Collaboration Engine is used in situations that aren't
 * directly associated with a UI, such as from a background thread or when
 * integrating with external services.
 * 

* An instance can be acquired using {@link #getInstance()} in any situation * where {@link CollaborationEngine#getInstance()} is available. Other * situations can use {@link CollaborationEngine#getSystemContext()} or create a * new context instance using the constructor. * * @author Vaadin Ltd */ public class SystemConnectionContext implements ConnectionContext { private final class ActionDispatcherImplementation implements ActionDispatcher { private final Executor executor; private final ExecutionQueue inbox = new ExecutionQueue(); private final CompletableFuture shutdownFuture = new CompletableFuture<>(); private boolean shuttingDown; private ActionDispatcherImplementation(Executor executor) { this.executor = executor; } @Override public void dispatchAction(Command action) { inbox.add(() -> { Map, CurrentInstance> oldInstances = CurrentInstance .getInstances(); try { VaadinService.setCurrent(ce.getVaadinService()); action.execute(); } finally { CurrentInstance.restoreInstances(oldInstances); } }); executor.execute(() -> { synchronized (this) { inbox.runPendingCommands(); if (shuttingDown) { shutdownFuture.complete(null); shuttingDown = false; } } }); } @Override public CompletableFuture createCompletableFuture() { return new CompletableFuture<>(); } synchronized private void shutdown() { if (inbox.isEmpty()) { shutdownFuture.complete(null); } else { shuttingDown = true; } } } private final CollaborationEngine ce; // Active handlers to deactivate if the service is destroyed private final Set activeHandlers = new HashSet<>(); private Registration serviceDestroyRegistration; /** * Creates a new system connection context instance for the given * Collaboration Engine instance. It is typically recommended reusing an * existing instance through {@link #getInstance()} or * {@link CollaborationEngine#getSystemContext()} rather than creating new * instances. * * @param ce * the collaboration engine instance to use, not * null */ public SystemConnectionContext(CollaborationEngine ce) { this.ce = Objects.requireNonNull(ce); } /** * Gets the system connection context associated with the current * Collaboration Engine instance. This method can be used only when * {@link CollaborationEngine#getInstance()} is available. * * @return a system connection context instance, not null * @throws IllegalStateException * in case no current collaboration engine instance is available */ public static SystemConnectionContext getInstance() { CollaborationEngine ce = CollaborationEngine.getInstance(); if (ce == null) { throw new IllegalStateException( "This method cannot be used when CollaborationEngine has not been configured for the current VaadinService."); } return ce.getSystemContext(); } @Override public Registration init(ActivationHandler activationHandler, Executor executor) { Objects.requireNonNull(activationHandler); Objects.requireNonNull(executor); synchronized (activeHandlers) { if (activeHandlers.isEmpty()) { serviceDestroyRegistration = ce.getVaadinService() .addServiceDestroyListener(e -> { synchronized (activeHandlers) { activeHandlers.forEach( handler -> handler.accept(null)); activeHandlers.clear(); } }); } if (!activeHandlers.add(activationHandler)) { throw new IllegalStateException( "The provided activation handler was already active"); } ActionDispatcherImplementation actionDispatcher = new ActionDispatcherImplementation( executor); activationHandler.accept(actionDispatcher); return new AsyncRegistration(actionDispatcher.shutdownFuture, () -> { synchronized (activeHandlers) { if (activeHandlers.remove(activationHandler)) { activationHandler.accept(null); actionDispatcher.shutdown(); if (activeHandlers.isEmpty()) { serviceDestroyRegistration.remove(); serviceDestroyRegistration = null; } } } }); } } // For testing CollaborationEngine getCollaborationEngine() { return ce; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy