/**
   * Save fileEntry and return the the path.
   *
   * @param user current user
   * @param path path to which this will forward.
   * @param fileEntry file to be saved
   * @param targetHosts target host parameter
   * @param createLibAndResource true if lib and resources should be created as well.
   * @param validated validated the script or not, 1 is validated, 0 is not.
   * @param model model
   * @return script/scriptList
   */
  @RequestMapping(value = "/save/**", method = RequestMethod.POST)
  public String saveFileEntry(
      User user,
      @RemainedPath String path,
      FileEntry fileEntry,
      @RequestParam String targetHosts,
      @RequestParam(defaultValue = "0") String validated,
      @RequestParam(defaultValue = "false") boolean createLibAndResource,
      ModelMap model) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("validated", validated);
    if (StringUtils.isNotBlank(targetHosts)) {
      map.put("targetHosts", StringUtils.trim(targetHosts));
    }
    fileEntry.setProperties(map);

    fileEntryService.save(user, fileEntry);

    String basePath = FilenameUtils.getPath(fileEntry.getPath());
    if (createLibAndResource) {
      fileEntryService.addFolder(user, basePath, "lib", getMessages("script.commit.libfolder"));
      fileEntryService.addFolder(
          user, basePath, "resources", getMessages("script.commit.resourcefolder"));
    }
    model.clear();
    return "redirect:/script/list/" + basePath;
  }
 /**
  * Download file entry of given path.
  *
  * @param user current user
  * @param path user
  * @param response response
  */
 @RequestMapping("/download/**")
 public void download(User user, @RemainedPath String path, HttpServletResponse response) {
   FileEntry fileEntry = fileEntryService.getFileEntry(user, path);
   if (fileEntry == null) {
     LOG.error("{} requested to download not existing file entity {}", user.getUserId(), path);
     return;
   }
   response.reset();
   try {
     response.addHeader(
         "Content-Disposition",
         "attachment;filename="
             + java.net.URLEncoder.encode(FilenameUtils.getName(fileEntry.getPath()), "utf8"));
   } catch (UnsupportedEncodingException e1) {
     LOG.error(e1.getMessage(), e1);
   }
   response.setContentType("application/octet-stream; charset=UTF-8");
   response.addHeader("Content-Length", "" + fileEntry.getFileSize());
   byte[] buffer = new byte[4096];
   ByteArrayInputStream fis = null;
   OutputStream toClient = null;
   try {
     fis = new ByteArrayInputStream(fileEntry.getContentBytes());
     toClient = new BufferedOutputStream(response.getOutputStream());
     int readLength;
     while (((readLength = fis.read(buffer)) != -1)) {
       toClient.write(buffer, 0, readLength);
     }
   } catch (IOException e) {
     throw new NGrinderRuntimeException("error while download file", e);
   } finally {
     IOUtils.closeQuietly(fis);
     IOUtils.closeQuietly(toClient);
   }
 }
  /**
   * Get the details of given path.
   *
   * @param user user
   * @param path user
   * @param revision revision. -1 if HEAD
   * @param model model
   * @return script/scriptEditor
   */
  @RequestMapping("/detail/**")
  public String getDetail(
      User user,
      @RemainedPath String path,
      @RequestParam(value = "r", required = false) Long revision,
      ModelMap model) {
    FileEntry script = fileEntryService.getFileEntry(user, path, revision);
    if (script == null || !script.getFileType().isEditable()) {
      LOG.error(
          "Error while getting file detail on {}. the file does not exist or not editable", path);
      model.clear();
      return "redirect:/script/list";
    }
    model.addAttribute("file", script);
    model.addAttribute("ownerId", user.getUserId());

    return "script/scriptEditor";
  }
 /**
  * Upload files.
  *
  * @param user current user
  * @param path path
  * @param description description
  * @param file multipart file
  * @param model model
  * @return script/scriptList
  */
 @RequestMapping(value = "/upload/**", method = RequestMethod.POST)
 public String uploadFiles(
     User user,
     @RemainedPath String path,
     @RequestParam("description") String description,
     @RequestParam("uploadFile") MultipartFile file,
     ModelMap model) {
   try {
     FileEntry fileEntry = new FileEntry();
     if (fileEntry.getFileType().isEditable()) {
       fileEntry.setContent(new String(file.getBytes()));
     } else {
       fileEntry.setContentBytes(file.getBytes());
     }
     fileEntry.setDescription(description);
     fileEntry.setPath(
         FilenameUtils.separatorsToUnix(FilenameUtils.concat(path, file.getOriginalFilename())));
     fileEntryService.save(user, fileEntry);
     return "redirect:/script/list/" + path;
   } catch (IOException e) {
     LOG.error("Error while getting file content:" + e.getMessage(), e);
     throw new NGrinderRuntimeException("Error while getting file content:" + e.getMessage(), e);
   }
 }
  /*
   * (non-Javadoc)
   *
   * @see
   * org.ngrinder.script.service.IScriptValidationService#validateScript(org
   * .ngrinder.model.User, org.ngrinder.model.IFileEntry, boolean,
   * java.lang.String)
   */
  @Override
  public String validateScript(
      User user, IFileEntry scriptIEntry, boolean useScriptInSVN, String hostString) {
    FileEntry scriptEntry = cast(scriptIEntry);
    try {
      checkNotNull(scriptEntry, "scriptEntity should be not null");
      checkNotEmpty(scriptEntry.getPath(), "scriptEntity path should be provided");
      if (!useScriptInSVN) {
        checkNotEmpty(scriptEntry.getContent(), "scriptEntity content should be provided");
      }
      checkNotNull(user, "user should be provided");
      // String result = checkSyntaxErrors(scriptEntry.getContent());

      ScriptHandler handler = scriptHandlerFactory.getHandler(scriptEntry);
      String result = handler.checkSyntaxErrors(scriptEntry.getPath(), scriptEntry.getContent());
      if (result != null) {
        return result;
      }
      File scriptDirectory = config.getHome().getScriptDirectory(user);
      FileUtils.deleteDirectory(scriptDirectory);
      scriptDirectory.mkdirs();
      ProcessingResultPrintStream processingResult =
          new ProcessingResultPrintStream(new ByteArrayOutputStream());
      handler.prepareDist(
          0L, user, scriptEntry, scriptDirectory, config.getSystemProperties(), processingResult);
      if (!processingResult.isSuccess()) {
        return new String(processingResult.getLogByteArray());
      }
      File scriptFile = new File(scriptDirectory, FilenameUtils.getName(scriptEntry.getPath()));

      if (useScriptInSVN) {
        fileEntryService.writeContentTo(user, scriptEntry.getPath(), scriptDirectory);
      } else {
        FileUtils.writeStringToFile(
            scriptFile,
            scriptEntry.getContent(),
            StringUtils.defaultIfBlank(scriptEntry.getEncoding(), "UTF-8"));
      }
      int timeout =
          Math.max(
              config
                  .getSystemProperties()
                  .getPropertyInt(
                      NGrinderConstants.NGRINDER_VALIDATION_TIMEOUT,
                      LocalScriptTestDriveService.DEFAULT_TIMEOUT),
              10);
      File doValidate =
          localScriptTestDriveService.doValidate(
              scriptDirectory,
              scriptFile,
              new Condition(),
              config.isSecurityEnabled(),
              hostString,
              timeout);
      List<String> readLines = FileUtils.readLines(doValidate);
      StringBuffer output = new StringBuffer();
      String path = config.getHome().getDirectory().getAbsolutePath();
      for (String each : readLines) {
        if (!each.startsWith("*sys-package-mgr")) {
          each = each.replace(path, "${NGRINDER_HOME}");
          output.append(each).append("\n");
        }
      }
      return output.toString();
    } catch (IOException e) {
      LOG.error("Error while distributing files on {} for {}", user, scriptEntry.getPath());
      LOG.error("Error details ", e);
    }
    return StringUtils.EMPTY;
  }