/**
   * All the BND magic happens here.
   *
   * @param jarInputStream On what to operate.
   * @param instructions BND instructions from user API
   * @param symbolicName Mandatory Header. In case user does not set it.
   * @return Bundle Jar Stream
   * @throws Exception Problems go here
   */
  private InputStream createBundle(
      InputStream jarInputStream, Properties instructions, String symbolicName) throws Exception {
    NullArgumentException.validateNotNull(jarInputStream, "Jar URL");
    NullArgumentException.validateNotNull(instructions, "Instructions");
    NullArgumentException.validateNotEmpty(symbolicName, "Jar info");

    final Jar jar = new Jar("dot", sink(jarInputStream));

    final Properties properties = new Properties();
    properties.putAll(instructions);

    final Analyzer analyzer = new Analyzer();
    analyzer.setJar(jar);
    analyzer.setProperties(properties);

    // throw away already existing headers that we overwrite:

    analyzer.mergeManifest(jar.getManifest());

    checkMandatoryProperties(analyzer, jar, symbolicName);
    Manifest manifest = analyzer.calcManifest();
    jar.setManifest(manifest);

    return createInputStream(jar);
  }
  /** Created a JAR that is a bundle and that contains its dependencies */
  @Override
  public Jar executable() throws Exception {
    Collection<String> bsns = getProject().getBsns();
    if (bsns.size() != 1)
      throw new IllegalArgumentException(
          "Can only handle a single bsn for a run configuration " + bsns);
    String bsn = bsns.iterator().next();

    Jar jar = new Jar(bsn);
    String path = "aQute/remote/embedded/activator/EmbeddedActivator.class";
    URLResource resource = new URLResource(getClass().getClassLoader().getResource(path));
    jar.putResource("aQute/remote/embedded/activator/EmbeddedActivator.class", resource);

    Collection<Container> rb = getProject().getRunbundles();
    rb = Container.flatten(rb);
    Attrs attrs = new Attrs();

    for (Container c : rb) {
      if (c.getError() != null) {
        getProject().error("invalid runbundle %s", c);
      } else {
        File f = c.getFile();
        String tbsn = c.getBundleSymbolicName();
        String version = c.getVersion();
        if (version == null || !Version.isVersion(version))
          getProject()
              .warning("The version of embedded bundle %s does not have a proper version", c);

        jar.putResource("jar/" + c.getBundleSymbolicName() + ".jar", new FileResource(f));

        attrs.put(tbsn, version);
      }
    }

    Analyzer a = new Analyzer(getProject());
    a.setJar(jar);

    a.setBundleActivator(EmbeddedActivator.class.getName());
    a.setProperty("Bnd-Embedded", attrs.toString().replace(';', ','));
    Manifest manifest = a.calcManifest();
    jar.setManifest(manifest);
    getProject().getInfo(a);
    return jar;
  }
  private Manifest _calculateManifest(URL url, Manifest manifest) {
    Analyzer analyzer = new Analyzer();

    Jar jar = null;

    try {
      URLConnection urlConnection = url.openConnection();

      String fileName = url.getFile();

      if (urlConnection instanceof JarURLConnection) {
        JarURLConnection jarURLConnection = (JarURLConnection) urlConnection;

        URL jarFileURL = jarURLConnection.getJarFileURL();

        fileName = jarFileURL.getFile();
      }

      File file = new File(fileName);

      if (!file.exists() || !file.canRead()) {
        return manifest;
      }

      fileName = file.getName();

      analyzer.setJar(new Jar(fileName, file));

      jar = analyzer.getJar();

      String bundleSymbolicName = fileName;

      Matcher matcher = _bundleSymbolicNamePattern.matcher(bundleSymbolicName);

      if (matcher.matches()) {
        bundleSymbolicName = matcher.group(1);
      }

      analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, bundleSymbolicName);

      String exportPackage = _calculateExportPackage(jar);

      analyzer.setProperty(Analyzer.EXPORT_PACKAGE, exportPackage);

      analyzer.mergeManifest(manifest);

      String bundleVersion = analyzer.getProperty(Analyzer.BUNDLE_VERSION);

      if (bundleVersion != null) {
        bundleVersion = Builder.cleanupVersion(bundleVersion);

        analyzer.setProperty(Analyzer.BUNDLE_VERSION, bundleVersion);
      }

      return analyzer.calcManifest();
    } catch (Exception e) {
      _log.error(e, e);

      return manifest;
    } finally {
      if (jar != null) {
        jar.close();
      }

      analyzer.close();
    }
  }