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

org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration Maven / Gradle / Ivy

/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.kurento.jsonrpc.internal.server.config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.catalina.Context;
import org.apache.tomcat.websocket.server.WsSci;
import org.kurento.jsonrpc.JsonRpcHandler;
import org.kurento.jsonrpc.internal.http.JsonRpcHttpRequestHandler;
import org.kurento.jsonrpc.internal.server.PerSessionJsonRpcHandler;
import org.kurento.jsonrpc.internal.server.ProtocolManager;
import org.kurento.jsonrpc.internal.server.SessionsManager;
import org.kurento.jsonrpc.internal.ws.JsonRpcWebSocketHandler;
import org.kurento.jsonrpc.server.JsonRpcConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistration;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class JsonRpcConfiguration implements WebSocketConfigurer {

  // public static class LoggerHandshakeInterceptor implements
  // HandshakeInterceptor {
  //
  // private static final Logger log = LoggerFactory
  // .getLogger(LoggerHandshakeInterceptor.class);
  //
  // @Override
  // public boolean beforeHandshake(ServerHttpRequest request,
  // ServerHttpResponse response, WebSocketHandler wsHandler,
  // Map attributes) throws Exception {
  //
  // log.debug(
  // "Websocket request before handshake. Request: headers={} uri={}
  // Attributes:{},",
  // request.getHeaders(), request.getURI(), attributes);
  //
  // return true;
  // }
  //
  // @Override
  // public void afterHandshake(ServerHttpRequest request,
  // ServerHttpResponse response, WebSocketHandler wsHandler,
  // Exception exception) {
  //
  // log.debug(
  // "Websocket request after handshake. Request: headers={} uri={}
  // Exception:{},",
  // request.getHeaders(), request.getURI(), exception);
  // }
  // }

  @Autowired
  protected ApplicationContext ctx;

  private final List configurers = new ArrayList<>();
  private DefaultJsonRpcHandlerRegistry instanceRegistry;

  private DefaultJsonRpcHandlerRegistry getJsonRpcHandlersRegistry() {
    if (instanceRegistry == null) {
      instanceRegistry = new DefaultJsonRpcHandlerRegistry();
      for (JsonRpcConfigurer configurer : this.configurers) {
        configurer.registerJsonRpcHandlers(instanceRegistry);
      }
    }
    return instanceRegistry;
  }

  @Autowired(required = false)
  public void setConfigurers(List configurers) {
    if (!CollectionUtils.isEmpty(configurers)) {
      this.configurers.addAll(configurers);
    }
  }

  @Bean
  public JsonRpcProperties jsonRpcProperties() {
    return new JsonRpcProperties();
  }

  // ---------------- HttpRequestHandlers -------------

  @Bean
  public HandlerMapping jsonRpcHandlerMapping() {

    DefaultJsonRpcHandlerRegistry registry = getJsonRpcHandlersRegistry();

    Map urlMap = new LinkedHashMap<>();

    for (DefaultJsonRpcHandlerRegistration registration : registry.getRegistrations()) {

      for (Entry, List> e : registration.getHandlerMap().entrySet()) {

        JsonRpcHandler handler = e.getKey();
        List paths = e.getValue();
        putHandlersMappings(urlMap, handler, paths);
      }

      for (Entry> e : registration.getPerSessionHandlerBeanNameMap()
          .entrySet()) {

        String handlerBeanName = e.getKey();
        JsonRpcHandler handler =
            (JsonRpcHandler) ctx.getBean("perSessionJsonRpcHandler", handlerBeanName, null);
        List paths = e.getValue();
        putHandlersMappings(urlMap, handler, paths);
      }

      for (Entry>, List> e : registration
          .getPerSessionHandlerClassMap().entrySet()) {

        Class> handlerClass = e.getKey();
        JsonRpcHandler handler =
            (JsonRpcHandler) ctx.getBean("perSessionJsonRpcHandler", null, handlerClass);
        List paths = e.getValue();
        putHandlersMappings(urlMap, handler, paths);
      }
    }

    SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
    hm.setUrlMap(urlMap);
    hm.setOrder(1);
    return hm;
  }

  private void putHandlersMappings(Map urlMap, JsonRpcHandler handler,
      List paths) {

    JsonRpcHttpRequestHandler requestHandler =
        new JsonRpcHttpRequestHandler((ProtocolManager) ctx.getBean("protocolManager", handler));

    for (String path : paths) {
      urlMap.put(path, requestHandler);
    }
  }

  // ---------------- Websockets -------------------
  @Override
  public void registerWebSocketHandlers(WebSocketHandlerRegistry wsHandlerRegistry) {

    DefaultJsonRpcHandlerRegistry registry = getJsonRpcHandlersRegistry();

    for (DefaultJsonRpcHandlerRegistration registration : registry.getRegistrations()) {

      for (Entry, List> e : registration.getHandlerMap().entrySet()) {

        JsonRpcHandler handler = e.getKey();
        List paths = e.getValue();

        publishWebSocketEndpoint(wsHandlerRegistry, handler, paths);
      }

      for (Entry> e : registration.getPerSessionHandlerBeanNameMap()
          .entrySet()) {

        String handlerBeanName = e.getKey();
        JsonRpcHandler handler =
            (JsonRpcHandler) ctx.getBean("perSessionJsonRpcHandler", handlerBeanName, null);
        List paths = e.getValue();

        publishWebSocketEndpoint(wsHandlerRegistry, handler, paths);
      }

      for (Entry>, List> e : registration
          .getPerSessionHandlerClassMap().entrySet()) {

        Class> handlerClass = e.getKey();
        JsonRpcHandler handler =
            (JsonRpcHandler) ctx.getBean("perSessionJsonRpcHandler", null, handlerClass);
        List paths = e.getValue();

        publishWebSocketEndpoint(wsHandlerRegistry, handler, paths);
      }

    }
  }

  private void publishWebSocketEndpoint(WebSocketHandlerRegistry wsHandlerRegistry,
      JsonRpcHandler handler, List paths) {

    ProtocolManager protocolManager = (ProtocolManager) ctx.getBean("protocolManager", handler);

    JsonRpcWebSocketHandler wsHandler = new JsonRpcWebSocketHandler(protocolManager);

    protocolManager.setPingWachdog(handler.isPingWatchdog());

    for (String path : paths) {

      WebSocketHandlerRegistration registration = wsHandlerRegistry.addHandler(wsHandler, path);

      List origins = handler.allowedOrigins();
      registration.setAllowedOrigins(origins.toArray(new String[origins.size()]));

      if (handler.isSockJSEnabled()) {
        registration.withSockJS().setSessionCookieNeeded(false);
      }
    
      if (handler.getLabel() != null) {
        wsHandler.setLabel(handler.getLabel());
      }
    }
  }

  // This methods workaround the bug
  // https://jira.springsource.org/browse/SPR-10841
  @Bean
  public TomcatEmbeddedServletContainerFactory tomcatContainerFactory() {
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.setTomcatContextCustomizers(
        Arrays.asList(new TomcatContextCustomizer[] { tomcatContextCustomizer() }));
    return factory;
  }

  @Bean
  public TomcatContextCustomizer tomcatContextCustomizer() {
    return new TomcatContextCustomizer() {
      @Override
      public void customize(Context context) {
        context.addServletContainerInitializer(new WsSci(), null);
      }
    };
  }

  // ----------------------- Components ------------------------

  @Bean
  public SessionsManager sessionsManager() {
    return new SessionsManager();
  }

  @Bean
  @Scope("prototype")
  public ProtocolManager protocolManager(JsonRpcHandler key) {
    return new ProtocolManager(key);
  }

  @Bean
  @Scope("prototype")
  @SuppressWarnings({ "rawtypes", "unchecked" })
  public PerSessionJsonRpcHandler perSessionJsonRpcHandler(String beanName,
      Class> beanClass) {
    return new PerSessionJsonRpcHandler(beanName, beanClass);
  }

  @Bean(destroyMethod = "shutdown")
  public TaskScheduler jsonrpcTaskScheduler() {
    return new ThreadPoolTaskScheduler();
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy