views:

172

answers:

2

I've built a (command-line) application in Scala that I want to distribute as a standalone JAR. I'm building it with sbt:

import sbt._

class Project(info: ProjectInfo) extends DefaultProject(info) with ProguardProject {
  override def parallelExecution = true      
  override def mainClass: Option[String] = // whatever

  override def libraryDependencies = Set(
    // whatever
  ) ++ super.libraryDependencies

  override def proguardOptions = List(
      "-keepclasseswithmembers public class * { public static void main(java.lang.String[]); }",
      "-dontoptimize",
      "-dontobfuscate",
      proguardKeepLimitedSerializability,
      proguardKeepAllScala,
      "-keep interface scala.ScalaObject"
  )
}

I can run my code with sbt run fine, and I can package it and run ProGuard over it (I'm not interested in obfuscating - the project is going to be open source anyway), I'm just using it to produce a standalone JAR). So, I eventually get a .min.jar file built in target/scala_2.8.0/

This is where it gets complicated. If I run this JAR, I get:

Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes

Okay, I haven't signed it.

So, I generate myself a signing key as follows:

keytool -keystore ~/.keystore -genkey -alias tom

And then, following the Java documentation, I try to sign the JAR:

jarsigner -signedjar [whatever].jar -keystore ~/.keystore target/scala_2.8.0/[whatever]-1.0.min.jar tom

It prompts me:

Enter Passphrase for keystore: 

Warning: 
The signer certificate will expire within six months.

Okay, that's fine. Now, surely, it'll run!

$ java -jar [whatever].jar
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes

I have no idea where to begin. I'm relatively new to the Java platform.

+1  A: 

I don't think you need ProGuard and signing to produce a standalone jar. You can just pack all the classes you need and a META-INF directory with proper classpath and main class set in a zip file, rename it to jar and it should run. See this tutorial.

Sorry, I didn't answer your question, I just don't understand why you want to sign your jar.

tulskiy
I think the issue is that jars normally can't contain jars, if I remember correctly, while ProGuard creates jars that can.
pr1001
I see, so he just needs to unpack scala-library.jar into his jar?
tulskiy
+1  A: 

I ran into the same problem and it appears the problem was that sun's jar signatures were added by proguard in the META-INF directory. I just added them to the filtered files:

override def makeInJarFilter (file :String) =
  super.makeInJarFilter(file) + ",!**/SUN_MICR.RSA,!**/SUN_MICR.SF"

and it works perfectly now.

Paul Brauner