mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Breaking down PackagingPlugin for incremental task.
This commit is contained in:
parent
3b8464f99c
commit
fa546e4510
4 changed files with 274 additions and 212 deletions
|
@ -0,0 +1,91 @@
|
||||||
|
package com.beust.kobalt.plugin.packaging
|
||||||
|
|
||||||
|
import com.beust.kobalt.IFileSpec
|
||||||
|
import com.beust.kobalt.api.KobaltContext
|
||||||
|
import com.beust.kobalt.api.Project
|
||||||
|
import com.beust.kobalt.api.ProjectDescription
|
||||||
|
import com.beust.kobalt.internal.JvmCompilerPlugin
|
||||||
|
import com.beust.kobalt.maven.DependencyManager
|
||||||
|
import com.beust.kobalt.misc.*
|
||||||
|
import com.google.inject.Inject
|
||||||
|
import java.io.File
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.jar.JarOutputStream
|
||||||
|
|
||||||
|
class JarGenerator @Inject constructor(val dependencyManager: DependencyManager){
|
||||||
|
fun includedFilesForJarFile(project: Project, context: KobaltContext, jar: Jar) : List<IncludedFile> {
|
||||||
|
//
|
||||||
|
// Add all the applicable files for the current project
|
||||||
|
//
|
||||||
|
val buildDir = KFiles.buildDir(project)
|
||||||
|
val result = arrayListOf<IncludedFile>()
|
||||||
|
val classesDir = KFiles.makeDir(buildDir.path, "classes")
|
||||||
|
|
||||||
|
if (jar.includedFiles.isEmpty()) {
|
||||||
|
// If no includes were specified, assume the user wants a simple jar file made of the
|
||||||
|
// classes of the project, so we specify a From("build/classes/"), To("") and
|
||||||
|
// a list of files containing everything under it
|
||||||
|
val relClassesDir = Paths.get(project.directory).relativize(Paths.get(classesDir.path))
|
||||||
|
val prefixPath = Paths.get(project.directory).relativize(Paths.get(classesDir.path + "/"))
|
||||||
|
|
||||||
|
// Class files
|
||||||
|
val files = KFiles.findRecursively(classesDir).map { File(relClassesDir.toFile(), it) }
|
||||||
|
val filesNotExcluded : List<File> = files.filter { ! KFiles.isExcluded(it, jar.excludes) }
|
||||||
|
val fileSpecs = arrayListOf<IFileSpec>()
|
||||||
|
filesNotExcluded.forEach {
|
||||||
|
fileSpecs.add(IFileSpec.FileSpec(it.path.toString().substring(prefixPath.toString().length + 1)))
|
||||||
|
}
|
||||||
|
result.add(IncludedFile(From(prefixPath.toString() + "/"), To(""), fileSpecs))
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// The user specified an include, just use it verbatim
|
||||||
|
//
|
||||||
|
result.addAll(PackagingPlugin.findIncludedFiles(project.directory, jar.includedFiles, jar.excludes))
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If fatJar is true, add all the transitive dependencies as well: compile, runtime and dependent projects
|
||||||
|
//
|
||||||
|
if (jar.fatJar) {
|
||||||
|
log(2, "Creating fat jar")
|
||||||
|
|
||||||
|
val seen = hashSetOf<String>()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val dependentProjects = project.projectProperties.get(JvmCompilerPlugin.DEPENDENT_PROJECTS)
|
||||||
|
as List<ProjectDescription>
|
||||||
|
val allDependencies = project.compileDependencies + project.compileRuntimeDependencies
|
||||||
|
val transitiveDependencies = dependencyManager.calculateDependencies(project, context, dependentProjects,
|
||||||
|
allDependencies)
|
||||||
|
transitiveDependencies.map {
|
||||||
|
it.jarFile.get()
|
||||||
|
}.forEach { file : File ->
|
||||||
|
if (! seen.contains(file.path)) {
|
||||||
|
seen.add(file.path)
|
||||||
|
if (! KFiles.isExcluded(file, jar.excludes)) {
|
||||||
|
result.add(IncludedFile(arrayListOf(IFileSpec.FileSpec(file.path))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateJar(project: Project, context: KobaltContext, jar: Jar) : File {
|
||||||
|
val allFiles = includedFilesForJarFile(project, context, jar)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generate the manifest
|
||||||
|
//
|
||||||
|
val manifest = java.util.jar.Manifest()//FileInputStream(mf))
|
||||||
|
jar.attributes.forEach { attribute ->
|
||||||
|
manifest.mainAttributes.putValue(attribute.first, attribute.second)
|
||||||
|
}
|
||||||
|
val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
|
||||||
|
|
||||||
|
return PackagingPlugin.generateArchive(project, context, jar.name, ".jar", allFiles,
|
||||||
|
true /* expandJarFiles */, jarFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,22 +12,19 @@ import com.beust.kobalt.api.annotation.Task
|
||||||
import com.beust.kobalt.glob
|
import com.beust.kobalt.glob
|
||||||
import com.beust.kobalt.internal.JvmCompilerPlugin
|
import com.beust.kobalt.internal.JvmCompilerPlugin
|
||||||
import com.beust.kobalt.maven.DependencyManager
|
import com.beust.kobalt.maven.DependencyManager
|
||||||
import com.beust.kobalt.maven.LocalRepo
|
|
||||||
import com.beust.kobalt.misc.*
|
import com.beust.kobalt.misc.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.jar.JarOutputStream
|
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class PackagingPlugin @Inject constructor(val dependencyManager : DependencyManager,
|
class PackagingPlugin @Inject constructor(val dependencyManager : DependencyManager,
|
||||||
val executors: KobaltExecutors, val localRepo: LocalRepo)
|
val executors: KobaltExecutors, val jarGenerator: JarGenerator, val warGenerator: WarGenerator,
|
||||||
: ConfigPlugin<InstallConfig>(), ITaskContributor {
|
val zipGenerator: ZipGenerator) : ConfigPlugin<InstallConfig>(), ITaskContributor {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PLUGIN_NAME = "Packaging"
|
const val PLUGIN_NAME = "Packaging"
|
||||||
|
@ -44,6 +41,92 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
|
||||||
|
|
||||||
const val TASK_ASSEMBLE: String = "assemble"
|
const val TASK_ASSEMBLE: String = "assemble"
|
||||||
const val TASK_INSTALL: String = "install"
|
const val TASK_INSTALL: String = "install"
|
||||||
|
|
||||||
|
|
||||||
|
fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<IFileSpec.Glob>)
|
||||||
|
: List<IncludedFile> {
|
||||||
|
val result = arrayListOf<IncludedFile>()
|
||||||
|
files.forEach { includedFile ->
|
||||||
|
val includedSpecs = arrayListOf<IFileSpec>()
|
||||||
|
includedFile.specs.forEach { spec ->
|
||||||
|
val fromPath = directory + "/" + includedFile.from
|
||||||
|
if (File(fromPath).exists()) {
|
||||||
|
spec.toFiles(fromPath).forEach { file ->
|
||||||
|
File(fromPath, file.path).let {
|
||||||
|
if (!it.exists()) {
|
||||||
|
throw AssertionError("File should exist: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KFiles.isExcluded(file, excludes)) {
|
||||||
|
includedSpecs.add(FileSpec(file.path))
|
||||||
|
} else {
|
||||||
|
log(2, "Not adding ${file.path} to jar file because it's excluded")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log(2, "Directory $fromPath doesn't exist, not including it in the jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includedSpecs.size > 0) {
|
||||||
|
log(3, "Including specs $includedSpecs")
|
||||||
|
result.add(IncludedFile(From(includedFile.from), To(includedFile.to), includedSpecs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateArchive(project: Project,
|
||||||
|
context: KobaltContext,
|
||||||
|
archiveName: String?,
|
||||||
|
suffix: String,
|
||||||
|
includedFiles: List<IncludedFile>,
|
||||||
|
expandJarFiles : Boolean = false,
|
||||||
|
outputStreamFactory: (OutputStream) -> ZipOutputStream = DEFAULT_STREAM_FACTORY) : File {
|
||||||
|
val fullArchiveName = context.variant.archiveName(project, archiveName, suffix)
|
||||||
|
val archiveDir = File(libsDir(project))
|
||||||
|
val result = File(archiveDir.path, fullArchiveName)
|
||||||
|
log(2, "Creating $result")
|
||||||
|
if (! Features.USE_TIMESTAMPS || isOutdated(project.directory, includedFiles, result)) {
|
||||||
|
val outStream = outputStreamFactory(FileOutputStream(result))
|
||||||
|
JarUtils.addFiles(project.directory, includedFiles, outStream, expandJarFiles)
|
||||||
|
log(2, text = "Added ${includedFiles.size} files to $result")
|
||||||
|
outStream.flush()
|
||||||
|
outStream.close()
|
||||||
|
log(1, " Created $result")
|
||||||
|
} else {
|
||||||
|
log(2, " $result is up to date")
|
||||||
|
}
|
||||||
|
|
||||||
|
project.projectProperties.put(JAR_NAME, result.absolutePath)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private val DEFAULT_STREAM_FACTORY = { os : OutputStream -> ZipOutputStream(os) }
|
||||||
|
|
||||||
|
private fun isOutdated(directory: String, includedFiles: List<IncludedFile>, output: File): Boolean {
|
||||||
|
if (! output.exists()) return true
|
||||||
|
|
||||||
|
val lastModified = output.lastModified()
|
||||||
|
includedFiles.forEach { root ->
|
||||||
|
val allFiles = root.allFromFiles(directory)
|
||||||
|
allFiles.forEach { relFile ->
|
||||||
|
val file = File(KFiles.joinDir(directory, root.from, relFile.path))
|
||||||
|
if (file.isFile) {
|
||||||
|
if (file.lastModified() > lastModified) {
|
||||||
|
log(2, " Outdated $file and $output "
|
||||||
|
+ Date(file.lastModified()) + " " + Date(output.lastModified()))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun libsDir(project: Project) = KFiles.makeDir(KFiles.buildDir(project).path, "libs").path
|
||||||
}
|
}
|
||||||
|
|
||||||
override val name = PLUGIN_NAME
|
override val name = PLUGIN_NAME
|
||||||
|
@ -59,222 +142,18 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
|
||||||
runTask = { taskAssemble(project) })
|
runTask = { taskAssemble(project) })
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun libsDir(project: Project) = KFiles.makeDir(KFiles.buildDir(project).path, "libs").path
|
|
||||||
|
|
||||||
@Task(name = TASK_ASSEMBLE, description = "Package the artifacts",
|
@Task(name = TASK_ASSEMBLE, description = "Package the artifacts",
|
||||||
runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE))
|
runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE))
|
||||||
fun taskAssemble(project: Project) : TaskResult {
|
fun taskAssemble(project: Project) : TaskResult {
|
||||||
project.projectProperties.put(PACKAGES, packages)
|
project.projectProperties.put(PACKAGES, packages)
|
||||||
packages.filter { it.project.name == project.name }.forEach { pkg ->
|
packages.filter { it.project.name == project.name }.forEach { pkg ->
|
||||||
pkg.jars.forEach { generateJar(pkg.project, it) }
|
pkg.jars.forEach { jarGenerator.generateJar(pkg.project, context, it) }
|
||||||
pkg.wars.forEach { generateWar(pkg.project, it) }
|
pkg.wars.forEach { warGenerator.generateWar(pkg.project, context, it, projects) }
|
||||||
pkg.zips.forEach { generateZip(pkg.project, it) }
|
pkg.zips.forEach { zipGenerator.generateZip(pkg.project, context, it) }
|
||||||
}
|
}
|
||||||
return TaskResult()
|
return TaskResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWar(project: Project, war: War) : File {
|
|
||||||
//
|
|
||||||
// src/main/web app and classes
|
|
||||||
//
|
|
||||||
val allFiles = arrayListOf(
|
|
||||||
IncludedFile(From("src/main/webapp"), To(""), listOf(Glob("**"))),
|
|
||||||
IncludedFile(From("kobaltBuild/classes"), To("WEB-INF/classes"), listOf(Glob("**")))
|
|
||||||
)
|
|
||||||
val manifest = java.util.jar.Manifest()//FileInputStream(mf))
|
|
||||||
war.attributes.forEach { attribute ->
|
|
||||||
manifest.mainAttributes.putValue(attribute.first, attribute.second)
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// The transitive closure of libraries goes into WEB-INF/libs.
|
|
||||||
// Copy them all in kobaltBuild/war/WEB-INF/libs and create one IncludedFile out of that directory
|
|
||||||
//
|
|
||||||
val allDependencies = dependencyManager.calculateDependencies(project, context, projects,
|
|
||||||
project.compileDependencies)
|
|
||||||
|
|
||||||
val WEB_INF = "WEB-INF/lib"
|
|
||||||
val outDir = project.buildDirectory + "/war"
|
|
||||||
val fullDir = outDir + "/" + WEB_INF
|
|
||||||
File(fullDir).mkdirs()
|
|
||||||
|
|
||||||
// Run through all the classpath contributors and add their contributions to the libs/ directory
|
|
||||||
context.pluginInfo.classpathContributors.map {
|
|
||||||
it.entriesFor(project)
|
|
||||||
}.map { deps : Collection<IClasspathDependency> ->
|
|
||||||
deps.forEach { dep ->
|
|
||||||
val jar = dep.jarFile.get()
|
|
||||||
KFiles.copy(Paths.get(jar.path), Paths.get(fullDir, jar.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the regular dependencies to the libs/ directory
|
|
||||||
allDependencies.map { it.jarFile.get() }.forEach {
|
|
||||||
KFiles.copy(Paths.get(it.absolutePath), Paths.get(fullDir, it.name))
|
|
||||||
}
|
|
||||||
|
|
||||||
allFiles.add(IncludedFile(From(fullDir), To(WEB_INF), listOf(Glob("**"))))
|
|
||||||
|
|
||||||
val jarFactory = { os:OutputStream -> JarOutputStream(os, manifest) }
|
|
||||||
return generateArchive(project, war.name, ".war", allFiles,
|
|
||||||
false /* don't expand jar files */, jarFactory)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateJar(project: Project, jar: Jar) : File {
|
|
||||||
//
|
|
||||||
// Add all the applicable files for the current project
|
|
||||||
//
|
|
||||||
val buildDir = KFiles.buildDir(project)
|
|
||||||
val allFiles = arrayListOf<IncludedFile>()
|
|
||||||
val classesDir = KFiles.makeDir(buildDir.path, "classes")
|
|
||||||
|
|
||||||
if (jar.includedFiles.isEmpty()) {
|
|
||||||
// If no includes were specified, assume the user wants a simple jar file made of the
|
|
||||||
// classes of the project, so we specify a From("build/classes/"), To("") and
|
|
||||||
// a list of files containing everything under it
|
|
||||||
val relClassesDir = Paths.get(project.directory).relativize(Paths.get(classesDir.path))
|
|
||||||
val prefixPath = Paths.get(project.directory).relativize(Paths.get(classesDir.path + "/"))
|
|
||||||
|
|
||||||
// Class files
|
|
||||||
val files = KFiles.findRecursively(classesDir).map { File(relClassesDir.toFile(), it) }
|
|
||||||
val filesNotExcluded : List<File> = files.filter { ! KFiles.isExcluded(it, jar.excludes) }
|
|
||||||
val fileSpecs = arrayListOf<IFileSpec>()
|
|
||||||
filesNotExcluded.forEach {
|
|
||||||
fileSpecs.add(FileSpec(it.path.toString().substring(prefixPath.toString().length + 1)))
|
|
||||||
}
|
|
||||||
allFiles.add(IncludedFile(From(prefixPath.toString() + "/"), To(""), fileSpecs))
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// The user specified an include, just use it verbatim
|
|
||||||
//
|
|
||||||
allFiles.addAll(findIncludedFiles(project.directory, jar.includedFiles, jar.excludes))
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If fatJar is true, add all the transitive dependencies as well: compile, runtime and dependent projects
|
|
||||||
//
|
|
||||||
if (jar.fatJar) {
|
|
||||||
log(2, "Creating fat jar")
|
|
||||||
|
|
||||||
val seen = hashSetOf<String>()
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val dependentProjects = project.projectProperties.get(JvmCompilerPlugin.DEPENDENT_PROJECTS)
|
|
||||||
as List<ProjectDescription>
|
|
||||||
val allDependencies = project.compileDependencies + project.compileRuntimeDependencies
|
|
||||||
val transitiveDependencies = dependencyManager.calculateDependencies(project, context, dependentProjects,
|
|
||||||
allDependencies)
|
|
||||||
transitiveDependencies.map {
|
|
||||||
it.jarFile.get()
|
|
||||||
}.forEach { file : File ->
|
|
||||||
if (! seen.contains(file.path)) {
|
|
||||||
seen.add(file.path)
|
|
||||||
if (! KFiles.isExcluded(file, jar.excludes)) {
|
|
||||||
allFiles.add(IncludedFile(arrayListOf(FileSpec(file.path))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Generate the manifest
|
|
||||||
//
|
|
||||||
val manifest = java.util.jar.Manifest()//FileInputStream(mf))
|
|
||||||
jar.attributes.forEach { attribute ->
|
|
||||||
manifest.mainAttributes.putValue(attribute.first, attribute.second)
|
|
||||||
}
|
|
||||||
val jarFactory = { os:OutputStream -> JarOutputStream(os, manifest) }
|
|
||||||
|
|
||||||
return generateArchive(project, jar.name, ".jar", allFiles,
|
|
||||||
true /* expandJarFiles */, jarFactory)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<IFileSpec.Glob>)
|
|
||||||
: List<IncludedFile> {
|
|
||||||
val result = arrayListOf<IncludedFile>()
|
|
||||||
files.forEach { includedFile ->
|
|
||||||
val includedSpecs = arrayListOf<IFileSpec>()
|
|
||||||
includedFile.specs.forEach { spec ->
|
|
||||||
val fromPath = directory + "/" + includedFile.from
|
|
||||||
if (File(fromPath).exists()) {
|
|
||||||
spec.toFiles(fromPath).forEach { file ->
|
|
||||||
File(fromPath, file.path).let {
|
|
||||||
if (! it.exists()) {
|
|
||||||
throw AssertionError("File should exist: $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! KFiles.isExcluded(file, excludes)) {
|
|
||||||
includedSpecs.add(FileSpec(file.path))
|
|
||||||
} else {
|
|
||||||
log(2, "Not adding ${file.path} to jar file because it's excluded")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log(2, "Directory $fromPath doesn't exist, not including it in the jar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includedSpecs.size > 0) {
|
|
||||||
log(3, "Including specs $includedSpecs")
|
|
||||||
result.add(IncludedFile(From(includedFile.from), To(includedFile.to), includedSpecs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateZip(project: Project, zip: Zip) {
|
|
||||||
val allFiles = findIncludedFiles(project.directory, zip.includedFiles, zip.excludes)
|
|
||||||
generateArchive(project, zip.name, ".zip", allFiles)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val DEFAULT_STREAM_FACTORY = { os : OutputStream -> ZipOutputStream(os) }
|
|
||||||
|
|
||||||
private fun generateArchive(project: Project,
|
|
||||||
archiveName: String?,
|
|
||||||
suffix: String,
|
|
||||||
includedFiles: List<IncludedFile>,
|
|
||||||
expandJarFiles : Boolean = false,
|
|
||||||
outputStreamFactory: (OutputStream) -> ZipOutputStream = DEFAULT_STREAM_FACTORY) : File {
|
|
||||||
val fullArchiveName = context.variant.archiveName(project, archiveName, suffix)
|
|
||||||
val archiveDir = File(libsDir(project))
|
|
||||||
val result = File(archiveDir.path, fullArchiveName)
|
|
||||||
log(2, "Creating $result")
|
|
||||||
if (! Features.USE_TIMESTAMPS || isOutdated(project.directory, includedFiles, result)) {
|
|
||||||
val outStream = outputStreamFactory(FileOutputStream(result))
|
|
||||||
JarUtils.addFiles(project.directory, includedFiles, outStream, expandJarFiles)
|
|
||||||
log(2, text = "Added ${includedFiles.size} files to $result")
|
|
||||||
outStream.flush()
|
|
||||||
outStream.close()
|
|
||||||
log(1, " Created $result")
|
|
||||||
} else {
|
|
||||||
log(2, " $result is up to date")
|
|
||||||
}
|
|
||||||
|
|
||||||
project.projectProperties.put(JAR_NAME, result.absolutePath)
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isOutdated(directory: String, includedFiles: List<IncludedFile>, output: File): Boolean {
|
|
||||||
if (! output.exists()) return true
|
|
||||||
|
|
||||||
val lastModified = output.lastModified()
|
|
||||||
includedFiles.forEach { root ->
|
|
||||||
val allFiles = root.allFromFiles(directory)
|
|
||||||
allFiles.forEach { relFile ->
|
|
||||||
val file = File(KFiles.joinDir(directory, root.from, relFile.path))
|
|
||||||
if (file.isFile) {
|
|
||||||
if (file.lastModified() > lastModified) {
|
|
||||||
log(2, " Outdated $file and $output "
|
|
||||||
+ Date(file.lastModified()) + " " + Date(output.lastModified()))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addPackage(p: PackageConfig) {
|
fun addPackage(p: PackageConfig) {
|
||||||
packages.add(p)
|
packages.add(p)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.beust.kobalt.plugin.packaging
|
||||||
|
|
||||||
|
import com.beust.kobalt.IFileSpec
|
||||||
|
import com.beust.kobalt.api.IClasspathDependency
|
||||||
|
import com.beust.kobalt.api.KobaltContext
|
||||||
|
import com.beust.kobalt.api.Project
|
||||||
|
import com.beust.kobalt.api.ProjectDescription
|
||||||
|
import com.beust.kobalt.maven.DependencyManager
|
||||||
|
import com.beust.kobalt.misc.From
|
||||||
|
import com.beust.kobalt.misc.IncludedFile
|
||||||
|
import com.beust.kobalt.misc.KFiles
|
||||||
|
import com.beust.kobalt.misc.To
|
||||||
|
import com.google.inject.Inject
|
||||||
|
import java.io.File
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.jar.JarOutputStream
|
||||||
|
|
||||||
|
class WarGenerator @Inject constructor(val dependencyManager: DependencyManager){
|
||||||
|
|
||||||
|
fun includedFilesForJarFile(project: Project, context: KobaltContext, war: War,
|
||||||
|
projects: List<ProjectDescription>) : List<IncludedFile> {
|
||||||
|
//
|
||||||
|
// src/main/web app and classes
|
||||||
|
//
|
||||||
|
val result = arrayListOf(
|
||||||
|
IncludedFile(From("src/main/webapp"), To(""), listOf(IFileSpec.Glob("**"))),
|
||||||
|
IncludedFile(From("kobaltBuild/classes"), To("WEB-INF/classes"), listOf(IFileSpec.Glob("**")))
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// The transitive closure of libraries goes into WEB-INF/libs.
|
||||||
|
// Copy them all in kobaltBuild/war/WEB-INF/libs and create one IncludedFile out of that directory
|
||||||
|
//
|
||||||
|
val allDependencies = dependencyManager.calculateDependencies(project, context, projects,
|
||||||
|
project.compileDependencies)
|
||||||
|
|
||||||
|
val WEB_INF = "WEB-INF/lib"
|
||||||
|
val outDir = project.buildDirectory + "/war"
|
||||||
|
val fullDir = outDir + "/" + WEB_INF
|
||||||
|
File(fullDir).mkdirs()
|
||||||
|
|
||||||
|
// Run through all the classpath contributors and add their contributions to the libs/ directory
|
||||||
|
context.pluginInfo.classpathContributors.map {
|
||||||
|
it.entriesFor(project)
|
||||||
|
}.map { deps : Collection<IClasspathDependency> ->
|
||||||
|
deps.forEach { dep ->
|
||||||
|
val jar = dep.jarFile.get()
|
||||||
|
KFiles.copy(Paths.get(jar.path), Paths.get(fullDir, jar.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the regular dependencies to the libs/ directory
|
||||||
|
allDependencies.map { it.jarFile.get() }.forEach {
|
||||||
|
KFiles.copy(Paths.get(it.absolutePath), Paths.get(fullDir, it.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(IncludedFile(From(fullDir), To(WEB_INF), listOf(IFileSpec.Glob("**"))))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateWar(project: Project, context: KobaltContext, war: War,
|
||||||
|
projects: List<ProjectDescription>) : File {
|
||||||
|
|
||||||
|
val manifest = java.util.jar.Manifest()//FileInputStream(mf))
|
||||||
|
war.attributes.forEach { attribute ->
|
||||||
|
manifest.mainAttributes.putValue(attribute.first, attribute.second)
|
||||||
|
}
|
||||||
|
|
||||||
|
val allFiles = includedFilesForJarFile(project, context, war, projects)
|
||||||
|
val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
|
||||||
|
return PackagingPlugin.generateArchive(project, context, war.name, ".war", allFiles,
|
||||||
|
false /* don't expand jar files */, jarFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.beust.kobalt.plugin.packaging
|
||||||
|
|
||||||
|
import com.beust.kobalt.api.KobaltContext
|
||||||
|
import com.beust.kobalt.api.Project
|
||||||
|
import com.beust.kobalt.maven.DependencyManager
|
||||||
|
import com.google.inject.Inject
|
||||||
|
|
||||||
|
class ZipGenerator @Inject constructor(val dependencyManager: DependencyManager){
|
||||||
|
fun findIncludedFiles(project: Project, context: KobaltContext, zip: Zip)
|
||||||
|
= PackagingPlugin.findIncludedFiles(project.directory, zip.includedFiles, zip.excludes)
|
||||||
|
|
||||||
|
fun generateZip(project: Project, context: KobaltContext, zip: Zip) {
|
||||||
|
val allFiles = findIncludedFiles(project, context, zip)
|
||||||
|
PackagingPlugin.generateArchive(project, context, zip.name, ".zip", allFiles)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue