/**
   * Starts a new thread which scans project files and automatically reloads a container on any
   * changes.
   *
   * @param scanIntervalSeconds
   * @param webapp
   * @param appContext
   */
  static void startScanner(final WebApplicationProxyImpl webApp, int scanIntervalSeconds)
      throws Exception {
    List scanList = new ArrayList();
    scanList.add(webApp.getWebXmlFile());
    scanList.addAll(webApp.getLibraries());
    scanList.addAll(webApp.getExtraScanTargets());

    Scanner.Listener changeListener =
        new Scanner.BulkListener() {

          public void filesChanged(List changedFiles) {
            if (hasAnyFileChanged(changedFiles)) {
              try {
                webApp.stop();
                webApp.applyConfiguration();
                webApp.start();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }
          }

          /**
           * Checks if any file in this particular application has changed. This is not that easy,
           * because some applications may use the same class'es directory.
           *
           * @param changedFiles list of changed files.
           * @return true if any of passed files has changed, false otherwise.
           */
          private boolean hasAnyFileChanged(List changedFiles) {
            Iterator changes = changedFiles.iterator();
            while (changes.hasNext()) {
              String className = (String) changes.next();
              if (webApp.isFileScanned(className)) {
                return true;
              }
            }

            return false;
          }
        };

    TaskLog.log(
        "Web application '"
            + webApp.getName()
            + "': starting scanner at interval of "
            + scanIntervalSeconds
            + " seconds.");

    Scanner scanner = new Scanner();
    scanner.setScanInterval(scanIntervalSeconds);
    scanner.addListener(changeListener);
    scanner.setScanDirs(scanList);
    scanner.setReportExistingFilesOnStartup(false);
    scanner.start();
  }
  /**
   * Executes this Ant task. The build flow is being stopped until Jetty server stops.
   *
   * @throws BuildException
   */
  public void execute() throws BuildException {
    TaskLog.setTask(this);
    TaskLog.log("Configuring Jetty for project: " + getProject().getName());
    WebApplicationProxyImpl.setBaseTempDirectory(tempDirectory);
    setSystemProperties();

    List connectorsList = null;

    if (connectors != null) {
      connectorsList = connectors.getConnectors();
    } else {
      connectorsList = new Connectors(jettyPort, 30000).getDefaultConnectors();
    }

    List loginServicesList =
        (loginServices != null ? loginServices.getLoginServices() : new ArrayList());
    ServerProxy server =
        new ServerProxyImpl(connectorsList, loginServicesList, requestLog, jettyXml);

    try {
      Iterator iterator = webapps.iterator();
      while (iterator.hasNext()) {
        WebApp webAppConfiguration = (WebApp) iterator.next();
        WebApplicationProxyImpl webApp = new WebApplicationProxyImpl(webAppConfiguration.getName());
        webApp.setSourceDirectory(webAppConfiguration.getWarFile());
        webApp.setContextPath(webAppConfiguration.getContextPath());
        webApp.setWebXml(webAppConfiguration.getWebXmlFile());
        webApp.setJettyEnvXml(webAppConfiguration.getJettyEnvXml());
        webApp.setClassPathFiles(webAppConfiguration.getClassPathFiles());
        webApp.setLibrariesConfiguration(webAppConfiguration.getLibrariesConfiguration());
        webApp.setExtraScanTargetsConfiguration(webAppConfiguration.getScanTargetsConfiguration());
        webApp.setContextHandlers(webAppConfiguration.getContextHandlers());
        webApp.setWebDefaultXmlFile(webAppConfiguration.getWebDefaultXmlFile());

        server.addWebApplication(webApp, webAppConfiguration.getScanIntervalSeconds());
      }
    } catch (Exception e) {
      throw new BuildException(e);
    }

    server.start();
  }
  public void addLoginServices(LoginServices services) {
    TaskLog.log("Setting <loginServices> via Ant is currently not supported.");
    /*
    if (this.loginServices != null )
    {
        throw new BuildException("Only one <loginServices> tag is allowed!");
    }

    this.loginServices = services;
    */
  }
 /** @deprecated */
 public void addUserRealms(Object o) {
   TaskLog.log("User realms are deprecated.");
 }