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

org.glassfish.grizzly.comet.CometEngine Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.grizzly.comet;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.grizzly.localization.LogMessages;

/**
 * Main class allowing Comet support on top of Grizzly Asynchronous Request Processing mechanism. This class is the
 * entry point to any component interested to execute Comet request style. Components can be Servlets, JSP, JSF or pure
 * Java class. A component interested to support Comet request must do:
 * 
 * 
 * 
 * (1) First, register the topic on which Comet support will be applied:
 *     CometEngine cometEngine = CometEngine.getEngine()
 *     CometContext cometContext = cometEngine.register(topic)
 * (2) Second, add an instance of {@link CometHandler} to the
 *     {@link CometContext} returned by the register method:
 *     {@link CometContext#addCometHandler}. Executing this operation
 *     will tells Grizzly to suspend the response.
 * (3) Finally, you can {@link CometContext#notify} other {@link CometHandler}
 *     to share information between {@link CometHandler}. When notified,
 *     {@link CometHandler} can decides to push back the data, resume the
 *     response, or simply ignore the content of the notification.
 * 
 * 
* * You can also select the stage where the suspension of the response happens when registering the * {@link CometContext}'s topic (see {@link #register}), which can be before, during or after invoking a * Servlet * * There is known limitation related to HTTP pipelining, it can't work properly when * {@link CometContext#isDetectClosedConnections()} is enabled. So if you want to support HTTP pipelining, the * closed connection detection mechanism should be disabled via * {@link CometContext#setDetectClosedConnections(boolean)}. * * @author Jeanfrancois Arcand * @author Gustav Trede */ public class CometEngine { // Disable suspended connection time out for a {@link CometContext#setExpirationDelay} @Deprecated public final static int DISABLE_SUSPEND_TIMEOUT = -1; // Disable client detection close for a {@link CometContext#setExpirationDelay} @Deprecated public final static int DISABLE_CLIENT_DISCONNECTION_DETECTION = 0; /** * The token used to support BEFORE_REQUEST_PROCESSING polling. */ @Deprecated public final static int BEFORE_REQUEST_PROCESSING = 0; /** * The token used to support AFTER_SERVLET_PROCESSING polling. */ @Deprecated public final static int AFTER_SERVLET_PROCESSING = 1; /** * The token used to support BEFORE_RESPONSE_PROCESSING polling. */ @Deprecated public final static int AFTER_RESPONSE_PROCESSING = 2; /** * Main logger */ protected final static Logger logger = Logger.getLogger(CometEngine.class.getName()); /** * The {@link ExecutorService} used to execute */ protected ExecutorService threadPool; /** * The single instance of this class. */ private final static CometEngine cometEngine = new CometEngine(); /** * The current active {@link CometContext} keyed by context path. */ protected final Map activeContexts; /** * Is Grizzly ARP enabled? By default we set it to false. */ private boolean isCometSupported; /** * Create a singleton and initialize all lists required. */ protected CometEngine() { activeContexts = new ConcurrentHashMap<>(16, 0.75f, 64); } /** * Return true if comet is enabled. */ protected boolean isCometEnabled() { return isCometSupported; } public void setCometSupported(boolean supported) { isCometSupported = supported; } /** * Return a singleton of this Class. * * @return CometEngine the singleton. */ public static CometEngine getEngine() { return cometEngine; } /** * Calls through to {@link #deregister(String)}. * * @deprecated */ @Deprecated public CometContext unregister(String topic) { return deregister(topic); } /** * Deregister the {@link CometHandler} to the list of the {@link CometContext}. Invoking this method will invoke all * {@link CometHandler#onTerminate(CometEvent)} before removing the associated {@link CometContext}. Invoking that * method will also resume the underlying connection associated with the {@link CometHandler}, similar to what * {@link CometContext#resumeCometHandler(CometHandler)} do. */ public CometContext deregister(String topic) { CometContext cometContext = activeContexts.remove(topic); if (cometContext != null) { cometContext.recycle(); } return cometContext; } /** * Register a context path with this {@link CometEngine}. The {@link CometContext} returned will be of type * type. * * @param topic the context path used to create the {@link CometContext} * @param type when the request will be suspended * * @return CometContext a configured {@link CometContext}. * @deprecated Use {@link #register(String)} instead */ @Deprecated public CometContext register(String topic, int type) { return register(topic); } /** * Register a context path with this {@link CometEngine}. The {@link CometContext} returned will be of type * AFTER_SERVLET_PROCESSING, which means the request target (most probably a Servlet) will be executed first and then * polled. * * @param topic the context path used to create the {@link CometContext} * * @return CometContext a configured {@link CometContext}. */ public CometContext register(String topic) { return register(topic, DefaultNotificationHandler.class); } /** * Instantiate a new {@link CometContext}. * * @param topic the topic the new {@link CometContext} will represent. * @return a new {@link CometContext} if not already created, or the existing one. */ @SuppressWarnings({ "unchecked" }) public CometContext register(String topic, Class notificationClass) { // Double checked locking used used to prevent the otherwise static/global // locking, cause example code does heavy usage of register calls // for existing topics from http get calls etc. CometContext cometContext = activeContexts.get(topic); if (cometContext == null) { synchronized (activeContexts) { cometContext = activeContexts.get(topic); if (cometContext == null) { cometContext = new CometContext<>(topic); NotificationHandler notificationHandler; try { notificationHandler = notificationClass.newInstance(); } catch (Throwable t) { if (logger.isLoggable(Level.SEVERE)) { logger.log(Level.SEVERE, LogMessages.SEVERE_GRIZZLY_COMET_ENGINE_INVALID_NOTIFICATION_HANDLER_ERROR(notificationClass.getName()), t); } notificationHandler = new DefaultNotificationHandler(); } cometContext.setNotificationHandler(notificationHandler); if (notificationHandler != null && notificationHandler instanceof DefaultNotificationHandler) { ((DefaultNotificationHandler) notificationHandler).setThreadPool(threadPool); } activeContexts.put(topic, cometContext); } } } return cometContext; } /** * Return the {@link CometContext} associated with the topic. * * @param topic the topic used to creates the {@link CometContext} */ @SuppressWarnings({ "unchecked" }) public CometContext getCometContext(String topic) { return activeContexts.get(topic); } /** * Interrupt a {@link CometHandler} by invoking {@link CometHandler#onInterrupt} * * @param handler The {@link CometHandler} encapsulating the suspended connection. * @param finishExecution Finish the current execution. * * @see CometContext#interrupt(CometHandler, boolean) * @deprecated use the CometContext version */ @Deprecated @SuppressWarnings({ "deprecation" }) protected boolean interrupt(CometHandler handler, boolean finishExecution) throws IOException { final CometContext cometContext = handler.getCometContext(); final boolean removed = cometContext.removeCometHandler(handler, finishExecution); if (removed && !finishExecution) { interrupt0(handler, finishExecution); } return removed; } /** * Interrupt logic in its own method, so it can be executed either async or sync.
* cometHandler.onInterrupt is performed async due to its functionality is unknown, hence not safe to run in the * performance critical selector thread. * * @param handler The {@link CometHandler} encapsulating the suspended connection. * @param finishExecution Finish the current execution. * * @see CometContext#interrupt0(CometHandler, boolean) * @deprecated use the CometContext version */ @Deprecated protected void interrupt0(CometHandler handler, boolean finishExecution) throws IOException { if (finishExecution) { try { handler.onInterrupt(handler.getCometContext().eventInterrupt); } catch (IOException e) { } } handler.getResponse().finish(); } /** * Return the current logger. */ public static Logger logger() { return logger; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy