com.kurento.kmf.content.internal.ContentApiWebApplicationInitializer.java Source code

Java tutorial

Introduction

Here is the source code for com.kurento.kmf.content.internal.ContentApiWebApplicationInitializer.java

Source

/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */
package com.kurento.kmf.content.internal;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.WebApplicationInitializer;

import com.kurento.kmf.common.exception.internal.ReflectionUtils;
import com.kurento.kmf.content.HttpPlayerHandler;
import com.kurento.kmf.content.HttpPlayerService;
import com.kurento.kmf.content.HttpRecorderHandler;
import com.kurento.kmf.content.HttpRecorderService;
import com.kurento.kmf.content.RtpContentHandler;
import com.kurento.kmf.content.RtpContentService;
import com.kurento.kmf.content.WebRtcContentHandler;
import com.kurento.kmf.content.WebRtcContentService;
import com.kurento.kmf.content.internal.player.PlayerHandlerServlet;
import com.kurento.kmf.content.internal.recorder.RecorderHandlerServlet;
import com.kurento.kmf.content.internal.rtp.RtpMediaHandlerServlet;
import com.kurento.kmf.content.internal.webrtc.WebRtcMediaHandlerServlet;
import com.kurento.kmf.spring.KurentoApplicationContextUtils;

/**
 * TODO: review & improve javadoc
 * 
 * This class performs the initialization of the implemented web applications,
 * searching the declared handlers with corresponding annotations (
 * {@link HttpPlayerService}, {@link HttpRecorderService},
 * {@link RtpContentService}, {@link RtpContentService}).
 * 
 * @see HttpPlayerService
 * @see HttpRecorderService
 * @see RtpContentService
 * @see WebRtcContentService
 * 
 * @author Luis Lpez (llopez@gsyc.es)
 * @author Boni Garca (bgarcia@gsyc.es)
 * @version 1.0.0
 */
public class ContentApiWebApplicationInitializer implements WebApplicationInitializer {

    /**
     * Logger.
     */
    private static final Logger log = LoggerFactory.getLogger(ContentApiWebApplicationInitializer.class);

    /**
     * Identifier for the declared handlers.
     */
    public static final String HANDLER_CLASS_PARAM_NAME = ContentApiWebApplicationInitializer.class.getName()
            + "HandlerClassParamName";

    /**
     * Web initialization is performed in this method, calling every handler
     * initilizator (player, recorder, webrtc, rtp).
     */
    @Override
    public void onStartup(ServletContext sc) throws ServletException {

        // At this stage we cannot create KurentoApplicationContext given that
        // we don't know y App developer wants to instantiate a Spring root
        // WebApplicationContext
        // ... so we need to live without Spring

        initializeRecorders(sc);
        initializePlayers(sc);
        initializeWebRtcMediaServices(sc);
        initializeRtpMediaServices(sc);

        // Register Kurento ServletContextListener
        KurentoApplicationContextUtils.registerKurentoServletContextListener(sc);
    }

    /**
     * Player initializator: this method search classes in the classpath using
     * the annotation {@link HttpPlayerService}, and it register a servlet for
     * each handler found.
     * 
     * @param sc
     *            Servlet Context in which register servlets for each handler
     * @throws ServletException
     *             Exception raised when a reflection problem occurs, typically
     *             when a class has not been found in the classpath
     */
    private void initializePlayers(ServletContext sc) throws ServletException {
        for (String ph : findServices(HttpPlayerHandler.class, HttpPlayerService.class)) {
            try {
                HttpPlayerService playerService = Class.forName(ph).getAnnotation(HttpPlayerService.class);
                if (playerService != null) {
                    String name = playerService.name().isEmpty() ? ph : playerService.name();
                    String path = playerService.path();
                    log.debug("Registering HttpPlayerHandler with name " + name + " at path " + path);
                    ServletRegistration.Dynamic sr = sc.addServlet(name, PlayerHandlerServlet.class);
                    if (sr == null) {
                        throw new ServletException("Duplicated handler named " + name
                                + " found. You must check your handlers' annotations to assert that no name duplications are declared.");
                    }
                    sr.addMapping(path);
                    sr.setInitParameter(HANDLER_CLASS_PARAM_NAME, ph);
                    sr.setAsyncSupported(true);
                }
            } catch (ClassNotFoundException e) {
                log.error("Error: could not find class " + ph + " in classpath", e);
                throw new ServletException(e);
            }
        }
    }

    /**
     * Recorder initializator: this method search classes in the classpath using
     * the annotation {@link HttpRecorderService}, and it register a servlet for
     * each handler found.
     * 
     * @param sc
     *            Servlet Context in which registering servlets for each handler
     * @throws ServletException
     *             Exception raised when a reflection problem occurs, typically
     *             when a class has not been found in the classpath
     */
    private void initializeRecorders(ServletContext sc) throws ServletException {
        for (String rh : findServices(HttpRecorderHandler.class, HttpRecorderService.class)) {
            try {
                HttpRecorderService recorderService = Class.forName(rh).getAnnotation(HttpRecorderService.class);
                if (recorderService != null) {
                    String name = recorderService.name().isEmpty() ? rh : recorderService.name();
                    String path = recorderService.path();
                    log.debug("Registering HttpRecorderHandler with name " + name + " at path " + path);
                    ServletRegistration.Dynamic sr = sc.addServlet(name, RecorderHandlerServlet.class);
                    sr.addMapping(path);
                    sr.setInitParameter(HANDLER_CLASS_PARAM_NAME, rh);
                    sr.setAsyncSupported(true);
                }
            } catch (ClassNotFoundException e) {
                log.error("Error: could not find class " + rh + " in classpath", e);
                throw new ServletException(e);
            }
        }
    }

    /**
     * WebRtc initializator: this method search classes in the classpath using
     * the annotation {@link WebRtcContentService}, and it register a servlet
     * for each handler found.
     * 
     * @param sc
     *            Servlet Context in which register servlets for each handler
     * @throws ServletException
     *             Exception raised when a reflection problem occurs, typically
     *             when a class has not been found in the classpath
     */
    private void initializeWebRtcMediaServices(ServletContext sc) throws ServletException {
        for (String wh : findServices(WebRtcContentHandler.class, WebRtcContentService.class)) {
            try {
                WebRtcContentService mediaService = Class.forName(wh).getAnnotation(WebRtcContentService.class);
                if (mediaService != null) {
                    String name = mediaService.name().isEmpty() ? wh : mediaService.name();
                    String path = mediaService.path();
                    log.debug("Registering WebRtcContentHandler with name " + name + " at path " + path);
                    ServletRegistration.Dynamic sr = sc.addServlet(name, WebRtcMediaHandlerServlet.class);
                    sr.addMapping(path);
                    sr.setInitParameter(HANDLER_CLASS_PARAM_NAME, wh);
                    sr.setAsyncSupported(true);
                }
            } catch (ClassNotFoundException e) {
                log.error("Error: could not find class " + wh + " in classpath", e);
                throw new ServletException(e);
            }
        }
    }

    /**
     * RtpMedia initializator: this method search classes in the classpath using
     * the annotation {@link RtpContentService}, and it register a servlet for
     * each handler found.
     * 
     * @param sc
     *            Servlet Context in which register servlets for each handler
     * @throws ServletException
     *             Exception raised when a reflection problem occurs, typically
     *             when a class has not been found in the classpath
     */
    private void initializeRtpMediaServices(ServletContext sc) throws ServletException {
        for (String rh : findServices(RtpContentHandler.class, RtpContentService.class)) {
            try {
                RtpContentService mediaService = Class.forName(rh).getAnnotation(RtpContentService.class);
                if (mediaService != null) {
                    String name = mediaService.name().isEmpty() ? rh : mediaService.name();
                    String path = mediaService.path();
                    log.debug("Registering RtpContentHandler with name " + name + " at path " + path);
                    ServletRegistration.Dynamic sr = sc.addServlet(name, RtpMediaHandlerServlet.class);
                    sr.addMapping(path);
                    sr.setInitParameter(HANDLER_CLASS_PARAM_NAME, rh);
                    sr.setAsyncSupported(true);
                }
            } catch (ClassNotFoundException e) {
                log.error("Error: could not find class " + rh + " in classpath", e);
                throw new ServletException(e);
            }
        }

    }

    /**
     * It seeks declared handlers in the classpath by using reflections.
     * 
     * @param handlerClass
     *            Handler class ({@link HttpPlayerHandler},
     *            {@link HttpRecorderHandler}, {@link WebRtcContentHandler},
     *            {@link RtpContentHandler})
     * @param serviceAnnotation
     *            Service annotation ({@link HttpPlayerService},
     *            {@link HttpRecorderService}, {@link WebRtcContentService},
     *            {@link RtpContentService})
     * @return List of services
     * @throws ServletException
     *             Exception raised when an incorrect implementation of handler
     *             is detected (mismatching between annotation and inheritance
     *             in handler)
     */
    private List<String> findServices(Class<?> handlerClass, Class<? extends Annotation> serviceAnnotation)
            throws ServletException {
        Set<Class<?>> annotatedList = ReflectionUtils.getTypesAnnotatedWith(serviceAnnotation);
        List<String> handlerList = new ArrayList<String>();
        for (Class<?> clazz : annotatedList) {
            if (handlerClass.isAssignableFrom(clazz)) {
                handlerList.add(clazz.getCanonicalName());
            } else {
                String error = "Incorrect implementation of handler: class " + clazz.getCanonicalName()
                        + " is annotated with " + serviceAnnotation.getSimpleName() + " (instead, "
                        + clazz.getSimpleName() + " should extend " + handlerClass.getSimpleName()
                        + " or use the correct annotation)";
                log.error(error);
                throw new ServletException(error);
            }
        }
        return handlerList;
    }
}