private void uninstall(PackageModel model, Map<String, DatabaseAction> associatedDatabases) {
    progress.status("Uninstallation process is running...", 1, LogLevel.INFO);
    String ofr = model.getName() + PackageFileType.PACKAGE_OFR.getDotExtension();
    try {
      InputStream stream =
          OPFEngine.FileStoreService.download(
              OpenFlame.FILESTORE_BASE,
              ofr,
              helper.getVersion(),
              model.getId().toString(),
              model.getDatabaseVersion().toString());
      InputStream xml = ArchiveUtils.getFile(stream, PackageFileType.PACKAGE_XML.getOfrFileName());
      IPackageDescriptor descriptor = packageInstallationService.getPackageDescriptor(xml);
      IOUtils.closeQuietly(xml);
      IOUtils.closeQuietly(stream);

      Map<String, List<String>> tablesMap =
          packageInstallationService.generateSQLTables(descriptor);
      int droppedDatabases = 0;
      for (Map.Entry<String, DatabaseAction> entry : associatedDatabases.entrySet()) {
        String lookup = entry.getKey();
        DatabaseAction databaseAction = entry.getValue();
        if (DatabaseActionType.DROP.equals(databaseAction.getAction())) {
          Database database = databaseAction.getDatabase();

          List<String> tables = tablesMap.get(lookup);
          if (tables != null && tables.size() != 0) {
            databaseManager.dropTables(database, tables);

            progress.status(
                "... database '" + database.getUrlPath() + "' dropping process is running",
                2,
                LogLevel.DEBUG);
            databaseManager.dropDatabase(database);
            progress.status(
                "database '" + database.getUrlPath() + "' dropping process has been finished",
                1,
                LogLevel.DEBUG);
            droppedDatabases++;
          }
        }
      }
      if (droppedDatabases > 0) {
        progress.status("all tables have been dropped.", 1, LogLevel.DEBUG);
      }
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
    }
  }
  @Override
  public void undeployPackage(
      PackageModel packageRN, String token, Map<String, DatabaseAction> associatedDatabases) {
    try {
      if (!associatedDatabases.isEmpty()) uninstall(packageRN, associatedDatabases);

      String name = packageRN.getUrlPath();
      if (packageRN.getUrlPath() == null || packageRN.getUrlPath().isEmpty()) name = "ROOT";

      name = name + PackageFileType.APP_WAR.getDotExtension();
      progress.status("... undeploying application: " + name, 1, LogLevel.INFO);
      requestTaskService.undeploy(packageRN.getId(), name);
      progress.status("Uninstallation process has been completed", 1, LogLevel.INFO);
    } catch (Exception e) {
      progress.status("Occurred error" + e.getMessage(), 1, LogLevel.ERROR);
      logger.error(e.getMessage(), e);
    }
  }
  @Override
  public void deployPackage(
      PackageModel packageRN,
      String token,
      InputStream stream,
      Map<String, DatabaseAction> associatedDatabases) {
    try {
      install(stream, packageRN, associatedDatabases);

      String name = packageRN.getUrlPath();
      if (packageRN.getUrlPath() == null || packageRN.getUrlPath().isEmpty()) name = "ROOT";

      name = name + PackageFileType.APP_WAR.getDotExtension();
      String file = packageRN.getName() + PackageFileType.APP_WAR.getDotExtension();
      progress.status("... deploying application: " + name, 1, LogLevel.INFO);
      requestTaskService.deploy(packageRN.getId(), name, file);
      progress.status("Archive version", 2, LogLevel.INFO);
      OPFEngine.RegistryService.archive(packageRN.getId());
      progress.status("Installation process has been completed", 2, LogLevel.INFO);
    } catch (ClientHandlerException e) {
      if (e.getCause() instanceof FileNotFoundException) {
        progress.status("Package archive has not been found", 1, LogLevel.ERROR);
      } else if (e.getCause() instanceof ConnectException) {
        progress.status("Connection refused", 1, LogLevel.ERROR);
      } else {
        progress.status("Occurred error", 1, LogLevel.ERROR);
      }
      logger.error(e.getMessage(), e);
    } catch (Exception e) {
      progress.status("Occurred error", 1, LogLevel.ERROR);
      logger.error(e.getMessage(), e);
    } finally {
      if (stream != null) {
        IOUtils.closeQuietly(stream);
      }
    }
  }
  private void install(
      InputStream stream, PackageModel packageRN, Map<String, DatabaseAction> associatedDatabases) {
    progress.status("Installation process is running...", 1, LogLevel.INFO);
    try {
      progress.status("... package archive has been downloaded", 1, LogLevel.INFO);
      progress.status("... unzipping package archive", 2, LogLevel.INFO);

      final File packageXmlUploadedFile =
          File.createTempFile(SecurityHelper.generateRandomSequence(16), null);
      final File upgradeXmlUploadedFile =
          File.createTempFile(SecurityHelper.generateRandomSequence(16), null);
      final File codeWarUploadedFile =
          File.createTempFile(SecurityHelper.generateRandomSequence(16), null);

      ArchiveUtils.unzip(
          stream,
          new ArchiveUtils.ArchiveCallback() {
            @Override
            public void callback(String dir, String name, InputStream stream) {
              try {
                if (PackageFileType.PACKAGE_XML.getOfrFileName().equals(name)) {
                  FileOutputStream packageXmlUploadFileOutputStream =
                      new FileOutputStream(packageXmlUploadedFile);
                  IOUtils.copy(stream, packageXmlUploadFileOutputStream);
                  IOUtils.closeQuietly(packageXmlUploadFileOutputStream);
                  progress.status("... extracted package xml", 1, LogLevel.DEBUG);
                } else if (PackageFileType.PACKAGE_UPGRADE.getOfrFileName().equals(name)) {
                  FileOutputStream upgradeXmlUploadFileOutputStream =
                      new FileOutputStream(upgradeXmlUploadedFile);
                  IOUtils.copy(stream, upgradeXmlUploadFileOutputStream);
                  IOUtils.closeQuietly(upgradeXmlUploadFileOutputStream);
                  progress.status("... extracted upgrade xml", 1, LogLevel.DEBUG);
                } else if (PackageFileType.APP_WAR.getOfrFileName().equals(name)) {
                  FileOutputStream codeWarFileOutputStream =
                      new FileOutputStream(codeWarUploadedFile);
                  IOUtils.copy(stream, codeWarFileOutputStream);
                  IOUtils.closeQuietly(codeWarFileOutputStream);
                  progress.status("... extracted war", 1, LogLevel.DEBUG);
                }
              } catch (IOException e) {
                logger.error(e, e);
              }
            }
          });

      Map<String, DatabaseAction> installDatabaseActionMap = new HashMap<String, DatabaseAction>();
      Map<String, DatabaseAction> upgradeDatabaseActionMap = new HashMap<String, DatabaseAction>();
      for (Map.Entry<String, DatabaseAction> entry : associatedDatabases.entrySet()) {
        String lookup = entry.getKey();
        DatabaseAction databaseAction = entry.getValue();
        if (DatabaseActionType.CREATE.equals(databaseAction.getAction())) {
          installDatabaseActionMap.put(lookup, databaseAction);
        } else if (DatabaseActionType.UPGRADE.equals(databaseAction.getAction())) {
          upgradeDatabaseActionMap.put(lookup, databaseAction);
        }
      }

      if (!installDatabaseActionMap.isEmpty()
          && (!packageXmlUploadedFile.exists() || !codeWarUploadedFile.exists())) {
        progress.status("... not all necessary files has been extracted", 1, LogLevel.ERROR);
        throw new BusinessFunctionException("Package archive is broken.");
      }
      if (!upgradeDatabaseActionMap.isEmpty()
          && (!upgradeXmlUploadedFile.exists() || !codeWarUploadedFile.exists())) {
        progress.status("... not all necessary files has been extracted", 1, LogLevel.ERROR);
        throw new BusinessFunctionException("Package archive is broken.");
      }

      Map<String, DataSource> installDataSourceMap = new HashMap<String, DataSource>();
      for (Map.Entry<String, DatabaseAction> entry : installDatabaseActionMap.entrySet()) {
        String lookup = entry.getKey();
        DatabaseAction databaseAction = entry.getValue();
        Database database = databaseAction.getDatabase();
        DataSource dataSource = databaseManager.getDataSource(database);
        progress.status(
            "... creating the "
                + database.getRdbms().name()
                + " database: "
                + database.getUrlPath(),
            1,
            LogLevel.INFO);
        boolean hasCreated = databaseManager.createDatabase(database);
        if (hasCreated) {
          progress.status("... the database has been created", 2, LogLevel.INFO);
        } else {
          progress.status("... the database has not been created", 2, LogLevel.WARN);
        }
        installDataSourceMap.put(lookup, dataSource);
      }

      if (!installDataSourceMap.isEmpty()) {
        try {
          progress.status("... creating database tables", 2, LogLevel.INFO);
          packageInstallationService.install(packageXmlUploadedFile, installDataSourceMap, null);
          progress.status("... database tables have been created", 2, LogLevel.INFO);
        } catch (Exception e) {
          progress.status("Database creating: occurred error." + e.getMessage(), 2, LogLevel.ERROR);
          throw new BusinessFunctionException(e);
        }
      }

      for (Map.Entry<String, DatabaseAction> entry : upgradeDatabaseActionMap.entrySet()) {
        String domainLookup = entry.getKey();
        DatabaseAction databaseAction = entry.getValue();
        Database database = databaseAction.getDatabase();
        DataSource dataSource = databaseManager.getDataSource(database);
        try {
          progress.status(
              "... upgrading the "
                  + database.getRdbms().name()
                  + " database: "
                  + database.getUrlPath(),
              3,
              LogLevel.INFO);
          upgradeExecutor.upgrade(upgradeXmlUploadedFile, dataSource, domainLookup);
          progress.status("... database have been upgraded", 1, LogLevel.INFO);
        } catch (Exception e) {
          progress.status(
              "Database upgrade process: occurred error" + e.getMessage(), 1, LogLevel.ERROR);
          throw new BusinessFunctionException(e);
        }
        entityStore.resetReverseEngineerMark(entry.getKey());
        relationshipStore.resetReverseEngineerMark(entry.getKey());
      }

      if (!upgradeDatabaseActionMap.isEmpty()) {
        progress.status(
            "Change database version to: " + VersionUtils.convertToVersion(packageRN.getVersion()),
            2,
            LogLevel.INFO);
        packageStore.save(packageRN, null, packageRN.getVersion(), false);
      }
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
      progress.status(
          "IOException: downloading package archive" + e.getMessage(), 1, LogLevel.ERROR);
      throw new BusinessFunctionException(e);
    }
  }