/**
   * Downloads a Bundle file for a given bundle id.
   *
   * @param request HttpRequest
   * @param response HttpResponse
   * @throws IOException If fails sending back to the user response information
   */
  public void downloadBundle(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    try {
      if (!APILocator.getLayoutAPI()
          .doesUserHaveAccessToPortlet("EXT_CONTENT_PUBLISHING_TOOL", getUser())) {
        response.sendError(401);
        return;
      }
    } catch (DotDataException e1) {
      Logger.error(RemotePublishAjaxAction.class, e1.getMessage(), e1);
      response.sendError(401);
      return;
    }
    Map<String, String> map = getURIParams();
    response.setContentType("application/x-tgz");

    String bid = map.get("bid");

    PublisherConfig config = new PublisherConfig();
    config.setId(bid);
    File bundleRoot = BundlerUtil.getBundleRoot(config);

    ArrayList<File> list = new ArrayList<File>(1);
    list.add(bundleRoot);
    File bundle =
        new File(bundleRoot + File.separator + ".." + File.separator + config.getId() + ".tar.gz");
    if (!bundle.exists()) {
      response.sendError(500, "No Bundle Found");
      return;
    }

    response.setHeader("Content-Disposition", "attachment; filename=" + config.getId() + ".tar.gz");
    BufferedInputStream in = null;
    try {
      in = new BufferedInputStream(new FileInputStream(bundle));
      byte[] buf = new byte[4096];
      int len;

      while ((len = in.read(buf, 0, buf.length)) != -1) {
        response.getOutputStream().write(buf, 0, len);
      }
    } catch (Exception e) {
      Logger.warn(this.getClass(), "Error Downloading Bundle.", e);
    } finally {
      try {
        in.close();
      } catch (Exception ex) {
        Logger.warn(this.getClass(), "Error Closing Stream.", ex);
      }
    }
    return;
  }
  /**
   * Generates an Unpublish bundle for a given bundle id operation (publish/unpublish)
   *
   * @param bundleId The Bundle id of the Bundle we want to generate
   * @param operation Download for publish or un-publish
   * @return The generated requested Bundle file
   * @throws DotPublisherException If fails retrieving the Bundle contents
   * @throws DotDataException If fails finding the system user
   * @throws DotPublishingException If fails initializing the Publisher
   * @throws IllegalAccessException If fails creating new Bundlers instances
   * @throws InstantiationException If fails creating new Bundlers instances
   * @throws DotBundleException If fails generating the Bundle
   * @throws IOException If fails compressing the all the Bundle contents into the final Bundle file
   */
  @SuppressWarnings("unchecked")
  private Map<String, Object> generateBundle(
      String bundleId, PushPublisherConfig.Operation operation)
      throws DotPublisherException, DotDataException, DotPublishingException,
          IllegalAccessException, InstantiationException, DotBundleException, IOException {

    PushPublisherConfig pconf = new PushPublisherConfig();
    PublisherAPI pubAPI = PublisherAPI.getInstance();

    List<PublishQueueElement> tempBundleContents = pubAPI.getQueueElementsByBundleId(bundleId);
    List<PublishQueueElement> assetsToPublish =
        new ArrayList<PublishQueueElement>(); // all assets but contentlets

    for (PublishQueueElement c : tempBundleContents) {
      if (!c.getType().equals("contentlet")) {
        assetsToPublish.add(c);
      }
    }

    pconf.setDownloading(true);
    pconf.setOperation(operation);

    // all types of assets in the queue but contentlets are passed here, which are passed through
    // lucene queries
    pconf.setAssets(assetsToPublish);
    // Queries creation
    pconf.setLuceneQueries(PublisherUtil.prepareQueries(tempBundleContents));
    pconf.setId(bundleId);
    pconf.setUser(APILocator.getUserAPI().getSystemUser());

    // BUNDLERS

    List<Class<IBundler>> bundlers = new ArrayList<Class<IBundler>>();
    List<IBundler> confBundlers = new ArrayList<IBundler>();

    Publisher publisher = new PushPublisher();
    publisher.init(pconf);
    // Add the bundles for this publisher
    for (Class clazz : publisher.getBundlers()) {
      if (!bundlers.contains(clazz)) {
        bundlers.add(clazz);
      }
    }

    // Create a new bundle id for this generated bundle
    String newBundleId = UUID.randomUUID().toString();
    pconf.setId(newBundleId);
    File bundleRoot = BundlerUtil.getBundleRoot(pconf);

    // Run bundlers
    BundlerUtil.writeBundleXML(pconf);
    for (Class<IBundler> c : bundlers) {

      IBundler bundler = c.newInstance();
      confBundlers.add(bundler);
      bundler.setConfig(pconf);
      BundlerStatus bundlerStatus = new BundlerStatus(bundler.getClass().getName());
      // Generate the bundler
      bundler.generate(bundleRoot, bundlerStatus);
    }

    pconf.setBundlers(confBundlers);

    // Compressing bundle
    ArrayList<File> list = new ArrayList<File>();
    list.add(bundleRoot);
    File bundle =
        new File(bundleRoot + File.separator + ".." + File.separator + pconf.getId() + ".tar.gz");

    Map<String, Object> bundleData = new HashMap<String, Object>();
    bundleData.put("id", newBundleId);
    bundleData.put("file", PushUtils.compressFiles(list, bundle, bundleRoot.getAbsolutePath()));
    return bundleData;
  }