/** {@inheritDoc} */
  public void configureWebApp() throws Exception {
    log.debug("Configuring Jetty webapp");

    // Get context
    WebAppContext context = getWebAppContext();

    // If app is already started...
    if (context.isStarted()) {
      log.debug("Cannot configure webapp after it is started");
      return;
    }

    // Get WEB_INF directory
    Resource webInf = context.getWebInf();
    if (webInf != null && webInf.isDirectory()) {
      // Get properties file with virtualHosts and context path
      Resource config = webInf.addPath("red5-web.properties");
      if (config.exists()) {
        log.debug("Configuring red5-web.properties");
        // Load configuration properties
        Properties props = new Properties();
        props.load(config.getInputStream());

        // Get context path and virtual hosts
        String contextPath = props.getProperty("webapp.contextPath");
        String virtualHosts = props.getProperty("webapp.virtualHosts");

        // Get hostnames
        String[] hostnames = virtualHosts.split(",");
        for (int i = 0; i < hostnames.length; i++) {
          hostnames[i] = hostnames[i].trim();
          if (hostnames[i].equals("*")) {
            // A virtual host "null" must be used so requests for
            // any host will be served.
            hostnames = null;
            break;
          }
        }

        // Set virtual hosts and context path to context
        context.setVirtualHosts(hostnames);
        context.setContextPath(contextPath);
        LoaderBase.setRed5ApplicationContext(contextPath, new JettyApplicationContext(context));
      }
    } else if (webInf == null) {
      // No WEB-INF directory found, register as default application
      log.info(
          "No WEB-INF directory found for "
              + context.getContextPath()
              + ", creating default application.");
      BeanFactoryLocator bfl = ContextSingletonBeanFactoryLocator.getInstance("red5.xml");
      BeanFactoryReference bfr = bfl.useBeanFactory("red5.common");

      // Create WebScope dynamically
      WebScope scope = new WebScope();
      IServer server = (IServer) bfr.getFactory().getBean(IServer.ID);
      scope.setServer(server);
      scope.setGlobalScope(server.getGlobal("default"));

      // Get default Red5 context from context loader that is JettyLoader in this case
      ApplicationContext appCtx = JettyLoader.getApplicationContext();
      ContextLoader loader = (ContextLoader) appCtx.getBean("context.loader");
      appCtx = loader.getContext("default.context");

      // Create context for the WebScope and initialize
      Context scopeContext = new Context();
      scopeContext.setContextPath("/");
      scopeContext.setClientRegistry((IClientRegistry) appCtx.getBean("global.clientRegistry"));
      scopeContext.setMappingStrategy((IMappingStrategy) appCtx.getBean("global.mappingStrategy"));
      scopeContext.setServiceInvoker((IServiceInvoker) appCtx.getBean("global.serviceInvoker"));
      scopeContext.setScopeResolver((IScopeResolver) appCtx.getBean("red5.scopeResolver"));

      // The context needs an ApplicationContext so resources can be
      // resolved
      GenericWebApplicationContext webCtx = new GenericWebApplicationContext();
      webCtx.setDisplayName("Automatic generated WebAppContext");
      webCtx.setParent(appCtx);
      webCtx.setServletContext(ContextHandler.getCurrentContext());
      scopeContext.setApplicationContext(webCtx);

      // Store context in scope
      scope.setContext(scopeContext);

      // Use default ApplicationAdapter as handler
      scope.setHandler(new ApplicationAdapter());

      // Make available as "/<directoryName>" and allow access from all
      // hosts
      scope.setContextPath(context.getContextPath());
      scope.setVirtualHosts("*");

      LoaderBase.setRed5ApplicationContext(
          context.getContextPath(), new JettyApplicationContext(context));

      // Register WebScope in server
      scope.register();
    }
  }
 /**
  * Initialization.
  *
  * @throws ServletException
  */
 @SuppressWarnings("cast")
 @Override
 public void start() throws ServletException {
   log.info("Loading tomcat virtual host");
   if (webappFolder != null) {
     // check for match with base webapp root
     if (webappFolder.equals(webappRoot)) {
       log.error("Web application root cannot be the same as base");
       return;
     }
   }
   ClassLoader classloader = Thread.currentThread().getContextClassLoader();
   // ensure we have a host
   if (host == null) {
     host = createHost();
   }
   host.setParentClassLoader(classloader);
   String propertyPrefix = name;
   if (domain != null) {
     propertyPrefix += '_' + domain.replace('.', '_');
   }
   log.debug("Generating name (for props) {}", propertyPrefix);
   System.setProperty(propertyPrefix + ".webapp.root", webappRoot);
   log.info("Virtual host root: {}", webappRoot);
   log.info("Virtual host context id: {}", defaultApplicationContextId);
   // Root applications directory
   File appDirBase = new File(webappRoot);
   // Subdirs of root apps dir
   File[] dirs = appDirBase.listFiles(new TomcatLoader.DirectoryFilter());
   // Search for additional context files
   for (File dir : dirs) {
     String dirName = '/' + dir.getName();
     // check to see if the directory is already mapped
     if (null == host.findChild(dirName)) {
       String webappContextDir = FileUtil.formatPath(appDirBase.getAbsolutePath(), dirName);
       Context ctx = null;
       if ("/root".equals(dirName) || "/root".equalsIgnoreCase(dirName)) {
         log.debug("Adding ROOT context");
         ctx = addContext("/", webappContextDir);
       } else {
         log.debug("Adding context from directory scan: {}", dirName);
         ctx = addContext(dirName, webappContextDir);
       }
       log.debug("Context: {}", ctx);
       webappContextDir = null;
     }
   }
   appDirBase = null;
   dirs = null;
   // Dump context list
   if (log.isDebugEnabled()) {
     for (Container cont : host.findChildren()) {
       log.debug("Context child name: {}", cont.getName());
     }
   }
   engine.addChild(host);
   // Start server
   try {
     log.info("Starting Tomcat virtual host");
     // may not have to do this step for every host
     LoaderBase.setApplicationLoader(
         new TomcatApplicationLoader(embedded, host, applicationContext));
     for (Container cont : host.findChildren()) {
       if (cont instanceof StandardContext) {
         StandardContext ctx = (StandardContext) cont;
         ServletContext servletContext = ctx.getServletContext();
         log.debug("Context initialized: {}", servletContext.getContextPath());
         // set the hosts id
         servletContext.setAttribute("red5.host.id", getHostId());
         String prefix = servletContext.getRealPath("/");
         log.debug("Path: {}", prefix);
         try {
           Loader cldr = ctx.getLoader();
           log.debug("Loader type: {}", cldr.getClass().getName());
           ClassLoader webClassLoader = cldr.getClassLoader();
           log.debug("Webapp classloader: {}", webClassLoader);
           // create a spring web application context
           XmlWebApplicationContext appctx = new XmlWebApplicationContext();
           appctx.setClassLoader(webClassLoader);
           appctx.setConfigLocations(new String[] {"/WEB-INF/red5-*.xml"});
           // check for red5 context bean
           if (applicationContext.containsBean(defaultApplicationContextId)) {
             appctx.setParent(
                 (ApplicationContext) applicationContext.getBean(defaultApplicationContextId));
           } else {
             log.warn(
                 "{} bean was not found in context: {}",
                 defaultApplicationContextId,
                 applicationContext.getDisplayName());
             // lookup context loader and attempt to get what we need from it
             if (applicationContext.containsBean("context.loader")) {
               ContextLoader contextLoader =
                   (ContextLoader) applicationContext.getBean("context.loader");
               appctx.setParent(contextLoader.getContext(defaultApplicationContextId));
             } else {
               log.debug("Context loader was not found, trying JMX");
               MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
               // get the ContextLoader from jmx
               ContextLoaderMXBean proxy = null;
               ObjectName oName = null;
               try {
                 oName = new ObjectName("org.red5.server:name=contextLoader,type=ContextLoader");
                 if (mbs.isRegistered(oName)) {
                   proxy = JMX.newMXBeanProxy(mbs, oName, ContextLoaderMXBean.class, true);
                   log.debug("Context loader was found");
                   proxy.setParentContext(defaultApplicationContextId, appctx.getId());
                 } else {
                   log.warn("Context loader was not found");
                 }
               } catch (Exception e) {
                 log.warn("Exception looking up ContextLoader", e);
               }
             }
           }
           if (log.isDebugEnabled()) {
             if (appctx.getParent() != null) {
               log.debug("Parent application context: {}", appctx.getParent().getDisplayName());
             }
           }
           //
           appctx.setServletContext(servletContext);
           // set the root webapp ctx attr on the each servlet context so spring can find it later
           servletContext.setAttribute(
               WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appctx);
           appctx.refresh();
         } catch (Throwable t) {
           log.error("Error setting up context: {}", servletContext.getContextPath(), t);
           if (log.isDebugEnabled()) {
             t.printStackTrace();
           }
         }
       }
     }
   } catch (Exception e) {
     log.error("Error loading Tomcat virtual host", e);
   }
 }