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

com.vaadin.server.communication.JSR356WebsocketInitializer Maven / Gradle / Ivy

There is a newer version: 8.27.3
Show newest version
/*
 * Copyright (C) 2000-2024 Vaadin Ltd
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */
package com.vaadin.server.communication;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebListener;

import org.atmosphere.cpr.AtmosphereFramework;

import com.vaadin.server.VaadinServlet;

/**
 * Initializer class for JSR 356 websockets.
 * 

* Websocket specification says that initialization of websocket end points * should be done in the servlet context initialization phase. Some servers * implement this strictly so that end points cannot be registered after the * context initialization phase. *

* Note that {@link WebListener} is Servlet 3.0 API so this will not be run for * older servers (unless added to web.xml), but these servers do not support JSR * 356 websockets either. * * @since 7.5.0 * @author Vaadin Ltd */ @WebListener public class JSR356WebsocketInitializer implements ServletContextListener { private static boolean atmosphereAvailable = false; static { try { org.atmosphere.util.Version.getRawVersion(); atmosphereAvailable = true; } catch (NoClassDefFoundError e) { } } /** * "ServletConfig" which only provides information from a * {@link ServletRegistration} and its {@link ServletContext}. */ public static class FakeServletConfig implements ServletConfig { private final ServletRegistration servletRegistration; private final ServletContext servletContext; public FakeServletConfig(ServletRegistration servletRegistration, ServletContext servletContext) { this.servletContext = servletContext; this.servletRegistration = servletRegistration; } @Override public String getServletName() { return servletRegistration.getName(); } @Override public ServletContext getServletContext() { return servletContext; } @Override public String getInitParameter(String name) { return servletRegistration.getInitParameter(name); } @Override public Enumeration getInitParameterNames() { return Collections.enumeration( servletRegistration.getInitParameters().keySet()); } } @Override public void contextInitialized(ServletContextEvent sce) { ServletContext servletContext = sce.getServletContext(); if (servletContext.getMajorVersion() < 3) { return; } init(servletContext); } /** * Initializes Atmosphere for use with Vaadin servlets found in the given * context. *

* For JSR 356 websockets to work properly, the initialization must be done * in the servlet context initialization phase. * * @param servletContext * The servlet context */ public void init(ServletContext servletContext) { if (!atmosphereAvailable) { return; } Map regs = servletContext .getServletRegistrations(); for (String servletName : regs.keySet()) { ServletRegistration servletRegistration = regs.get(servletName); if (isVaadinServlet(servletRegistration, servletContext)) { try { initAtmosphereForVaadinServlet(servletRegistration, servletContext); } catch (Exception e) { getLogger().log(Level.WARNING, "Failed to initialize Atmosphere for " + servletName, e); } } } } /** * Initializes Atmosphere for use with the given Vaadin servlet *

* For JSR 356 websockets to work properly, the initialization must be done * in the servlet context initialization phase. * * @param servletRegistration * The servlet registration info for the servlet * @param servletContext */ public static void initAtmosphereForVaadinServlet( ServletRegistration servletRegistration, ServletContext servletContext) { String servletName = servletRegistration.getName(); String attributeName = getAttributeName(servletName); if (servletContext.getAttribute(attributeName) != null) { // Already initialized getLogger().warning("Atmosphere already initialized"); return; } getLogger().finer("Creating AtmosphereFramework for " + servletName); AtmosphereFramework framework = PushRequestHandler.initAtmosphere( new FakeServletConfig(servletRegistration, servletContext)); servletContext.setAttribute(attributeName, framework); getLogger().finer("Created AtmosphereFramework for " + servletName); } /** * Returns the name of the attribute in the servlet context where the * pre-initialized Atmosphere object is stored. * * @param servletName * The name of the servlet * @return The attribute name which contains the initialized Atmosphere * object */ public static String getAttributeName(String servletName) { return JSR356WebsocketInitializer.class.getName() + "." + servletName; } /** * Checks if the given attribute name matches the convention used for * storing AtmosphereFramework references. * * @param attributeName * the attribute name to check * @return true if the attribute name matches the convention, * false otherwise */ private static boolean isAtmosphereFrameworkAttribute( String attributeName) { return attributeName .startsWith(JSR356WebsocketInitializer.class.getName() + "."); } /** * Tries to determine if the given servlet registration refers to a Vaadin * servlet. * * @param servletRegistration * The servlet registration info for the servlet * @return false if the servlet is definitely not a Vaadin servlet, true * otherwise */ protected boolean isVaadinServlet(ServletRegistration servletRegistration, ServletContext servletContext) { try { String servletClassName = servletRegistration.getClassName(); if (servletClassName.equals("com.ibm.ws.wsoc.WsocServlet")) { // Websphere servlet which implements websocket endpoints, // dynamically added return false; } // Must use servletContext class loader to load servlet class to // work correctly in an OSGi environment (#20024) Class servletClass = servletContext.getClassLoader() .loadClass(servletClassName); return VaadinServlet.class.isAssignableFrom(servletClass); } catch (Exception e) { // This will fail in OSGi environments, assume everything is a // VaadinServlet return true; } } private static final Logger getLogger() { return Logger.getLogger(JSR356WebsocketInitializer.class.getName()); } @Override public void contextDestroyed(ServletContextEvent sce) { // Destroy any AtmosphereFramework instance we have initialized. // This must be done here to ensure that we cleanup Atmosphere instances // related to servlets which are never initialized ServletContext servletContext = sce.getServletContext(); Enumeration attributeNames = servletContext.getAttributeNames(); while (attributeNames.hasMoreElements()) { String attributeName = attributeNames.nextElement(); if (isAtmosphereFrameworkAttribute(attributeName)) { Object value = servletContext.getAttribute(attributeName); if (value instanceof AtmosphereFramework) { // This might result in calling destroy() twice, once from // here and once from PushRequestHandler but // AtmosphereFramework.destroy() deals with that ((AtmosphereFramework) value).destroy(); } } } } /** * Checks if Atmosphere is available on the classpath. * * @return true if Atmosphere is available, false * otherwise */ public static boolean isAtmosphereAvailable() { return atmosphereAvailable; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy