/**
   * Lancer par signal de NoPublicController quand le processus sshd est démarré dans les containers
   * serveur et git
   */
  public Application updateEnv(Application application, User user) throws ServiceException {

    logger.info("--update Env of Server--");
    String command = null;
    Map<String, String> configShellModule = new HashMap<>();
    Map<String, String> configShellServer = new HashMap<>();

    Module moduleGit = moduleService.findGitModule(user.getLogin(), application);
    Server server = application.getServers().get(0);

    String rootPassword = application.getUser().getPassword();
    configShellModule.put("port", moduleGit.getSshPort());
    configShellModule.put("dockerManagerAddress", moduleGit.getApplication().getManagerIp());
    configShellModule.put("password", rootPassword);
    configShellModule.put("dockerManagerAddress", application.getManagerIp());
    logger.info("new server ip : " + server.getContainerIP());
    try {
      int counter = 0;
      while (!server.getStatus().equals(Status.START)
          || !moduleGit.getStatus().equals(Status.START)) {
        if (counter == 100) {
          break;
        }
        Thread.sleep(1000);
        logger.info(" wait git and server sshd processus start");
        logger.info(
            "SSHDSTATUS = server : " + server.getStatus() + " - module : " + moduleGit.getStatus());
        moduleGit = moduleService.findById(moduleGit.getId());
        server = serverService.findById(server.getId());
        counter++;
      }
      command = ". /cloudunit/scripts/update-env.sh " + server.getContainerIP();
      logger.info("command shell to execute [" + command + "]");

      shellUtils.executeShell(command, configShellModule);

      configShellServer.put("port", server.getSshPort());
      configShellServer.put("dockerManagerAddress", server.getApplication().getManagerIp());
      configShellServer.put("password", rootPassword);
      command = ". /cloudunit/scripts/rm-auth-keys.sh ";
      logger.info("command shell to execute [" + command + "]");

      shellUtils.executeShell(command, configShellServer);
      String cleanCommand = server.getServerAction().cleanCommand();
      if (cleanCommand != null) {
        shellUtils.executeShell(server.getServerAction().cleanCommand(), configShellServer);
      }
    } catch (Exception e) {
      moduleGit.setStatus(Status.FAIL);
      moduleGit = moduleService.saveInDB(moduleGit);
      server.setStatus(Status.FAIL);
      server = serverService.saveInDB(server);
      logger.error("Error :  Error during update Env var of GIT " + e);
      throw new ServiceException(e.getLocalizedMessage(), e);
    }
    return application;
  }
 public void closeDown() {
   try {
     if (!isServer) clientSocket.close();
     else {
       for (ServerService s : services) s.closeDown();
     }
   } catch (IOException e) {
     e.printStackTrace();
   }
 }
 public void chat(String message) {
   message = message.substring(5);
   if (isServer) {
     for (ServerService s : services)
       s.sendMessageToClients(
           "chat " + gameData.getPlayerName() + " " + gameData.getPlayerSide() + " " + message);
     parseChatMessage(
         "chat " + gameData.getPlayerName() + " " + gameData.getPlayerSide() + " " + message);
   }
   if (!isServer)
     requestToServer.println(
         "chat " + gameData.getPlayerName() + " " + gameData.getPlayerSide() + " " + message);
 }
  public DispatcherResult killDispatcherExecution(final String execId)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("id", execId);
    params.put("xmlreq", "true");

    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_KILL_JOB_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    final Envelope envelope = validateResponse(response);

    final boolean result = envelope.isSuccessResult();
    final StringBuffer sb = envelope.successMessages();
    return new DispatcherResult() {
      public boolean isSuccessful() {
        return result;
      }

      public String getMessage() {
        return sb.toString();
      }
    };
  }
 public void elaborateShootRequest(int x, int y, String side) {
   String controllerQuery = null;
   if (side.equals("guest")) {
     controllerQuery = cont.shootAtHostSide(x, y);
   }
   if (side.equals("host")) {
     controllerQuery = cont.shootAtGuestSide(x, y);
   }
   for (ServerService s : services) {
     s.sendMessageToClients(controllerQuery);
   }
   if (controllerQuery.startsWith("water")) waterResponse(controllerQuery);
   if (controllerQuery.startsWith("hit")) hitResponse(controllerQuery);
   if (controllerQuery.startsWith("destroyed")) destroyedResponse(controllerQuery);
   if (controllerQuery.startsWith("allShipsDestroyed")) allShipsDestroyed(controllerQuery);
 }
  public DispatcherResult killDispatcherExecution(final String execId)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();

    final String rundeckApiKillJobPath =
        substitutePathVariable(RUNDECK_API_KILL_JOB_PATH, "id", execId);
    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(rundeckApiKillJobPath, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    final Envelope envelope = validateResponse(response);

    final Node result1 = envelope.doc.selectSingleNode("result");
    final String abortStatus = result1.selectSingleNode("abort/@status").getStringValue();
    final boolean result = !"failed".equals(abortStatus);
    final StringBuffer sb = envelope.successMessages();
    return new DispatcherResult() {
      public boolean isSuccessful() {
        return result;
      }

      public String getMessage() {
        return sb.toString();
      }
    };
  }
  /**
   * List the items on the dispatcher queue for a project
   *
   * @param project Project name
   * @return Collection of Strings listing the active dispatcher queue items
   * @throws CentralDispatcherException if an error occurs
   */
  public Collection<QueuedItem> listDispatcherQueue(final String project)
      throws CentralDispatcherException {
    if (null == project) {
      throw new CentralDispatcherException(
          "Unsupported operation: project is required by the RunDeck API");
    }
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("project", project);

    final WebserviceResponse response;
    try {
      response =
          serverService.makeRundeckRequest(RUNDECK_API_LIST_EXECUTIONS_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    validateResponse(response);

    ////////////////////
    // parse result list of queued items, return the collection of QueuedItems
    ///////////////////

    return parseExecutionListResult(response);
  }
  /**
   * Submit a request to the server which expects an execution id in response, and return a single
   * QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws com.dtolabs.rundeck.core.dispatcher.CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitRunRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    final Document resultDoc = response.getResultDoc();

    if (null != resultDoc.selectSingleNode("/result/execution")
        && null != resultDoc.selectSingleNode("/result/execution/@id")) {
      final Node node = resultDoc.selectSingleNode("/result/execution/@id");
      final String succeededId = node.getStringValue();
      final String name = "adhoc";
      String url = createExecutionURL(succeededId);
      url = makeAbsoluteURL(url);
      logger.info("\t[" + succeededId + "] <" + url + ">");
      return QueuedItemResultImpl.successful("Succeeded queueing " + name, succeededId, url, name);
    }
    return QueuedItemResultImpl.failed("Server response contained no success information.");
  }
  /**
   * Submit a request to the server which expects a list of execution items in the response, and
   * return a single QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws com.dtolabs.rundeck.core.dispatcher.CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitExecutionRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    final ArrayList<QueuedItem> list = parseExecutionListResult(response);
    if (null == list || list.size() < 1) {

      return QueuedItemResultImpl.failed("Server response contained no success information.");
    } else {

      final QueuedItem next = list.iterator().next();
      return QueuedItemResultImpl.successful(
          "Succeeded queueing " + next.getName(), next.getId(), next.getUrl(), next.getName());
    }
  }
  @Override
  @Transactional
  public Application stop(Application application) throws ServiceException {

    try {
      List<Server> servers = application.getServers();
      for (Server server : servers) {
        server = serverService.stopServer(server);
      }
      List<Module> modules = application.getModules();
      for (Module module : modules) {
        try {
          module = moduleService.stopModule(module);
        } catch (ServiceException e) {
          logger.error(
              "ApplicationService Error : failed to stop " + application.getName() + " : " + e);
        }
      }
      logger.info("ApplicationService : Application successfully stopped ");
    } catch (PersistenceException e) {
      throw new ServiceException(e.getLocalizedMessage(), e);
    }

    return application;
  }
  @Override
  @Transactional
  public Application start(Application application) throws ServiceException {
    try {
      User user = authentificationUtils.getAuthentificatedUser();
      logger.debug("start : Methods parameters : " + application);

      List<Module> modules = application.getModules();
      for (Module module : modules) {
        try {
          module = moduleService.startModule(module);
        } catch (ServiceException e) {
          logger.error("failed to start " + application.toString(), e);
        }
      }
      List<Server> servers = application.getServers();
      for (Server server : servers) {
        logger.info("old server ip : " + server.getContainerIP());
        server = serverService.startServer(server);
      }

      if (application.getAliases() != null && !application.getAliases().isEmpty()) {
        updateAliases(application);
      }
      logger.info("ApplicationService : Application successfully started ");
    } catch (PersistenceException e) {
      throw new ServiceException(e.getLocalizedMessage(), e);
    }
    return application;
  }
 public boolean placeShipsOnField(
     String field, String alignment, String shipName, int xStartCoordinate, int yStartCoordinate) {
   if (!gameData.shipAlreadyPlaced(shipName, alignment, xStartCoordinate, yStartCoordinate)) {
     if (!isServer) {
       requestToServer.println(
           "placeShip "
               + field
               + " "
               + alignment
               + " "
               + shipName
               + " "
               + xStartCoordinate
               + " "
               + yStartCoordinate);
       return true;
     }
     if (isServer) {
       boolean controllerQuery =
           cont.addShip(shipName, alignment, field, xStartCoordinate, yStartCoordinate);
       if (controllerQuery) {
         gameData.placeShipsOnField(alignment, shipName, xStartCoordinate, yStartCoordinate);
         for (ServerService s : services) {
           s.sendMessageToClients(
               "placeShip "
                   + field
                   + " "
                   + alignment
                   + " "
                   + shipName
                   + " "
                   + xStartCoordinate
                   + " "
                   + yStartCoordinate);
         }
         return true;
       }
     }
   }
   return false;
 }
 public void elaboratePlaceRequest(
     String field, String alignment, String shipName, int xStartCoordinate, int yStartCoordinate) {
   boolean controllerResponse = false;
   controllerResponse =
       cont.addShip(shipName, alignment, field, xStartCoordinate, yStartCoordinate);
   if (controllerResponse) {
     for (ServerService s : services) {
       s.sendMessageToClients(
           "shipSuccessfullyPlaced "
               + field
               + " "
               + alignment
               + " "
               + shipName
               + " "
               + new Integer(xStartCoordinate).toString()
               + " "
               + new Integer(yStartCoordinate).toString());
     }
   }
 }
 /**
  * If the url appears relative to an authority, i.e. it starts with "/", then convert it to be
  * absolute using the server URL (including context path) provided by the ServerService.
  *
  * @param url a context-relative url path to convert into absolute url.
  * @return absolute URL if input was a url path, otherwise returns the input string.
  */
 String makeContextAbsoluteURL(String url) {
   if (null != url && url.startsWith("/")) {
     // change relative URL into absolute using the base server URL
     try {
       final URL newUrl = new URL(serverService.getConnParams().getServerUrl() + url);
       url = newUrl.toExternalForm();
     } catch (MalformedURLException e) {
       e.printStackTrace();
     }
   }
   return url;
 }
  public Collection<IStoredJob> reallistStoredJobs(final IStoredJobsQuery iStoredJobsQuery)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    final String nameMatch = iStoredJobsQuery.getNameMatch();
    String groupMatch = iStoredJobsQuery.getGroupMatch();
    final String projectFilter = iStoredJobsQuery.getProjectFilter();
    final String idlistFilter = iStoredJobsQuery.getIdlist();

    if (null != nameMatch) {
      params.put("jobExactFilter", nameMatch);
    }
    if (null != groupMatch) {
      final Matcher matcher = Pattern.compile("^/*(.+?)/*$").matcher(groupMatch);
      if (matcher.matches()) {
        // strip leading and trailing slashes
        groupMatch = matcher.group(1);
      }
      params.put("groupPathExact", groupMatch);
    }
    if (null != projectFilter) {
      params.put("project", projectFilter);
    }
    if (null != idlistFilter) {
      params.put("idlist", idlistFilter);
    }

    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_API_JOBS_LIST_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);
    // extract job list
    final Document resultDoc = response.getResultDoc();
    final ArrayList<IStoredJob> list = new ArrayList<IStoredJob>();

    final Node jobs = resultDoc.selectSingleNode("/result/jobs");
    for (final Object job1 : jobs.selectNodes("job")) {
      final Node job = (Node) job1;
      final String id = job.selectSingleNode("@id").getStringValue();
      final String name = job.selectSingleNode("name").getStringValue();
      final String group = job.selectSingleNode("group").getStringValue();
      final String desc = job.selectSingleNode("description").getStringValue();
      final String url = createJobURL(id);
      list.add(StoredJobImpl.create(id, name, url, group, desc, projectFilter));
    }

    return list;
  }
 /**
  * Method useful for Logs and Monitoring Management
  *
  * @return
  * @throws ServiceException
  */
 @Override
 public List<Application> findAll() throws ServiceException {
   try {
     logger.debug("start findAll");
     List<Application> listApplications = applicationDAO.findAll();
     for (Application application : listApplications) {
       application.setServers(serverService.findByApp(application));
       application.setModules(
           moduleService.findByAppAndUser(application.getUser(), application.getName()));
     }
     logger.debug("ApplicationService : All Applications found ");
     return listApplications;
   } catch (PersistenceException e) {
     logger.error("Error ApplicationService : error findAll Method : " + e);
     throw new ServiceException(e.getLocalizedMessage(), e);
   }
 }
  /**
   * Report execution status
   *
   * @param project project
   * @param title execution title
   * @param status result status, either 'succeed','cancel','fail'
   * @param failedNodeCount total node count
   * @param successNodeCount count of successful nodes
   * @param tags
   * @param script script content (can be null if summary specified)
   * @param summary summary of execution (can be null if script specified)
   * @param start start date (can be null)
   * @param end end date (can be null)
   * @throws com.dtolabs.rundeck.core.dispatcher.CentralDispatcherException
   */
  public void reportExecutionStatus(
      final String project,
      final String title,
      final String status,
      final int failedNodeCount,
      final int successNodeCount,
      final String tags,
      final String script,
      final String summary,
      final Date start,
      final Date end)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("project", project);
    params.put("title", title);
    params.put("status", status);
    params.put("nodesuccesscount", Integer.toString(successNodeCount));
    params.put("nodefailcount", Integer.toString(failedNodeCount));
    if (null != tags) {
      params.put("tags", tags);
    }
    if (null != script) {
      params.put("script", script);
    }
    params.put("summary", summary);
    if (null != start) {
      params.put("start", Long.toString(start.getTime()));
    }
    if (null != end) {
      params.put("end", Long.toString(end.getTime()));
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_API_EXECUTION_REPORT, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    validateResponse(response);
  }
  public Collection<QueuedItem> listDispatcherQueue() throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("xmlreq", "true");

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_LIST_EXECUTIONS_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    validateResponse(response);

    ////////////////////
    // parse result list of queued items, return the collection of QueuedItems
    ///////////////////

    final Document resultDoc = response.getResultDoc();

    final Node node = resultDoc.selectSingleNode("/result/items");
    final List items = node.selectNodes("item");
    final ArrayList<QueuedItem> list = new ArrayList<QueuedItem>();
    if (null != items && items.size() > 0) {
      for (final Object o : items) {
        final Node node1 = (Node) o;
        final String id = node1.selectSingleNode("id").getStringValue();
        final String name = node1.selectSingleNode("name").getStringValue();
        String url = node1.selectSingleNode("url").getStringValue();
        url = makeAbsoluteURL(url);
        logger.info("\t" + ": " + name + " [" + id + "] <" + url + ">");
        list.add(QueuedItemResultImpl.createQueuedItem(id, url, name));
      }
    }

    return list;
  }
 public void run() {
   if (isServer) {
     try {
       sSocket = new ServerSocket(portNr);
     } catch (IOException e) {
       e.printStackTrace();
     }
     while (shouldRun) {
       try {
         Socket s = sSocket.accept();
         ServerService c = new ServerService(s, gameData, this, cont);
         services.add(c);
         c.start();
         clientsJoined++;
         System.out.println(
             clientsJoined + " " + cont.getHostPlayers() + " " + cont.getGuestPlayers());
         if (clientsJoined == cont.getHostPlayers() + cont.getGuestPlayers() - 1) {
           System.out.println("ready");
           ready = true;
         }
       } catch (IOException e) {
         e.printStackTrace();
       }
     }
     for (ServerService a : services) a.setShouldRun(false);
   } else {
     while (shouldRun) {
       try {
         String response = responseFromServer.readLine();
         if (response.startsWith("spl")) {
           spl = response.substring(3);
           serverResponse = true;
         }
         if (response.startsWith("opl")) {
           opponentResponse = true;
           opl = response.substring(3);
         }
         if (response.startsWith("gamechallenge")) serverGameData = response;
         if (response.equals("sidefull")) cs.playerNotAdded();
         if (response.equals("playeradded")) cs.playerAdded();
         if (response.startsWith("chat")) {
           parseChatMessage(response);
         }
         if (response.startsWith("water")) {
           waterResponse(response);
         }
         if (response.startsWith("hit")) {
           System.out.println("ship shot");
           hitResponse(response);
         }
         if (response.startsWith("shipSuccessfullyPlaced")) {
           shipPlacedResponse(response);
         }
         if (response.startsWith("destroyed")) {
           destroyedResponse(response);
         }
         if (response.equals("endGame")) {
           closeDown();
         }
         if (response.startsWith("allShipsDestroyed")) allShipsDestroyed(response);
         response = null;
       } catch (IOException e) {
         e.printStackTrace();
       }
     }
   }
 }
  @Override
  @Transactional(rollbackFor = ServiceException.class)
  public Application create(String applicationName, String login, String serverName, String tagName)
      throws ServiceException, CheckException {

    // if tagname is null, we prefix with a ":"
    if (tagName != null) {
      tagName = ":" + tagName;
    }
    if (applicationName != null) {
      applicationName = applicationName.toLowerCase();
    }

    logger.info("--CALL CREATE NEW APP--");
    Application application = new Application();

    logger.info("applicationName = " + applicationName + ", serverName = " + serverName);

    User user = authentificationUtils.getAuthentificatedUser();

    // For cloning management
    if (tagName != null) {
      application.setAClone(true);
    }

    application.setName(applicationName);
    application.setUser(user);
    application.setModules(new ArrayList<>());

    // verify if application exists already
    this.checkCreate(application, serverName);

    // todo : use a session flag
    application.setStatus(Status.PENDING);

    application = this.saveInDB(application);
    serverService.checkMaxNumberReach(application);

    String subdomain = System.getenv("CU_SUB_DOMAIN") == null ? "" : System.getenv("CU_SUB_DOMAIN");

    List<Image> imagesEnabled = imageService.findEnabledImages();
    List<String> imageNames = new ArrayList<>();
    for (Image image : imagesEnabled) {
      imageNames.add(image.getName());
    }

    if (!imageNames.contains(serverName)) {
      throw new CheckException(messageSource.getMessage("server.not.found", null, locale));
    }

    try {
      // BLOC APPLICATION
      application.setDomainName(subdomain + suffixCloudUnitIO);
      application = applicationDAO.save(application);
      application.setManagerIp(dockerManagerIp);
      application.setJvmRelease(javaVersionDefault);
      application.setRestHost(restHost);
      logger.info(application.getManagerIp());

      // BLOC SERVER
      Server server = ServerFactory.getServer(serverName);
      // We get image associated to server
      Image image = imageService.findByName(serverName);
      server.setImage(image);
      server.setApplication(application);
      server.setName(serverName);
      server = serverService.create(server, tagName);

      List<Server> servers = new ArrayList<>();
      servers.add(server);
      application.setServers(servers);

      // BLOC MODULE
      Module moduleGit = this.addGitContainer(application, tagName);
      application.getModules().add(moduleGit);
      application.setGitContainerIP(moduleGit.getContainerIP());

      // Persistence for Application model
      application = applicationDAO.save(application);

      // Copy the ssh key from the server to git container to be able to deploy war with gitpush
      // During clone processus, env variables are not updated. We must wait for a restart before
      // to copy the ssh keys for git push
      if (tagName == null) {
        this.sshCopyIDToServer(application, user);
      }

    } catch (DataAccessException e) {
      throw new ServiceException(e.getLocalizedMessage(), e);
    }

    logger.info("" + application);
    logger.info(
        "ApplicationService : Application " + application.getName() + " successfully created.");

    return application;
  }
  /**
   * Remove an application
   *
   * @param application
   * @param user
   * @return
   * @throws ServiceException
   */
  @Override
  @Transactional
  public Application remove(Application application, User user)
      throws ServiceException, CheckException {

    try {
      logger.info("Starting removing application " + application.getName());

      // Delete all modules
      List<Module> listModules = application.getModules();
      for (Module module : listModules) {
        try {
          moduleService.remove(application, user, module, false, application.getStatus());
        } catch (ServiceException | CheckException e) {
          application.setStatus(Status.FAIL);
          logger.error(
              "ApplicationService Error : failed to remove module "
                  + module.getName()
                  + " for application "
                  + application.getName()
                  + " : "
                  + e);
          e.printStackTrace();
        }
      }

      // Delete all alias
      List<String> aliases = new ArrayList<>();
      aliases.addAll(application.getAliases());
      for (String alias : aliases) {
        removeAlias(application, alias);
      }

      // Delete all servers
      List<Server> listServers = application.getServers();
      for (Server server : listServers) {
        serverService.remove(server.getName());
        if (listServers.indexOf(server) == listServers.size() - 1) {
          hipacheRedisUtils.removeRedisAppKey(application);
          applicationDAO.delete(server.getApplication());
          portUtils.releaseProxyPorts(application);
        }
      }

      logger.info("ApplicationService : Application successfully removed ");

    } catch (PersistenceException e) {
      setStatus(application, Status.FAIL);
      logger.error(
          "ApplicationService Error : failed to remove " + application.getName() + " : " + e);

      throw new ServiceException(e.getLocalizedMessage(), e);
    } catch (ServiceException e) {
      setStatus(application, Status.FAIL);
      logger.error(
          "ApplicationService Error : failed to remove application "
              + application.getName()
              + " : "
              + e);
    }
    return application;
  }
 public void sendMessageToAllClients(String message) {
   for (ServerService s : services) s.sendMessageToClients(message);
 }
  public Collection<IStoredJob> listStoredJobs(
      final IStoredJobsQuery iStoredJobsQuery,
      final OutputStream output,
      final JobDefinitionFileFormat fformat)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    final String nameMatch = iStoredJobsQuery.getNameMatch();
    String groupMatch = iStoredJobsQuery.getGroupMatch();
    final String projectFilter = iStoredJobsQuery.getProjectFilter();
    final String idlistFilter = iStoredJobsQuery.getIdlist();

    final String expectedContentType;
    if (null != fformat) {
      params.put("format", fformat.getName());
      expectedContentType = fformat == JobDefinitionFileFormat.xml ? "text/xml" : "text/yaml";
    } else {
      params.put("format", JobDefinitionFileFormat.xml.getName());
      expectedContentType = "text/xml";
    }
    if (null != nameMatch) {
      params.put("jobFilter", nameMatch);
    }
    if (null != groupMatch) {
      final Matcher matcher = Pattern.compile("^/*(.+?)/*$").matcher(groupMatch);
      if (matcher.matches()) {
        // strip leading and trailing slashes
        groupMatch = matcher.group(1);
      }
      params.put("groupPath", groupMatch);
    }
    if (null != projectFilter) {
      params.put("project", projectFilter);
    }
    if (null != idlistFilter) {
      params.put("idlist", idlistFilter);
    }

    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response =
          serverService.makeRundeckRequest(
              RUNDECK_API_JOBS_EXPORT_PATH, params, null, null, expectedContentType);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    checkErrorResponse(response);
    // if xml, do local validation and listing
    if (null == fformat || fformat == JobDefinitionFileFormat.xml) {
      validateJobsResponse(response);

      ////////////////////
      // parse result list of queued items, return the collection of QueuedItems
      ///////////////////

      final Document resultDoc = response.getResultDoc();

      final Node node = resultDoc.selectSingleNode("/joblist");
      final ArrayList<IStoredJob> list = new ArrayList<IStoredJob>();
      if (null == node) {
        return list;
      }
      final List items = node.selectNodes("job");
      if (null != items && items.size() > 0) {
        for (final Object o : items) {
          final Node node1 = (Node) o;
          final Node uuid = node1.selectSingleNode("uuid");
          final Node id1 = node1.selectSingleNode("id");
          final String id = null != uuid ? uuid.getStringValue() : id1.getStringValue();
          final String name = node1.selectSingleNode("name").getStringValue();
          final String url = createJobURL(id);

          final Node gnode = node1.selectSingleNode("group");
          final String group = null != gnode ? gnode.getStringValue() : null;
          final String description = node1.selectSingleNode("description").getStringValue();
          list.add(StoredJobImpl.create(id, name, url, group, description, projectFilter));
        }
      }

      if (null != output) {
        // write output doc to the outputstream
        final OutputFormat format = OutputFormat.createPrettyPrint();
        try {
          final XMLWriter writer = new XMLWriter(output, format);
          writer.write(resultDoc);
          writer.flush();
        } catch (IOException e) {
          throw new CentralDispatcherServerRequestException(e);
        }
      }
      return list;
    } else if (fformat == JobDefinitionFileFormat.yaml) {
      // do rought yaml parse
      final Collection<Map> mapCollection = validateJobsResponseYAML(response);
      final ArrayList<IStoredJob> list = new ArrayList<IStoredJob>();

      if (null == mapCollection || mapCollection.size() < 1) {
        return list;
      }
      for (final Map map : mapCollection) {
        final Object uuidobj = map.get("uuid");
        final Object idobj = map.get("id");
        final String id = null != uuidobj ? uuidobj.toString() : idobj.toString();
        final String name = (String) map.get("name");
        final String group = map.containsKey("group") ? (String) map.get("group") : null;
        final String desc = map.containsKey("description") ? (String) map.get("description") : "";
        final String url = createJobURL(id);
        list.add(StoredJobImpl.create(id, name, url, group, desc, projectFilter));
      }

      if (null != output) {
        // write output doc to the outputstream
        try {
          final Writer writer = new OutputStreamWriter(output);
          writer.write(response.getResults());
          writer.flush();
        } catch (IOException e) {
          throw new CentralDispatcherServerRequestException(e);
        }
      }
      return list;
    }
    return null;
  }
  public Collection<IStoredJobLoadResult> loadJobs(ILoadJobsRequest iLoadJobsRequest, File input)
      throws CentralDispatcherException {
    final HashMap params = new HashMap();
    params.put("dupeOption", iLoadJobsRequest.getDuplicateOption().toString());
    params.put("xmlreq", "true");

    /*
     * Send the request bean and the file as a multipart request.
     */

    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(RUNDECK_JOBS_UPLOAD, params, input, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    ////////////////////
    // parse result list of queued items, return the collection of QueuedItems
    ///////////////////

    final Document result = response.getResultDoc();

    final int succeeded;
    final int failed;
    final int skipped;
    Node node = result.selectSingleNode("/result/succeeded/@count");
    if (null != node) {
      succeeded = Integer.parseInt(node.getStringValue());
    } else {
      succeeded = -1;
    }
    node = result.selectSingleNode("/result/failed/@count");
    if (null != node) {
      failed = Integer.parseInt(node.getStringValue());
    } else {
      failed = -1;
    }
    node = result.selectSingleNode("/result/skipped/@count");
    if (null != node) {
      skipped = Integer.parseInt(node.getStringValue());
    } else {
      skipped = -1;
    }
    ArrayList<IStoredJobLoadResult> resultList = new ArrayList<IStoredJobLoadResult>();
    if (succeeded > 0) {
      logger.debug("Succeeded creating/updating " + succeeded + " Jobs:");
      final List nodes = result.selectNodes("/result/succeeded/job");
      for (final Object node2 : nodes) {
        final Node node1 = (Node) node2;
        final IStoredJobLoadResult storedJobLoadResult =
            parseStoredJobResult(node1, true, false, "Succeeded");
        resultList.add(storedJobLoadResult);
      }
    }
    if (failed > 0) {
      logger.debug("Failed to add " + failed + " Jobs:");
      final List nodes = result.selectNodes("/result/failed/job");
      for (final Object node2 : nodes) {
        final Node node1 = (Node) node2;
        final String error =
            null != node1.selectSingleNode("error")
                ? node1.selectSingleNode("error").getStringValue()
                : "Failed";
        final IStoredJobLoadResult storedJobLoadResult =
            parseStoredJobResult(node1, false, false, error);

        resultList.add(storedJobLoadResult);
      }
    }
    if (skipped > 0) {
      logger.debug("Skipped " + skipped + " Jobs:");
      final List nodes = result.selectNodes("/result/skipped/job");
      for (final Object node2 : nodes) {
        final Node node1 = (Node) node2;

        final String error =
            null != node1.selectSingleNode("error")
                ? node1.selectSingleNode("error").getStringValue()
                : "Skipped";
        final IStoredJobLoadResult storedJobLoadResult =
            parseStoredJobResult(node1, true, true, error);
        resultList.add(storedJobLoadResult);
      }
    }
    return resultList;
  }
  public Collection<IStoredJob> listStoredJobs(
      final IStoredJobsQuery iStoredJobsQuery, final OutputStream output)
      throws CentralDispatcherException {
    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("xmlreq", "true");
    final String nameMatch = iStoredJobsQuery.getNameMatch();
    String groupMatch = iStoredJobsQuery.getGroupMatch();
    final String projectFilter = iStoredJobsQuery.getProjectFilter();
    final String commandFilter = iStoredJobsQuery.getCommand();
    final String idlistFilter = iStoredJobsQuery.getIdlist();
    final String typeFilter = iStoredJobsQuery.getType();
    final String resourceFilter = iStoredJobsQuery.getResource();

    if (null != nameMatch) {
      params.put("jobFilter", nameMatch);
    }
    if (null != groupMatch) {
      final Matcher matcher = Pattern.compile("^/*(.+?)/*$").matcher(groupMatch);
      if (matcher.matches()) {
        // strip leading and trailing slashes
        groupMatch = matcher.group(1);
      }
      params.put("groupPath", groupMatch);
    }
    if (null != projectFilter) {
      params.put("projFilter", projectFilter);
    }
    if (null != resourceFilter) {
      params.put("objFilter", resourceFilter);
    }
    if (null != typeFilter) {
      params.put("typeFilter", typeFilter);
    }
    if (null != commandFilter) {
      params.put("cmdFilter", commandFilter);
    }
    if (null != idlistFilter) {
      params.put("idlist", idlistFilter);
    }

    params.put("xmlreq", "true");

    // 2. send request via ServerService
    final WebserviceResponse response;
    try {
      response =
          serverService.makeRundeckRequest(RUNDECK_LIST_STORED_JOBS_PATH, params, null, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }

    validateJobsResponse(response);

    ////////////////////
    // parse result list of queued items, return the collection of QueuedItems
    ///////////////////

    final Document resultDoc = response.getResultDoc();

    final Node node = resultDoc.selectSingleNode("/joblist");
    final ArrayList<IStoredJob> list = new ArrayList<IStoredJob>();
    if (null == node) {
      return list;
    }
    final List items = node.selectNodes("job");
    if (null != items && items.size() > 0) {
      for (final Object o : items) {
        final Node node1 = (Node) o;
        final String id = node1.selectSingleNode("id").getStringValue();
        final String name = node1.selectSingleNode("name").getStringValue();
        final String url = createJobURL(id);

        final Node gnode = node1.selectSingleNode("group");
        final String group = null != gnode ? gnode.getStringValue() : null;
        final String description = node1.selectSingleNode("description").getStringValue();
        list.add(StoredJobImpl.create(id, name, url, group, description));
      }
    }

    if (null != output) {
      // write output doc to the outputstream
      final OutputFormat format = OutputFormat.createPrettyPrint();
      try {
        final XMLWriter writer = new XMLWriter(output, format);
        writer.write(resultDoc);
        writer.flush();
      } catch (IOException e) {
        throw new CentralDispatcherServerRequestException(e);
      }
    }

    return list;
  }
  /**
   * Lancer par signal de NoPublicController quand le processus sshd est (re)démarré dans container
   * serveur et git, pour mettre à jour la nouvelle IP du serveur
   */
  @Override
  public Application sshCopyIDToServer(Application application, User user) throws ServiceException {
    String command = null;
    Map<String, String> configShell = new HashMap<>();

    Module moduleGit = moduleService.findGitModule(user.getLogin(), application);

    if (logger.isDebugEnabled()) {
      logger.debug("--ssh Copy ID To Server--");
      logger.debug("ssh port : " + moduleGit.getSshPort());
      logger.debug("manager ip : " + application.getManagerIp());
    }

    for (Server server : application.getServers()) {
      configShell.put("password", server.getApplication().getUser().getPassword());
      configShell.put("port", moduleGit.getSshPort());
      configShell.put("dockerManagerAddress", application.getManagerIp());
      configShell.put("userLogin", server.getApplication().getUser().getLogin());

      try {
        int counter = 0;
        while (!server.getStatus().equals(Status.START)
            || !moduleGit.getStatus().equals(Status.START)) {
          if (counter == 100) {
            break;
          }
          Thread.sleep(1000);
          logger.info(" wait git and server ssh processus start");
          logger.info(
              "STATUS = server : " + server.getStatus() + " - module : " + moduleGit.getStatus());

          moduleGit = moduleService.findById(moduleGit.getId());
          server = serverService.findById(server.getId());
          counter++;
        }

        // To permit ssh access on server from git container
        command =
            "expect /cloudunit/scripts/ssh-copy-id-expect.sh "
                + moduleGit.getApplication().getUser().getPassword();
        logger.info("command shell to execute [" + command + "]");

        shellUtils.executeShell(command, configShell);

      } catch (Exception e) {
        moduleGit.setStatus(Status.FAIL);
        moduleGit = moduleService.saveInDB(moduleGit);
        server.setStatus(Status.FAIL);
        server = serverService.saveInDB(server);
        logger.error("Error :  Error during permit git to access to server " + e);

        throw new ServiceException(e.getLocalizedMessage(), e);
      }
    }

    try {
      moduleGit = moduleService.update(moduleGit);

      application.getModules().add(moduleGit);
      application.setGitContainerIP(moduleGit.getContainerIP());

    } catch (ServiceException e) {
      moduleGit.setStatus(Status.FAIL);
      moduleService.saveInDB(moduleGit);
      logger.error("Error :  Error during persist git module " + e);
      throw new ServiceException(e.getLocalizedMessage(), e);
    }
    logger.info(
        "ApplicationService : Application " + application.getName() + " successfully created.");
    return application;
  }
  /**
   * Submit a request to the server which expects a list of queued item results in the response, and
   * return a single QueuedItemResult parsed from the response.
   *
   * @param tempxml xml temp file (or null)
   * @param otherparams parameters for the request
   * @param requestPath
   * @return a single QueuedItemResult
   * @throws CentralDispatcherException if an error occurs
   */
  private QueuedItemResult submitQueueRequest(
      final File tempxml, final HashMap<String, String> otherparams, final String requestPath)
      throws CentralDispatcherException {

    final HashMap<String, String> params = new HashMap<String, String>();
    params.put("xmlreq", "true");
    if (null != otherparams) {
      params.putAll(otherparams);
    }

    final WebserviceResponse response;
    try {
      response = serverService.makeRundeckRequest(requestPath, params, tempxml, null);
    } catch (MalformedURLException e) {
      throw new CentralDispatcherServerRequestException("Failed to make request", e);
    }
    validateResponse(response);

    ////////////////////
    // parse result list of execution responses.  this implementation handles multiple responses,
    // but only
    // returns a single QueuedItem (the first one found).
    // TODO: update to return multiple QueuedItems when multiple job queue requests are supported
    ///////////////////

    final Document resultDoc = response.getResultDoc();

    final int succeeded;
    final int failed;

    Node node = resultDoc.selectSingleNode("/result/succeeded/@count");
    if (null != node) {
      succeeded = Integer.parseInt(node.getStringValue());
    } else {
      succeeded = -1;
    }
    node = resultDoc.selectSingleNode("/result/failed/@count");
    if (null != node) {
      failed = Integer.parseInt(node.getStringValue());
    } else {
      failed = -1;
    }
    final String succeededId;
    if (succeeded > 0) {
      logger.info("Succeeded queueing " + succeeded + " Job" + (succeeded > 1 ? "s" : "") + ":");
      final List nodes = resultDoc.selectNodes("/result/succeeded/execution");
      final Node node1 = (Node) nodes.iterator().next();
      final String index = node1.selectSingleNode("@index").getStringValue();
      final String id = node1.selectSingleNode("id").getStringValue();
      succeededId = id;
      final String name = node1.selectSingleNode("name").getStringValue();
      String url = node1.selectSingleNode("url").getStringValue();
      url = makeAbsoluteURL(url);
      logger.info("\t" + index + ": " + name + " [" + id + "] <" + url + ">");
      return QueuedItemResultImpl.successful("Succeeded queueing " + name, succeededId, url, name);
    }
    if (failed > 0) {
      final String s1 = "Failed to queue " + failed + " Job" + (failed > 1 ? "s" : "") + ":";
      logger.error(s1);
      final List nodes = resultDoc.selectNodes("/result/failed/execution");
      final Node node1 = (Node) nodes.iterator().next();
      final String index = node1.selectSingleNode("@index").getStringValue();
      final String id =
          null != node1.selectSingleNode("id")
              ? node1.selectSingleNode("id").getStringValue()
              : null;
      String url =
          null != node1.selectSingleNode("url")
              ? node1.selectSingleNode("url").getStringValue()
              : null;
      url = makeAbsoluteURL(url);
      final String error =
          null != node1.selectSingleNode("error")
              ? node1.selectSingleNode("error").getStringValue()
              : null;
      final String message =
          null != node1.selectSingleNode("message")
              ? node1.selectSingleNode("message").getStringValue()
              : null;
      final String errmsg =
          error
              + (null != id ? " [" + id + "] <" + url + ">" : "")
              + (null != message ? " : " + message : "");
      final String s2 = index + ": " + errmsg;
      logger.error(s2);
      return QueuedItemResultImpl.failed(errmsg);
    }
    return QueuedItemResultImpl.failed("Server response contained no success information.");
  }