scala.tools.ant.Pack200Task.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-compiler Show documentation
Show all versions of scala-compiler Show documentation
Compiler for the Scala Programming Language
/* __ *\
** ________ ___ / / ___ Scala Ant Tasks **
** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.tools.ant
import java.io.{BufferedOutputStream, File, FileInputStream,
FileOutputStream, PipedInputStream, PipedOutputStream}
import java.util.jar.{JarFile, JarInputStream, JarOutputStream, Pack200}
import java.util.jar.Pack200.Packer._
import org.apache.tools.ant.{BuildException, DirectoryScanner}
import org.apache.tools.ant.types.FileSet
/** An [[http://ant.apache.org Ant]] task that applies the pack200 encoding
* to a JAR file.
*
* - `destdir` (mandatory),
* - `dir` (defaults to project's basedir),
* - `effort` (default 9),
* - `keepFileOrder` (default `'''false'''`),
* - `keepModificationTime` (default `'''false'''`),
* - `repack` (default false),
* - `segmentLimit` (default `-1` for no limit),
* - `suffix` (default ".pack")
*
* @author James Matlik
*/
class Pack200Task extends ScalaMatchingTask {
/*============================================================================*\
** Ant user-properties **
\*============================================================================*/
var destdir: Option[File] = None
var srcdir: Option[File] = None
var effort = 9
var keepFileOrder = false
var keepModificationTime = false
var repack = false
var segmentLimit = -1
var packFileSuffix = ".pack"
/*============================================================================*\
** Properties setters **
\*============================================================================*/
def setDir(dir: File) {
if (dir.exists && dir.isDirectory) srcdir = Some(dir)
else buildError("Please specify a valid directory with Jar files for packing.")
}
/** A level from 0 (none) to 9 (max) of effort for applying Pack200 */
def setEffort(x: Int) {
if (effort < 10 && effort > -1) effort = x
else buildError("The effort level must be a value from 0 to 9")
}
/** Set the flag to specify if file reordering should be performed. Reordering
* is used to remove empty packages and improve pack200 optimization.
* @param keep
* `'''true'''` to retain file ordering.
* `'''false'''` to optimize directory structure (DEFAULT). */
def setKeepFileOrder(x: Boolean) { keepFileOrder = x }
/** If false, a single modification time is used for all contained files */
def setKeepModificationTime(x: Boolean) { keepModificationTime = x }
/** A flag that tells the task to pack and then unpack the source JAR file
* into another JAR file. This resulting JAR file can then be signed,
* packed again, compressed and distributed for securely distributed code.
*/
def setRepack(r: Boolean) { repack = r }
def setSegmentLimit(size: Int) { segmentLimit = size }
/** Set the output directory */
def setDestdir(file: File) {
if (file != null && file.exists && file.isDirectory) destdir = Some(file)
else buildError("The destination directory is invalid: " + file.getAbsolutePath)
}
def setSuffix(s: String) { packFileSuffix = s }
/*============================================================================*\
** Properties getters **
\*============================================================================*/
/** Gets the list of individual JAR files for processing.
* @return The list of JAR files */
private def getFileList: List[File] = {
var files: List[File] = Nil
val fs = getImplicitFileSet
var ds = fs.getDirectoryScanner(getProject())
var dir = fs.getDir(getProject())
for (filename <- ds.getIncludedFiles()
if filename.toLowerCase.endsWith(".jar")) {
val file = new File(dir, filename)
if(files.exists(file.equals(_)) == false) files = file :: files
}
files.reverse
}
/*============================================================================*\
** Compilation and support methods **
\*============================================================================*/
private def makeJarOutputStream(file: File) =
new JarOutputStream(makeOutputStream(file))
private def makeOutputStream(file: File) =
new BufferedOutputStream(new FileOutputStream(file))
/*============================================================================*\
** The big execute method **
\*============================================================================*/
/** Performs the tool creation. */
override def execute() = {
// Audits
val packDir = destdir.getOrElse(buildError("No output directory specified"))
// Setup the inherited fileset for further processing
fileset.setDir(srcdir.getOrElse(getProject.getBaseDir))
val files = getFileList
if (files.isEmpty) buildError("No JAR files were selected for packing.")
// Setup the packer
val packer = Pack200.newPacker
val p = packer.properties
p.put(EFFORT, effort.toString)
p.put(SEGMENT_LIMIT, segmentLimit.toString)
p.put(KEEP_FILE_ORDER, if(keepFileOrder) TRUE else FALSE)
p.put(MODIFICATION_TIME, if(keepModificationTime) LATEST else KEEP)
for (file <- files) {
if (repack) {
val repackedFile = new File(packDir, file.getName)
if (file.lastModified > repackedFile.lastModified) {
println("Repacking " + file.toString + " to " + repackedFile.toString)
val tmpFile = new File(packDir, file.getName + ".tmp")
val os = makeOutputStream(tmpFile)
packer.pack(new JarFile(file), os)
os.close()
val jos = makeJarOutputStream(repackedFile)
Pack200.newUnpacker.unpack(tmpFile, jos)
jos.close()
tmpFile.delete()
}
}
else {
val packFile: File = {
val name = file.getName.substring(0, file.getName.lastIndexOf("."))
new File(packDir, name + packFileSuffix)
}
if(file.lastModified > packFile.lastModified) {
println("Packing " + file.toString + " to " + packFile.toString)
val os = makeOutputStream(packFile)
packer.pack(new JarFile(file), os)
}
}
}
}
}