001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.socket.sockjs.transport.handler;
018
019import java.util.Arrays;
020import java.util.Collection;
021import java.util.LinkedHashSet;
022import java.util.Set;
023
024import javax.servlet.ServletContext;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028
029import org.springframework.lang.Nullable;
030import org.springframework.scheduling.TaskScheduler;
031import org.springframework.web.context.ServletContextAware;
032import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
033import org.springframework.web.socket.sockjs.transport.TransportHandler;
034import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService;
035
036/**
037 * A default implementation of {@link org.springframework.web.socket.sockjs.SockJsService}
038 * with all default {@link TransportHandler} implementations pre-registered.
039 *
040 * @author Rossen Stoyanchev
041 * @author Juergen Hoeller
042 * @since 4.0
043 */
044public class DefaultSockJsService extends TransportHandlingSockJsService implements ServletContextAware {
045
046        /**
047         * Create a DefaultSockJsService with default {@link TransportHandler handler} types.
048         * @param scheduler a task scheduler for heart-beat messages and removing
049         * timed-out sessions; the provided TaskScheduler should be declared as a
050         * Spring bean to ensure it is initialized at start up and shut down when the
051         * application stops.
052         */
053        public DefaultSockJsService(TaskScheduler scheduler) {
054                this(scheduler, getDefaultTransportHandlers(null));
055        }
056
057        /**
058         * Create a DefaultSockJsService with overridden {@link TransportHandler handler} types
059         * replacing the corresponding default handler implementation.
060         * @param scheduler a task scheduler for heart-beat messages and removing timed-out sessions;
061         * the provided TaskScheduler should be declared as a Spring bean to ensure it gets
062         * initialized at start-up and shuts down when the application stops
063         * @param handlerOverrides zero or more overrides to the default transport handler types
064         */
065        public DefaultSockJsService(TaskScheduler scheduler, TransportHandler... handlerOverrides) {
066                this(scheduler, Arrays.asList(handlerOverrides));
067        }
068
069        /**
070         * Create a DefaultSockJsService with overridden {@link TransportHandler handler} types
071         * replacing the corresponding default handler implementation.
072         * @param scheduler a task scheduler for heart-beat messages and removing timed-out sessions;
073         * the provided TaskScheduler should be declared as a Spring bean to ensure it gets
074         * initialized at start-up and shuts down when the application stops
075         * @param handlerOverrides zero or more overrides to the default transport handler types
076         */
077        public DefaultSockJsService(TaskScheduler scheduler, Collection<TransportHandler> handlerOverrides) {
078                super(scheduler, getDefaultTransportHandlers(handlerOverrides));
079        }
080
081
082        private static Set<TransportHandler> getDefaultTransportHandlers(@Nullable Collection<TransportHandler> overrides) {
083                Set<TransportHandler> result = new LinkedHashSet<>(8);
084                result.add(new XhrPollingTransportHandler());
085                result.add(new XhrReceivingTransportHandler());
086                result.add(new XhrStreamingTransportHandler());
087                result.add(new EventSourceTransportHandler());
088                result.add(new HtmlFileTransportHandler());
089                try {
090                        result.add(new WebSocketTransportHandler(new DefaultHandshakeHandler()));
091                }
092                catch (Exception ex) {
093                        Log logger = LogFactory.getLog(DefaultSockJsService.class);
094                        if (logger.isWarnEnabled()) {
095                                logger.warn("Failed to create a default WebSocketTransportHandler", ex);
096                        }
097                }
098                if (overrides != null) {
099                        result.addAll(overrides);
100                }
101                return result;
102        }
103
104        @Override
105        public void setServletContext(ServletContext servletContext) {
106                for (TransportHandler handler : getTransportHandlers().values()) {
107                        if (handler instanceof ServletContextAware) {
108                                ((ServletContextAware) handler).setServletContext(servletContext);
109                        }
110                }
111        }
112}