/** Downloads the bundles, features and FABs for this profile. */
  public void downloadProfile(Profile profile) throws Exception {
    if (!profile.isOverlay()) {
      profile = profile.getOverlay();
    }

    DownloadManager downloadManager =
        DownloadManagers.createDownloadManager(fabricService, executorService);

    Set<String> bundles = new LinkedHashSet<String>();
    Set<Feature> features = new LinkedHashSet<Feature>();
    addMavenBundles(bundles, profile.getBundles());
    addMavenBundles(bundles, profile.getFabs());
    AgentUtils.addFeatures(features, fabricService, downloadManager, profile);

    Map<String, File> files =
        AgentUtils.downloadBundles(
            downloadManager, features, bundles, Collections.<String>emptySet());
    Set<Map.Entry<String, File>> entries = files.entrySet();
    for (Map.Entry<String, File> entry : entries) {
      String name = entry.getKey();
      File file = entry.getValue();
      if (processedFiles.add(file)) {
        String fileName = file.getName();
        String mvnCoords = getMavenCoords(name);

        File destFile;
        if (mvnCoords != null) {
          Parser parser = new Parser(mvnCoords);
          destFile = new File(target, parser.getArtifactPath());
        } else {
          destFile = new File(target, fileName);
        }
        if (force || !destFile.exists()) {
          LOG.info("Copying file " + name + " to :  " + destFile.getCanonicalPath());
          Files.copy(file, destFile);
        }
      }
    }
  }
  public String generateContainerImage(
      FabricService fabric,
      Container container,
      List<Profile> profileList,
      Docker docker,
      JavaContainerOptions options,
      JavaContainerConfig javaConfig,
      CreateDockerContainerOptions containerOptions,
      ExecutorService downloadExecutor,
      Map<String, String> envVars)
      throws Exception {
    String libDirAndSeparator = ensureEndsWithFileSeparator(options.getJavaLibraryPath());
    String homeDirAndSeparator = ensureEndsWithFileSeparator(options.getHomePath());
    Map<String, Parser> artifacts =
        JavaContainers.getJavaContainerArtifacts(fabric, profileList, downloadExecutor);

    URI mavenRepoURI = fabric.getMavenRepoURI();
    String repoTextPrefix = mavenRepoURI.toString();
    int idx = repoTextPrefix.indexOf("://");
    if (idx > 0) {
      repoTextPrefix = repoTextPrefix.substring(idx + 3);
    }
    repoTextPrefix =
        "http://"
            + fabric.getZooKeeperUser()
            + ":"
            + fabric.getZookeeperPassword()
            + "@"
            + repoTextPrefix;

    String baseImage = options.getBaseImage();
    String tag = options.getNewImageTag();

    DockerFileBuilder dockerFile = DockerFileBuilder.from(baseImage);

    Set<Map.Entry<String, Parser>> entries = artifacts.entrySet();
    for (Map.Entry<String, Parser> entry : entries) {
      Parser parser = entry.getValue();
      String path = parser.getArtifactPath();
      String url = repoTextPrefix + path;
      String version = parser.getVersion();
      String snapshotModifier = "";
      // avoid the use of the docker cache for snapshot dependencies
      if (version != null && version.contains("SNAPSHOT")) {
        long time = new Date().getTime();
        url += "?t=" + time;
        snapshotModifier = "-" + time;
      }
      String fileName =
          parser.getArtifact() + "-" + version + snapshotModifier + "." + parser.getType();
      String filePath = libDirAndSeparator + fileName;

      dockerFile.add(url, filePath);
    }

    if (container != null) {
      List<String> bundles = new ArrayList<String>();
      for (String name : artifacts.keySet()) {
        if (name.startsWith("fab:")) {
          name = name.substring(4);
        }
        bundles.add(name);
      }
      Collections.sort(bundles);
      container.setProvisionList(bundles);
    }

    String restAPI = fabric.getRestAPI();
    if (Strings.isNotBlank(restAPI)) {
      addContainerOverlays(
          dockerFile,
          restAPI,
          fabric,
          container,
          profileList,
          docker,
          options,
          javaConfig,
          containerOptions,
          envVars,
          homeDirAndSeparator);
    } else {
      LOGGER.error("Cannot perform container overlays as there is no REST API for fabric8!");
    }

    String[] copiedEnvVars = JavaContainerEnvironmentVariables.ALL_ENV_VARS;
    for (String envVarName : copiedEnvVars) {
      String value = envVars.get(envVarName);
      if (value != null) {
        dockerFile.env(envVarName, value);
      }
    }

    String entryPoint = options.getEntryPoint();
    if (Strings.isNotBlank(entryPoint)) {
      dockerFile.cmd(entryPoint);
    }

    // TODO we should keep a cache of the Dockerfile text for each profile so we don't create it
    // each time

    // lets use the command line for now....
    File tmpFile = File.createTempFile("fabric-", ".dockerfiledir");
    tmpFile.delete();
    tmpFile.mkdirs();

    dockerFile.writeTo(new File(tmpFile, "Dockerfile"));

    // lets use the docker command line for now...
    String[] commands = new String[] {"docker", "build", "-t", tag, tmpFile.getCanonicalPath()};

    String message = join(asList(commands), " ");
    LOGGER.info("Executing commands: " + message);
    String answer = null;
    String errors = null;
    String dockerHost = resolveDockerHost();
    try {
      ProcessBuilder dockerBuild = new ProcessBuilder().command(commands);
      Map<String, String> env = dockerBuild.environment();
      env.put("DOCKER_HOST", dockerHost);
      Process process = dockerBuild.start();
      answer = parseCreatedImage(process.getInputStream(), message);
      errors = processErrors(process.getErrorStream(), message);
    } catch (Exception e) {
      LOGGER.error("Failed to execute process " + "stdin" + " for " + message + ": " + e, e);
      throw e;
    }
    if (answer == null) {
      LOGGER.error("Failed to create image " + errors);
      throw new CreateDockerImageFailedException("Failed to create docker image: " + errors);
    } else {
      LOGGER.info("Created Image: " + answer);
      return answer;
    }
  }