Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

file 117 lines (108 sloc) 4.438 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/* sbt -- Simple Build Tool
* Copyright 2010 Mark Harrah
*/
package sbt

import Predef.{conforms => _, _}
import java.io.File
import java.util.jar.{Attributes, Manifest}
import collection.JavaConversions._
import Types.:+:
import Path._

import sbinary.{DefaultProtocol,Format}
import DefaultProtocol.{FileFormat, immutableMapFormat, StringFormat, UnitFormat}
import Cache.{defaultEquiv, hConsCache, hNilCache, streamFormat, wrapIn}
import Tracked.{inputChanged, outputChanged}
import FileInfo.exists
import FilesInfo.lastModified

sealed trait PackageOption
object Package
{
final case class JarManifest(m: Manifest) extends PackageOption
{
assert(m != null)
}
final case class MainClass(mainClassName: String) extends PackageOption
final case class ManifestAttributes(attributes: (Attributes.Name, String)*) extends PackageOption
def ManifestAttributes(attributes: (String, String)*): ManifestAttributes =
{
val converted = for( (name,value) <- attributes ) yield (new Attributes.Name(name), value)
new ManifestAttributes(converted : _*)
}

def mergeAttributes(a1: Attributes, a2: Attributes) = a1 ++= a2
// merges `mergeManifest` into `manifest` (mutating `manifest` in the process)
def mergeManifests(manifest: Manifest, mergeManifest: Manifest)
{
mergeAttributes(manifest.getMainAttributes, mergeManifest.getMainAttributes)
val entryMap = asScalaMap(manifest.getEntries)
for((key, value) <- mergeManifest.getEntries)
{
entryMap.get(key) match
{
case Some(attributes) => mergeAttributes(attributes, value)
case None => entryMap put (key, value)
}
}
}

final class Configuration(val sources: Seq[(File, String)], val jar: File, val options: Seq[PackageOption])
def apply(conf: Configuration, cacheFile: File, log: Logger)
{
val manifest = new Manifest
val main = manifest.getMainAttributes
for(option <- conf.options)
{
option match
{
case JarManifest(mergeManifest) => mergeManifests(manifest, mergeManifest)
case MainClass(mainClassName) => main.put(Attributes.Name.MAIN_CLASS, mainClassName)
case ManifestAttributes(attributes @ _*) => main ++= attributes
case _ => log.warn("Ignored unknown package option " + option)
}
}
setVersion(main)

val cachedMakeJar = inputChanged(cacheFile / "inputs") { (inChanged, inputs: Map[File, String] :+: FilesInfo[ModifiedFileInfo] :+: Manifest :+: HNil) =>
val sources :+: _ :+: manifest :+: HNil = inputs
outputChanged(cacheFile / "output") { (outChanged, jar: PlainFileInfo) =>
if(inChanged || outChanged)
makeJar(sources.toSeq, jar.file, manifest, log)
else
log.debug("Jar uptodate: " + jar.file)
}
}

val map = conf.sources.toMap
val inputs = map :+: lastModified(map.keySet.toSet) :+: manifest :+: HNil
cachedMakeJar(inputs)(() => exists(conf.jar))
}
def setVersion(main: Attributes)
{
val version = Attributes.Name.MANIFEST_VERSION
if(main.getValue(version) eq null)
main.put(version, "1.0")
}
def addSpecManifestAttributes(name: String, version: String, orgName: String): PackageOption =
{
import Attributes.Name._
val attribKeys = Seq(SPECIFICATION_TITLE, SPECIFICATION_VERSION, SPECIFICATION_VENDOR)
val attribVals = Seq(name, version, orgName)
ManifestAttributes(attribKeys zip attribVals : _*)
}
def addImplManifestAttributes(name: String, version: String, homepage: Option[java.net.URL], org: String, orgName: String): PackageOption =
{
import Attributes.Name._
val attribKeys = Seq(IMPLEMENTATION_TITLE, IMPLEMENTATION_VERSION, IMPLEMENTATION_VENDOR, IMPLEMENTATION_VENDOR_ID)
val attribVals = Seq(name, version, orgName, org)
ManifestAttributes((attribKeys zip attribVals) ++ { homepage map(h => (IMPLEMENTATION_URL, h.toString)) } : _*)
}
def makeJar(sources: Seq[(File, String)], jar: File, manifest: Manifest, log: Logger)
{
log.info("Packaging " + jar.getAbsolutePath + " ...")
IO.delete(jar)
log.debug(sourcesDebugString(sources))
IO.jar(sources, jar, manifest)
log.info("Done packaging.")
}
def sourcesDebugString(sources: Seq[(File, String)]): String =
"Input file mappings:\n\t" + (sources map { case (f,s) => s + "\n\t " + f} mkString("\n\t") )

implicit def manifestEquiv: Equiv[Manifest] = defaultEquiv
implicit def manifestFormat: Format[Manifest] = streamFormat( _ write _, in => new Manifest(in))

implicit def stringMapEquiv: Equiv[Map[File, String]] = defaultEquiv
}
Something went wrong with that request. Please try again.