/**
  * Add a package file into the cache
  *
  * @param packageFileName
  * @return The added LocalPackage or null if failed
  */
 public LocalPackage pkgAdd(String packageFileName) {
   CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_ADD);
   cmdInfo.param = packageFileName;
   LocalPackage pkg = null;
   try {
     File fileToAdd = getLocalPackageFile(packageFileName);
     if (fileToAdd == null) {
       String pkgId = getRemotePackageId(packageFileName);
       if (pkgId == null) {
         throw new PackageException(
             "Couldn't find a remote or local (relative to "
                 + "current directory or to NUXEO_HOME) "
                 + "package with name or ID "
                 + packageFileName);
       } else if (!downloadPackages(Arrays.asList(new String[] {pkgId}))) {
         throw new PackageException("Couldn't download package " + pkgId);
       }
       pkg = service.getPackage(pkgId);
       if (pkg == null) {
         throw new PackageException("Couldn't find downloaded package in cache " + pkgId);
       }
     } else {
       log.info("Adding " + packageFileName);
       pkg = service.addPackage(fileToAdd);
     }
     newPackageInfo(cmdInfo, pkg);
   } catch (Exception e) {
     cmdInfo.exitCode = 1;
     cmdInfo.newMessage(e);
   }
   return pkg;
 }
 /**
  * Add a list of packages into the cache, downloading them if needed and possible.
  *
  * @param pkgsToAdd
  * @return true if command succeeded
  * @see #pkgAdd(String)
  */
 public boolean pkgAdd(List<String> pkgsToAdd) {
   boolean cmdOk = true;
   if (pkgsToAdd == null || pkgsToAdd.isEmpty()) {
     return cmdOk;
   }
   List<String> pkgIdsToDownload = new ArrayList<String>();
   for (String pkgToAdd : pkgsToAdd) {
     CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_ADD);
     cmdInfo.param = pkgToAdd;
     try {
       File fileToAdd = getLocalPackageFile(pkgToAdd);
       if (fileToAdd == null) {
         String pkgId = getRemotePackageId(pkgToAdd);
         if (pkgId == null) {
           throw new PackageException(
               "Couldn't find a remote or local (relative to "
                   + "current directory or to NUXEO_HOME) "
                   + "package with name or ID "
                   + pkgToAdd);
         } else {
           cmdInfo.newMessage(SimpleLog.LOG_LEVEL_INFO, "Waiting for download");
           pkgIdsToDownload.add(pkgId);
         }
       } else {
         log.info("Adding " + pkgToAdd);
         LocalPackage pkg = service.addPackage(fileToAdd);
         newPackageInfo(cmdInfo, pkg);
       }
     } catch (PackageException e) {
       cmdOk = false;
       cmdInfo.exitCode = 1;
       cmdInfo.newMessage(e);
     }
   }
   cmdOk = downloadPackages(pkgIdsToDownload) && cmdOk;
   return cmdOk;
 }
 /**
  * @param packages List of packages identified by their ID, name or local filename.
  * @since 5.7
  */
 public boolean pkgShow(List<String> packages) {
   boolean cmdOk = true;
   if (packages == null || packages.isEmpty()) {
     return cmdOk;
   }
   StringBuilder sb = new StringBuilder();
   sb.append("****************************************");
   for (String pkg : packages) {
     CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_SHOW);
     cmdInfo.param = pkg;
     try {
       PackageInfo packageInfo = newPackageInfo(cmdInfo, findPackage(pkg));
       sb.append("\nPackage: " + packageInfo.id);
       sb.append("\nState: " + packageInfo.state);
       sb.append("\nVersion: " + packageInfo.version);
       sb.append("\nName: " + packageInfo.name);
       sb.append("\nType: " + packageInfo.type);
       sb.append("\nVisibility: " + packageInfo.visibility);
       if (packageInfo.state == PackageState.REMOTE
           && packageInfo.type != PackageType.STUDIO
           && packageInfo.visibility != PackageVisibility.PUBLIC
           && !LogicalInstanceIdentifier.isRegistered()) {
         sb.append(" (registration required)");
       }
       sb.append("\nTarget platforms: " + ArrayUtils.toString(packageInfo.targetPlatforms));
       appendIfNotEmpty(sb, "\nVendor: ", packageInfo.vendor);
       sb.append("\nSupports hot-reload: " + packageInfo.supportsHotReload);
       sb.append("\nSupported: " + packageInfo.supported);
       sb.append("\nProduction state: " + packageInfo.productionState);
       sb.append("\nValidation state: " + packageInfo.validationState);
       appendIfNotEmpty(sb, "\nProvides: ", packageInfo.provides);
       appendIfNotEmpty(sb, "\nDepends: ", packageInfo.dependencies);
       appendIfNotEmpty(sb, "\nConflicts: ", packageInfo.conflicts);
       appendIfNotEmpty(sb, "\nTitle: ", packageInfo.title);
       appendIfNotEmpty(sb, "\nDescription: ", packageInfo.description);
       appendIfNotEmpty(sb, "\nHomepage: ", packageInfo.homePage);
       appendIfNotEmpty(sb, "\nLicense: ", packageInfo.licenseType);
       appendIfNotEmpty(sb, "\nLicense URL: ", packageInfo.licenseUrl);
       sb.append("\n****************************************");
     } catch (PackageException e) {
       cmdOk = false;
       cmdInfo.exitCode = 1;
       cmdInfo.newMessage(e);
     }
   }
   log.info(sb.toString());
   return cmdOk;
 }
 /**
  * Install a local package.
  *
  * @param pkgId Package ID or Name
  * @return The installed LocalPackage or null if failed
  */
 public LocalPackage pkgInstall(String pkgId) {
   if (env.getProperty(LAUNCHER_CHANGED_PROPERTY, "false").equals("true")) {
     System.exit(LAUNCHER_CHANGED_EXIT_CODE);
   }
   CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_INSTALL);
   cmdInfo.param = pkgId;
   try {
     LocalPackage pkg = getLocalPackage(pkgId);
     if (pkg == null) {
       // We don't know this package, try to add it first
       pkg = pkgAdd(pkgId);
     }
     if (pkg == null) {
       // Nothing worked - can't find the package anywhere
       throw new PackageException("Package not found: " + pkgId);
     }
     pkgId = pkg.getId();
     cmdInfo.param = pkgId;
     log.info("Installing " + pkgId);
     Task installTask = pkg.getInstallTask();
     try {
       performTask(installTask);
     } catch (PackageException e) {
       installTask.rollback();
       throw e;
     }
     // Refresh state
     pkg = service.getPackage(pkgId);
     newPackageInfo(cmdInfo, pkg);
     return pkg;
   } catch (Exception e) {
     log.error(String.format("Failed to install package: %s (%s)", pkgId, e.getMessage()));
     cmdInfo.exitCode = 1;
     cmdInfo.newMessage(e);
     return null;
   }
 }
 @SuppressWarnings("unused")
 protected boolean downloadPackages(List<String> packagesToDownload) {
   if (packagesToDownload == null) {
     return true;
   }
   List<String> packagesAlreadyDownloaded = new ArrayList<String>();
   for (String pkg : packagesToDownload) {
     try {
       if (getLocalPackage(pkg) != null) {
         log.info(String.format("Package %s is already in local cache", pkg));
         packagesAlreadyDownloaded.add(pkg);
       }
     } catch (PackageException e) {
       log.error(
           String.format("Looking for package %s in local cache raised an error. Aborting.", pkg),
           e);
       return false;
     }
   }
   packagesToDownload.removeAll(packagesAlreadyDownloaded);
   if (packagesToDownload.isEmpty()) {
     return true;
   }
   List<DownloadingPackage> pkgs = new ArrayList<DownloadingPackage>();
   // Queue downloads
   log.info("Downloading " + packagesToDownload + "...");
   for (String pkg : packagesToDownload) {
     try {
       pkgs.add(getPackageManager().download(pkg));
     } catch (Exception e) {
       log.error("Cannot download packages", e);
       return false;
     }
   }
   // Check progress
   boolean downloadOk = true;
   long startTime = new Date().getTime();
   long deltaTime = 0;
   do {
     List<DownloadingPackage> pkgsCompleted = new ArrayList<DownloadingPackage>();
     for (DownloadingPackage pkg : pkgs) {
       if (pkg.isCompleted()) {
         pkgsCompleted.add(pkg);
         CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_DOWNLOAD);
         cmdInfo.param = pkg.getId();
         // Digest check not correctly implemented
         if (false && !pkg.isDigestOk()) {
           downloadOk = false;
           cmdInfo.exitCode = 1;
           cmdInfo.newMessage(
               SimpleLog.LOG_LEVEL_ERROR, "Wrong digest for package " + pkg.getName());
         } else if (pkg.getState() == PackageState.DOWNLOADED.getValue()) {
           cmdInfo.newMessage(SimpleLog.LOG_LEVEL_DEBUG, "Downloaded " + pkg);
         } else {
           downloadOk = false;
           cmdInfo.exitCode = 1;
           cmdInfo.newMessage(
               SimpleLog.LOG_LEVEL_ERROR,
               String.format("Download failed for %s. %s", pkg, pkg.getErrorMessage()));
         }
       }
     }
     pkgs.removeAll(pkgsCompleted);
     deltaTime = (new Date().getTime() - startTime) / 1000;
   } while (deltaTime < PACKAGES_DOWNLOAD_TIMEOUT_SECONDS && pkgs.size() > 0);
   // Timeout (not everything get downloaded)?
   if (pkgs.size() > 0) {
     downloadOk = false;
     log.error("Timeout while trying to download packages");
     for (DownloadingPackage pkg : pkgs) {
       CommandInfo cmdInfo = cset.newCommandInfo(CommandInfo.CMD_ADD);
       cmdInfo.param = pkg.getId();
       cmdInfo.exitCode = 1;
       cmdInfo.newMessage(SimpleLog.LOG_LEVEL_ERROR, "Download timeout for " + pkg);
     }
   }
   return downloadOk;
 }