예제 #1
0
  /** Check if the getSubBuilders properly predicts the output. */
  public static void testSubBuilders() throws Exception {
    Workspace ws = Workspace.getWorkspace(new File("test/ws"));
    Project project = ws.getProject("p4-sub");

    Collection<? extends Builder> bs = project.getSubBuilders();
    assertNotNull(bs);
    assertEquals(3, bs.size());
    Set<String> names = new HashSet<String>();
    for (Builder b : bs) {
      names.add(b.getBsn());
    }
    assertTrue(names.contains("p4-sub.a"));
    assertTrue(names.contains("p4-sub.b"));
    assertTrue(names.contains("p4-sub.c"));

    File[] files = project.build();
    assertTrue(project.check());

    System.err.println(Processor.join(project.getErrors(), "\n"));
    System.err.println(Processor.join(project.getWarnings(), "\n"));
    assertEquals(0, project.getErrors().size());
    assertEquals(0, project.getWarnings().size());
    assertNotNull(files);
    assertEquals(3, files.length);
    for (File file : files) {
      Jar jar = new Jar(file);
      Manifest m = jar.getManifest();
      assertTrue(names.contains(m.getMainAttributes().getValue("Bundle-SymbolicName")));
    }
  }
예제 #2
0
  /**
   * Read the version information from a file with a given file name. The file must be a jar
   * manifest file and all its entries are searched for package names and their specification
   * version information. All information is collected in a map for later lookup of package names
   * and their versions.
   *
   * @param versionFileName name of the jar file containing version information
   */
  public static String readVersionFromFile(String applicationName, String versionFileName) {
    try {
      FileInputStream fileInput = new FileInputStream(versionFileName);
      Manifest manifest = new Manifest();
      manifest.read(fileInput);

      Map entries = manifest.getEntries();
      // Now write out the pre-entry attributes
      Iterator entryIterator = entries.entrySet().iterator();
      while (entryIterator.hasNext()) {
        Map.Entry currentEntry = (Map.Entry) entryIterator.next();
        String packageName = currentEntry.getKey().toString();
        packageName = normalizePackageName(packageName);
        Attributes attributes = (Attributes) currentEntry.getValue();
        String packageSpecVersion = attributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
        packageSpecVersion = extractVersionInfo(packageSpecVersion);
        return packageSpecVersion;
      }
    } catch (IOException exception) {
      exception.printStackTrace();
    }

    // no version found
    return null;
  }
예제 #3
0
  public static boolean extractJarDir(String jarfile, String outfile) throws Exception {
    long filesize = new File(jarfile).length();
    JarInputStream jar = new JarInputStream(new FileInputStream(jarfile));
    // while (true) {
    //	JarEntry jarentry = (JarEntry)jar.getNextJarEntry();
    //	if (jarentry==null) break;
    //	String maindir = jarentry.getName();
    //	// get rid of "./" and "/" prefix
    //	if (maindir.startsWith("."))
    //		maindir = maindir.substring(1);
    //	if (maindir.startsWith(File.separator))
    //		maindir = maindir.substring(1);
    //	// Find manifest
    //	System.out.println(maindir);
    //	if (maindir.equals("META-INF/MANIFEST.MF")) {
    //		java.io.InputStream ins = jar;

    java.io.FileOutputStream outs = new java.io.FileOutputStream(outfile);
    Manifest man = jar.getManifest();
    if (man == null) return false;
    man.write(outs);
    byte[] buf = ("MIDlet-Jar-Size: " + filesize).getBytes();
    outs.write(buf, 0, buf.length);
    outs.close();
    //		// copy buffered (is a lot faster than one byte at a time)
    //		byte[] buf = new byte[8192];
    //		int total_bytes=0;
    //		while (true) {
    //			//outs.write(ins.read());
    //			int len = ins.read(buf);
    //			if (len < 0) break;
    //			outs.write(buf,0,len);
    //			total_bytes += len;
    //		}
    //		buf = ("MIDlet-Jar-Size: "+total_bytes).getBytes();
    //		outs.write(buf,0,buf.length);
    //		outs.close();
    //		//ins.close();
    //	}
    // }
    // return false;
    // remove empty lines from the generated jad which may have been
    // introduced by manifest write.
    // some systems have trouble with empty lines
    List<String> lines = new ArrayList<String>();
    BufferedReader in = new BufferedReader(new FileReader(outfile));
    while (true) {
      String line = in.readLine();
      if (line == null) break;
      lines.add(line);
    }
    in.close();
    PrintWriter outp = new PrintWriter(outfile);
    for (String s : lines) {
      if (s.trim().equals("")) continue;
      outp.println(s);
    }
    outp.close();
    return true;
  }
 protected void addPathFile(final File pathComponent) throws IOException {
   if (!this.pathComponents.contains(pathComponent)) {
     this.pathComponents.addElement(pathComponent);
   }
   if (pathComponent.isDirectory()) {
     return;
   }
   final String absPathPlusTimeAndLength =
       pathComponent.getAbsolutePath()
           + pathComponent.lastModified()
           + "-"
           + pathComponent.length();
   String classpath = AntClassLoader.pathMap.get(absPathPlusTimeAndLength);
   if (classpath == null) {
     JarFile jarFile = null;
     try {
       jarFile = new JarFile(pathComponent);
       final Manifest manifest = jarFile.getManifest();
       if (manifest == null) {
         return;
       }
       classpath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
     } finally {
       if (jarFile != null) {
         jarFile.close();
       }
     }
     if (classpath == null) {
       classpath = "";
     }
     AntClassLoader.pathMap.put(absPathPlusTimeAndLength, classpath);
   }
   if (!"".equals(classpath)) {
     final URL baseURL = AntClassLoader.FILE_UTILS.getFileURL(pathComponent);
     final StringTokenizer st = new StringTokenizer(classpath);
     while (st.hasMoreTokens()) {
       final String classpathElement = st.nextToken();
       final URL libraryURL = new URL(baseURL, classpathElement);
       if (!libraryURL.getProtocol().equals("file")) {
         this.log(
             "Skipping jar library "
                 + classpathElement
                 + " since only relative URLs are supported by this"
                 + " loader",
             3);
       } else {
         final String decodedPath = Locator.decodeUri(libraryURL.getFile());
         final File libraryFile = new File(decodedPath);
         if (!libraryFile.exists() || this.isInPath(libraryFile)) {
           continue;
         }
         this.addPathFile(libraryFile);
       }
     }
   }
 }
  // optimal side-effects
  private synchronized boolean isSuperMan() throws IOException {

    if (superMan == null) {
      superMan = super.getManifest();
    }

    if (superMan != null) {
      superAttr = superMan.getMainAttributes();
      superEntries = superMan.getEntries();
      return true;
    } else return false;
  }
예제 #6
0
  /** Test default package versions. */
  public static void testDefaultPackageVersion() throws Exception {
    Builder a = new Builder();
    a.addClasspath(new File("bin"));
    a.setProperty("Bundle-Version", "1.2.3");
    a.setProperty("Export-Package", "test.refer");
    Jar jar = a.build();

    Manifest m = jar.getManifest();
    Parameters exports =
        Processor.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE), null);
    Map<String, String> attrs = exports.get("test.refer");
    assertNotNull(attrs);
    assertEquals("1.2.3", attrs.get("version"));
  }
예제 #7
0
  /** Test import provide:. */
  public static void testExportProvided() throws Exception {
    Builder a = new Builder();
    a.addClasspath(IO.getFile("jar/osgi.jar"));
    a.addClasspath(new File("bin"));
    a.setProperty("Private-Package", "test.refer");
    a.setProperty("Export-Package", "org.osgi.service.http;provide:=true");
    Jar jar = a.build();
    Map<String, String> event = a.getImports().getByFQN("org.osgi.service.event");
    assertEquals("[1.0,2)", event.get("version"));
    Map<String, String> http = a.getImports().getByFQN("org.osgi.service.http");
    assertEquals("[1.2,1.3)", http.get("version"));

    Manifest m = jar.getManifest();
    String imports = m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
    assertFalse(imports.contains(Constants.PROVIDE_DIRECTIVE));
  }
예제 #8
0
  /** hardcoded imports */
  public static void testHardcodedImports() throws Exception {
    Builder b = new Builder();
    b.addClasspath(IO.getFile("jar/osgi.jar"));
    b.setProperty("-versionpolicy", "${range;[==,+)}");
    b.setProperty("Private-Package", "org.objectweb.asm");
    b.setProperty("Import-Package", "org.osgi.framework,org.objectweb.asm,abc;version=2.0.0,*");
    b.build();
    Manifest m = b.getJar().getManifest();
    m.write(System.err);
    String s = b.getImports().getByFQN("org.objectweb.asm").get("version");
    assertNull(s);
    s = b.getImports().getByFQN("abc").get("version");
    assertEquals("2.0.0", s);

    s = b.getImports().getByFQN("org.osgi.framework").get("version");
    assertEquals("[1.3,2)", s);
  }
예제 #9
0
  /**
   * Tests if the implementation of the EventHandler (which is marked as a ConsumerType) causes the
   * import of the api package to use the consumer version policy.
   */
  public static void testConsumerType() throws Exception {
    Builder a = new Builder();
    a.addClasspath(new File("bin"));
    a.setPrivatePackage("test.versionpolicy.uses");
    a.setExportPackage("test.versionpolicy.api");
    a.setProperty("build", "123");
    Jar jar = a.build();
    assertTrue(a.check());
    Manifest m = jar.getManifest();
    m.write(System.err);
    Domain d = Domain.domain(m);

    Parameters parameters = d.getImportPackage();
    Attrs attrs = parameters.get("test.versionpolicy.api");
    assertNotNull(attrs);
    assertEquals("[1.2,2)", attrs.get("version"));
  }
예제 #10
0
  /**
   * Test if the implementation of "AnnotatedProviderInterface", which is annotated with OSGi
   * R6 @ProviderType, causes import of the api package to use the provider version policy
   */
  public static void testProviderTypeR6() throws Exception {
    Builder b = new Builder();
    b.addClasspath(new File("bin"));
    b.setPrivatePackage("test.versionpolicy.implemented.osgi");
    b.setProperty("build", "123");

    Jar jar = b.build();
    assertTrue(b.check());
    Manifest m = jar.getManifest();
    m.write(System.err);

    Domain d = Domain.domain(m);
    Parameters params = d.getImportPackage();
    Attrs attrs = params.get("test.version.annotations.osgi");
    assertNotNull(attrs);
    assertEquals("[1.2,1.3)", attrs.get("version"));
  }
예제 #11
0
 private static String getVersionString() {
   String findContainingJar = JarManager.findContainingJar(Main.class);
   try {
     StringBuffer buffer = new StringBuffer();
     JarFile jar = new JarFile(findContainingJar);
     final Manifest manifest = jar.getManifest();
     final Map<String, Attributes> attrs = manifest.getEntries();
     Attributes attr = attrs.get("org/apache/pig");
     String version = (String) attr.getValue("Implementation-Version");
     String svnRevision = (String) attr.getValue("Svn-Revision");
     String buildTime = (String) attr.getValue("Build-TimeStamp");
     // we use a version string similar to svn
     // svn, version 1.4.4 (r25188)
     // compiled Sep 23 2007, 22:32:34
     return "Apache Pig version " + version + " (r" + svnRevision + ") \ncompiled " + buildTime;
   } catch (Exception e) {
     throw new RuntimeException("unable to read pigs manifest file", e);
   }
 }
예제 #12
0
  /**
   * Tests if the implementation of the EventAdmin (which is marked as a ProviderType) causes the
   * import of the api package to use the provider version policy.
   */
  public static void testProviderType() throws Exception {
    Builder a = new Builder();
    a.addClasspath(new File("bin"));
    a.setPrivatePackage("test.versionpolicy.implemented");
    a.setExportPackage("test.versionpolicy.api");
    a.setImportPackage("test.versionpolicy.api"); // what changed so this is
    // not automatically
    // added?
    a.setProperty("build", "123");
    Jar jar = a.build();
    assertTrue(a.check());
    Manifest m = jar.getManifest();
    m.write(System.err);
    Domain d = Domain.domain(m);

    Parameters parameters = d.getImportPackage();
    Attrs attrs = parameters.get("test.versionpolicy.api");
    assertNotNull(attrs);
    assertEquals("[1.2,1.3)", attrs.get("version"));
  }
예제 #13
0
  public String verify(JarFile jar, String... algorithms) throws IOException {
    if (algorithms == null || algorithms.length == 0) algorithms = new String[] {"MD5", "SHA"};
    else if (algorithms.length == 1 && algorithms[0].equals("-")) return null;

    try {
      Manifest m = jar.getManifest();
      if (m.getEntries().isEmpty()) return "No name sections";

      for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
        JarEntry je = e.nextElement();
        if (MANIFEST_ENTRY.matcher(je.getName()).matches()) continue;

        Attributes nameSection = m.getAttributes(je.getName());
        if (nameSection == null) return "No name section for " + je.getName();

        for (String algorithm : algorithms) {
          try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            String expected = nameSection.getValue(algorithm + "-Digest");
            if (expected != null) {
              byte digest[] = Base64.decodeBase64(expected);
              copy(jar.getInputStream(je), md);
              if (!Arrays.equals(digest, md.digest()))
                return "Invalid digest for "
                    + je.getName()
                    + ", "
                    + expected
                    + " != "
                    + Base64.encodeBase64(md.digest());
            } else reporter.error("could not find digest for " + algorithm + "-Digest");
          } catch (NoSuchAlgorithmException nsae) {
            return "Missing digest algorithm " + algorithm;
          }
        }
      }
    } catch (Exception e) {
      return "Failed to verify due to exception: " + e.getMessage();
    }
    return null;
  }
예제 #14
0
파일: Installer.java 프로젝트: suever/CTP
 private static Hashtable<String, String> getManifestAttributes(Manifest manifest) {
   Hashtable<String, String> h = new Hashtable<String, String>();
   try {
     Attributes attrs = manifest.getMainAttributes();
     Iterator it = attrs.keySet().iterator();
     while (it.hasNext()) {
       String key = it.next().toString();
       h.put(key, attrs.getValue(key));
     }
   } catch (Exception ignore) {
   }
   return h;
 }
예제 #15
0
  /**
   * We create a JAR with the test.classreferenc.ClassReference class. This class contains a
   * javax.swing.Box.class reference Prior to Java 1.5, this was done in a silly way that is handled
   * specially. After 1.5 it is a normal reference.
   *
   * @throws Exception
   */
  public void testReference() throws Exception {
    Properties properties = new Properties();
    properties.put("-classpath", "compilerversions/compilerversions.jar");
    String[] packages = {
      "sun_1_1",
      "sun_1_6",
      "eclipse_1_1",
      "sun_1_2",
      "sun_1_3",
      "sun_1_4",
      "sun_1_5",
      "sun_jsr14",
      "eclipse_1_5",
      "eclipse_1_6",
      "eclipse_1_2",
      "eclipse_1_3",
      "eclipse_1_4",
      "eclipse_jsr14"
    };
    for (int i = 0; i < packages.length; i++) {
      Builder builder = new Builder();
      properties.put("Export-Package", packages[i]);
      builder.setProperties(properties);
      Jar jar = builder.build();
      System.out.println(builder.getErrors());
      System.out.println(builder.getWarnings());
      assertEquals(0, builder.getErrors().size());
      assertEquals(0, builder.getWarnings().size());

      Manifest manifest = jar.getManifest();
      String imports = manifest.getMainAttributes().getValue("Import-Package");
      assertTrue(
          "Package " + packages[i] + "contains swing ref", imports.indexOf("javax.swing") >= 0);
      assertFalse(
          "Package " + packages[i] + "should not contain ClassRef",
          imports.indexOf("ClassRef") >= 0);
    }
  }
예제 #16
0
  /** Check implementation version policy. Uses the package test.versionpolicy.(uses|implemented) */
  static void assertPolicy(String pack, String type) throws Exception {
    Builder a = new Builder();
    a.addClasspath(new File("bin"));
    a.setProperty("Export-Package", "test.versionpolicy.api");
    Jar jar = a.build();

    Builder b = new Builder();
    b.addClasspath(jar);
    b.addClasspath(new File("bin"));

    b.setProperty("-versionpolicy-impl", "IMPL");
    b.setProperty("-versionpolicy-uses", "USES");
    b.setProperty("Private-Package", pack);
    b.build();
    Manifest m = b.getJar().getManifest();
    m.write(System.err);
    Map<String, String> map = b.getImports().getByFQN("test.versionpolicy.api");
    assertNotNull(map);
    // String s = map.get(Constants.IMPLEMENTED_DIRECTIVE);
    // assertEquals("true", s);
    Parameters mp = Processor.parseHeader(m.getMainAttributes().getValue("Import-Package"), null);
    assertEquals(type, mp.get("test.versionpolicy.api").get("version"));
  }
  public Manifest getManifest() throws IOException {

    if (!isSuperMan()) {
      return null;
    }

    Manifest man = new Manifest();
    Attributes attr = man.getMainAttributes();
    attr.putAll((Map) superAttr.clone());

    // now deep copy the manifest entries
    if (superEntries != null) {
      Map entries = man.getEntries();
      Iterator it = superEntries.keySet().iterator();
      while (it.hasNext()) {
        Object key = it.next();
        Attributes at = (Attributes) superEntries.get(key);
        entries.put(key, at.clone());
      }
    }

    return man;
  }
예제 #18
0
  /**
   * Tests the handling of the -sub facility
   *
   * @throws Exception
   */
  public static void testSub() throws Exception {
    Workspace ws = Workspace.getWorkspace(new File("test/ws"));
    Project project = ws.getProject("p4-sub");
    File[] files = project.build();
    Arrays.sort(files);

    System.err.println(Processor.join(project.getErrors(), "\n"));
    System.err.println(Processor.join(project.getWarnings(), "\n"));

    assertEquals(0, project.getErrors().size());
    assertEquals(0, project.getWarnings().size());
    assertNotNull(files);
    assertEquals(3, files.length);

    Jar a = new Jar(files[0]);
    Jar b = new Jar(files[1]);
    Manifest ma = a.getManifest();
    Manifest mb = b.getManifest();

    assertEquals("base", ma.getMainAttributes().getValue("Base-Header"));
    assertEquals("base", mb.getMainAttributes().getValue("Base-Header"));
    assertEquals("a", ma.getMainAttributes().getValue("Sub-Header"));
    assertEquals("b", mb.getMainAttributes().getValue("Sub-Header"));
  }
 protected void definePackage(
     final File container, final String packageName, final Manifest manifest) {
   final String sectionName = packageName.replace('.', '/') + "/";
   String specificationTitle = null;
   String specificationVendor = null;
   String specificationVersion = null;
   String implementationTitle = null;
   String implementationVendor = null;
   String implementationVersion = null;
   String sealedString = null;
   URL sealBase = null;
   final Attributes sectionAttributes = manifest.getAttributes(sectionName);
   if (sectionAttributes != null) {
     specificationTitle = sectionAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
     specificationVendor = sectionAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
     specificationVersion = sectionAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
     implementationTitle = sectionAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
     implementationVendor = sectionAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
     implementationVersion = sectionAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
     sealedString = sectionAttributes.getValue(Attributes.Name.SEALED);
   }
   final Attributes mainAttributes = manifest.getMainAttributes();
   if (mainAttributes != null) {
     if (specificationTitle == null) {
       specificationTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
     }
     if (specificationVendor == null) {
       specificationVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
     }
     if (specificationVersion == null) {
       specificationVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
     }
     if (implementationTitle == null) {
       implementationTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
     }
     if (implementationVendor == null) {
       implementationVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
     }
     if (implementationVersion == null) {
       implementationVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
     }
     if (sealedString == null) {
       sealedString = mainAttributes.getValue(Attributes.Name.SEALED);
     }
   }
   if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
     try {
       sealBase = new URL(FileUtils.getFileUtils().toURI(container.getAbsolutePath()));
     } catch (MalformedURLException ex) {
     }
   }
   this.definePackage(
       packageName,
       specificationTitle,
       specificationVersion,
       specificationVendor,
       implementationTitle,
       implementationVersion,
       implementationVendor,
       sealBase);
 }
예제 #20
0
파일: Signer.java 프로젝트: JSlain/bnd
  public void signJar(Jar jar) {
    if (digestNames == null || digestNames.length == 0)
      error("Need at least one digest algorithm name, none are specified");

    if (keystoreFile == null || !keystoreFile.getAbsoluteFile().exists()) {
      error("No such keystore file: " + keystoreFile);
      return;
    }

    if (alias == null) {
      error("Private key alias not set for signing");
      return;
    }

    MessageDigest digestAlgorithms[] = new MessageDigest[digestNames.length];

    getAlgorithms(digestNames, digestAlgorithms);

    try {
      Manifest manifest = jar.getManifest();
      manifest.getMainAttributes().putValue("Signed-By", "Bnd");

      // Create a new manifest that contains the
      // Name parts with the specified digests

      ByteArrayOutputStream o = new ByteArrayOutputStream();
      manifest.write(o);
      doManifest(jar, digestNames, digestAlgorithms, o);
      o.flush();
      byte newManifestBytes[] = o.toByteArray();
      jar.putResource("META-INF/MANIFEST.MF", new EmbeddedResource(newManifestBytes, 0));

      // Use the bytes from the new manifest to create
      // a signature file

      byte[] signatureFileBytes = doSignatureFile(digestNames, digestAlgorithms, newManifestBytes);
      jar.putResource("META-INF/BND.SF", new EmbeddedResource(signatureFileBytes, 0));

      // Now we must create an RSA signature
      // this requires the private key from the keystore

      KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());

      KeyStore.PrivateKeyEntry privateKeyEntry = null;

      java.io.FileInputStream keystoreInputStream = null;
      try {
        keystoreInputStream = new java.io.FileInputStream(keystoreFile);
        char[] pw = password == null ? new char[0] : password.toCharArray();

        keystore.load(keystoreInputStream, pw);
        keystoreInputStream.close();
        privateKeyEntry =
            (PrivateKeyEntry) keystore.getEntry(alias, new KeyStore.PasswordProtection(pw));
      } catch (Exception e) {
        error(
            "No able to load the private key from the give keystore("
                + keystoreFile.getAbsolutePath()
                + ") with alias "
                + alias
                + " : "
                + e);
        return;
      } finally {
        IO.close(keystoreInputStream);
      }
      PrivateKey privateKey = privateKeyEntry.getPrivateKey();

      Signature signature = Signature.getInstance("MD5withRSA");
      signature.initSign(privateKey);

      signature.update(signatureFileBytes);

      signature.sign();

      // TODO, place the SF in a PCKS#7 structure ...
      // no standard class for this? The following
      // is an idea but we will to have do ASN.1 BER
      // encoding ...

      ByteArrayOutputStream tmpStream = new ByteArrayOutputStream();
      jar.putResource("META-INF/BND.RSA", new EmbeddedResource(tmpStream.toByteArray(), 0));
    } catch (Exception e) {
      error("During signing: " + e);
    }
  }
예제 #21
0
  public CommandData parseCommandData(ArtifactData artifact) throws Exception {
    File source = new File(artifact.file);
    if (!source.isFile()) throw new FileNotFoundException();

    CommandData data = new CommandData();
    data.sha = artifact.sha;
    data.jpmRepoDir = repoDir.getCanonicalPath();
    JarFile jar = new JarFile(source);
    try {
      reporter.trace("Parsing %s", source);
      Manifest m = jar.getManifest();
      Attributes main = m.getMainAttributes();
      data.name = data.bsn = main.getValue("Bundle-SymbolicName");
      String version = main.getValue("Bundle-Version");
      if (version == null) data.version = Version.LOWEST;
      else data.version = new Version(version);

      data.main = main.getValue("Main-Class");
      data.description = main.getValue("Bundle-Description");
      data.title = main.getValue("JPM-Name");

      reporter.trace("name " + data.name + " " + data.main + " " + data.title);
      DependencyCollector path = new DependencyCollector(this);
      path.add(artifact);
      DependencyCollector bundles = new DependencyCollector(this);
      if (main.getValue("JPM-Classpath") != null) {
        Parameters requires = OSGiHeader.parseHeader(main.getValue("JPM-Classpath"));

        for (Map.Entry<String, Attrs> e : requires.entrySet()) {
          path.add(e.getKey(), e.getValue().get("name")); // coordinate
        }
      } else if (!artifact.local) { // No JPM-Classpath, falling back to
        // server's revision
        // Iterable<RevisionRef> closure =
        // library.getClosure(artifact.sha,
        // false);
        // System.out.println("getting closure " + artifact.url + " " +
        // Strings.join("\n",closure));

        // if (closure != null) {
        // for (RevisionRef ref : closure) {
        // path.add(Hex.toHexString(ref.revision));
        // }
        // }
      }

      if (main.getValue("JPM-Runbundles") != null) {
        Parameters jpmrunbundles = OSGiHeader.parseHeader(main.getValue("JPM-Runbundles"));

        for (Map.Entry<String, Attrs> e : jpmrunbundles.entrySet()) {
          bundles.add(e.getKey(), e.getValue().get("name"));
        }
      }

      reporter.trace("collect digests runpath");
      data.dependencies.addAll(path.getDigests());
      reporter.trace("collect digests bundles");
      data.runbundles.addAll(bundles.getDigests());

      Parameters command = OSGiHeader.parseHeader(main.getValue("JPM-Command"));
      if (command.size() > 1) reporter.error("Only one command can be specified");

      for (Map.Entry<String, Attrs> e : command.entrySet()) {
        data.name = e.getKey();

        Attrs attrs = e.getValue();

        if (attrs.containsKey("jvmargs")) data.jvmArgs = attrs.get("jvmargs");

        if (attrs.containsKey("title")) data.title = attrs.get("title");

        if (data.title != null) data.title = data.name;
      }
      return data;
    } finally {
      jar.close();
    }
  }