diff --git a/kobalt/src/Build.kt b/kobalt/src/Build.kt index 98b626ab..faa32f8f 100644 --- a/kobalt/src/Build.kt +++ b/kobalt/src/Build.kt @@ -26,6 +26,9 @@ object Versions { val okio = "1.6.0" val retrofit = "2.0.0" val gson = "2.6.2" + val aether = "1.1.0" + val sonatypeAether = "1.13.1" + val maven = "3.3.9" } val wrapper = project { @@ -73,14 +76,24 @@ val kobaltPluginApi = project { "com.google.inject.extensions:guice-assistedinject:4.0", "javax.inject:javax.inject:1", "com.google.guava:guava:19.0-rc2", - "org.apache.maven:maven-model:3.3.3", + "org.apache.maven:maven-model:${Versions.maven}", "io.reactivex:rxjava:1.0.16", "com.google.code.gson:gson:${Versions.gson}", "com.squareup.okio:okio:${Versions.okio}", "com.squareup.retrofit2:retrofit:${Versions.retrofit}", "com.squareup.retrofit2:converter-gson:${Versions.retrofit}", - "com.beust:jcommander:1.48" - ) + "com.beust:jcommander:1.48", + + "org.eclipse.aether:aether-spi:${Versions.aether}", + "org.eclipse.aether:aether-util:${Versions.aether}", + "org.eclipse.aether:aether-impl:${Versions.aether}", + "org.eclipse.aether:aether-connector-basic:${Versions.aether}", + "org.eclipse.aether:aether-transport-file:${Versions.aether}", + "org.eclipse.aether:aether-transport-http:${Versions.aether}", + "org.sonatype.aether:aether-api:${Versions.sonatypeAether}", + "org.sonatype.aether:aether-connector-wagon:1.13.1", + "org.apache.maven:maven-aether-provider:${Versions.maven}" + ) } @@ -122,7 +135,7 @@ val kobaltApp = project(kobaltPluginApi, wrapper) { "com.google.inject:guice:4.0", "com.google.inject.extensions:guice-assistedinject:4.0", "com.beust:jcommander:1.48", - "org.apache.maven:maven-model:3.3.3", + "org.apache.maven:maven-model:${Versions.maven}", "com.google.code.findbugs:jsr305:3.0.1", "com.google.code.gson:gson:${Versions.gson}", "com.squareup.okhttp3:okhttp:${Versions.okhttp}", diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Constants.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Constants.kt index 4a14fa60..4101157c 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Constants.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Constants.kt @@ -10,12 +10,14 @@ object Constants { internal val DEFAULT_REPOS = listOf( "http://repo1.maven.org/maven2/", "https://maven-central.storage.googleapis.com/", - "https://jcenter.bintray.com/" + "https://jcenter.bintray.com/", + + // snapshots + "https://oss.sonatype.org/content/repositories/snapshots/" // The following repos contain snapshots, don't include them by default // , "https://repository.jboss.org/nexus/content/repositories/root_repository/" // , "http://repository.jetbrains.com/all/" -// , "https://oss.sonatype.org/content/repositories/snapshots/" ) } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Pom2.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Pom2.kt index fffddb61..11a71b03 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Pom2.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Pom2.kt @@ -15,20 +15,8 @@ import javax.xml.transform.sax.SAXSource class PomProject { var modelVersion: String? = null var groupId: String? = null - get() { - if (field != null && field!!.contains("\${")) { - println("VARIABLE GROUP") - } - return field - } var artifactId: String? = null var version: String? = null - get() { - if (field != null && field!!.contains("\${")) { - println("VARIABLE VERSION") - } - return field - } var name: String? = null var description: String? = null var url: String? = null @@ -58,24 +46,39 @@ class PomProject { } } -fun main(argv: Array) { - val p = Pom2(File("/Users/beust/t/pom.xml")) - val pom = p.pom - println("Dependencies: " + pom.dependencies[0]) -} +//fun main(argv: Array) { +// val p = Pom2(File("/Users/beust/t/pom.xml")) +// val pom = p.pom +// println("Dependencies: " + pom.dependencies[0]) +//} -class Pom2(val documentFile: File) { - val pom: PomProject by lazy { - val ins = documentFile.inputStream() - val jaxbContext = JAXBContext.newInstance(PomProject::class.java) - val unmarshaller = jaxbContext.createUnmarshaller() +class Either(val exception: E?, val value: V?) - val sax = SAXParserFactory.newInstance() - sax.isNamespaceAware = false - val reader = sax.newSAXParser().xmlReader - val er = SAXSource(reader, InputSource(FileReader(documentFile))) +class Pom2(val pomProject: PomProject) { + companion object { + fun parse(documentFile: File, dependencyManager: DependencyManager): Either { + val jaxbContext = JAXBContext.newInstance(PomProject::class.java) + val unmarshaller = jaxbContext.createUnmarshaller() - unmarshaller.unmarshal(er) as PomProject + val sax = SAXParserFactory.newInstance() + sax.isNamespaceAware = false + val reader = sax.newSAXParser().xmlReader + val er = SAXSource(reader, InputSource(FileReader(documentFile))) + + try { + val result = unmarshaller.unmarshal(er) as PomProject + result.parent?.let { + val id = with(it) { + groupId + ":" + artifactId + ":" + version + } + val dep = dependencyManager.createMaven(id) + println("DEP: " + dep) + } + return Either(null, Pom2(result)) + } catch(ex: Exception) { + return Either(ex, null) + } + } } } @@ -122,31 +125,40 @@ class Dependencies { } class Dependency { + @JvmField var groupId: String = "" fun groupId(pom: Pom2) : String = expandVariable(groupId, pom) + @JvmField var artifactId: String = "" fun artifactId(pom: Pom2) : String = expandVariable(artifactId, pom) + @JvmField var version: String = "" fun version(pom: Pom2) : String = expandVariable(version, pom) + @JvmField var optional: String = "false" + @JvmField var scope: String = "" + @JvmField var packaging: String = "" - val id: String = "$groupId:$artifactId:$version" + fun id(pom: Pom2) = groupId(pom) + ":" + artifactId(pom) + ":" + version(pom) val mustDownload: Boolean get() = ! optional.toBoolean() && "provided" != scope && "test" != scope - val isValid : Boolean get() = ! isVariable(groupId) && ! isVariable(artifactId) && ! isVariable(version) + val isValid : Boolean get() = true //! isVariable(groupId) && ! isVariable(artifactId) && ! isVariable(version) - private fun isVariable(s: String) = s.startsWith("\${") && s.endsWith("}") + private fun extractVariable(s: String) = if (s.startsWith("\${") && s.endsWith("}")) s.substring(2, s.length - 1) + else null private fun expandVariable(s: String, pom: Pom2) : String { - if (isVariable(s)) { - println("Expanding variable $s") + val variable = extractVariable(s) + if (variable != null) { + println("Expanding variable $variable") + val value = pom.pomProject.propertyValue(variable) return s } else { return s diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt index 8bed7dee..34592646 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt @@ -37,7 +37,7 @@ class RepoFinder @Inject constructor(val executors: KobaltExecutors, val finderF localPath.substring(lastDot) result } else { - localPath + localPath } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Aether.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Aether.kt new file mode 100644 index 00000000..1638f72a --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Aether.kt @@ -0,0 +1,63 @@ +package com.beust.kobalt.maven.aether + +import com.beust.kobalt.api.Kobalt +import com.beust.kobalt.internal.KobaltSettings +import com.google.inject.Inject +import org.eclipse.aether.artifact.DefaultArtifact +import org.eclipse.aether.collection.CollectRequest +import org.eclipse.aether.graph.Dependency +import org.eclipse.aether.resolution.DependencyRequest +import org.eclipse.aether.util.artifact.JavaScopes +import org.eclipse.aether.util.filter.DependencyFilterUtils +import java.io.File + +class Aether @Inject constructor(val settings: KobaltSettings){ + fun call3() { + println("------------------------------------------------------------") + + val system = Booter.newRepositorySystem() + + val session = Booter.newRepositorySystemSession(system, File(settings.localRepo)) + + val artifact = DefaultArtifact("org.testng:testng:6.9.9") + + val classpathFlter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE) + + val collectRequest = CollectRequest() + collectRequest.root = Dependency(artifact, JavaScopes.COMPILE) + collectRequest.repositories = Booter.newRepositories(Kobalt.repos.map { it.url }) + + val dependencyRequest = DependencyRequest(collectRequest, classpathFlter) + + val artifactResults = system.resolveDependencies(session, dependencyRequest).artifactResults + + for (artifactResult in artifactResults) { + println(artifactResult.artifact.toString() + " resolved to " + artifactResult.artifact.file) + } + } + + // fun call2() { + // val request = ArtifactRequest().apply { + // artifact = DefaultArtifact(id) + // repositories = listOf(RemoteRepository("Maven", "", repo.url)) + // } + // val repoSystem = DefaultRepositorySystem().apply { + // val artifactResolver = DefaultArtifactResolver().apply { + // setRemoteRepositoryManager(DefaultRemoteRepositoryManager().apply { + // addRepositoryConnectorFactory(WagonRepositoryConnectorFactory()) + // }) + // setVersionResolver { + // p0, request -> VersionResult(request) + // } + // } + // setArtifactResolver(artifactResolver) + // } + // val session = DefaultRepositorySystemSession().apply { + // localRepositoryManager = SimpleLocalRepositoryManager(File("/Users/beust/.aether")) + // } + // val artifact = repoSystem.resolveArtifact(session, request) + // println("Artifact: " + artifact) + // } + + +} diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Booter.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Booter.kt new file mode 100644 index 00000000..e48b5bcc --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/Booter.kt @@ -0,0 +1,36 @@ +package com.beust.kobalt.maven.aether + +import org.eclipse.aether.DefaultRepositorySystemSession +import org.eclipse.aether.RepositorySystem +import org.eclipse.aether.repository.LocalRepository +import org.eclipse.aether.repository.RemoteRepository +import java.io.File + +object Booter { + + fun newRepositorySystem(): RepositorySystem { + return ManualRepositorySystemFactory.newRepositorySystem() + // return org.eclipse.aether.examples.guice.GuiceRepositorySystemFactory.newRepositorySystem(); + // return org.eclipse.aether.examples.sisu.SisuRepositorySystemFactory.newRepositorySystem(); + // return org.eclipse.aether.examples.plexus.PlexusRepositorySystemFactory.newRepositorySystem(); + } + + fun newRepositorySystemSession(system: RepositorySystem, repo: File): DefaultRepositorySystemSession { + val session = MavenRepositorySystemUtils.newSession() + + val localRepo = LocalRepository(repo.absolutePath) + session.localRepositoryManager = system.newLocalRepositoryManager(session, localRepo) + + session.transferListener = ConsoleTransferListener() + session.repositoryListener = ConsoleRepositoryListener() + + // uncomment to generate dirty trees + // session.setDependencyGraphTransformer( null ); + + return session + } + + fun newRepositories(repositories: Collection) + = repositories.map { RemoteRepository.Builder("maven", "default", it).build() } +} + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleRepositoryListener.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleRepositoryListener.kt new file mode 100644 index 00000000..4cfbaae5 --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleRepositoryListener.kt @@ -0,0 +1,88 @@ +package com.beust.kobalt.maven.aether + +import org.eclipse.aether.AbstractRepositoryListener +import org.eclipse.aether.RepositoryEvent +import java.io.PrintStream + +/** + * A simplistic repository listener that logs events to the console. + */ +class ConsoleRepositoryListener @JvmOverloads constructor(out: PrintStream? = null) : AbstractRepositoryListener() { + + private val out: PrintStream + + init { + this.out = out ?: System.out + } + + override fun artifactDeployed(event: RepositoryEvent?) { + out.println("Deployed " + event!!.artifact + " to " + event.repository) + } + + override fun artifactDeploying(event: RepositoryEvent?) { + out.println("Deploying " + event!!.artifact + " to " + event.repository) + } + + override fun artifactDescriptorInvalid(event: RepositoryEvent?) { + out.println("Invalid artifact descriptor for " + event!!.artifact + ": " + + event.exception.message) + } + + override fun artifactDescriptorMissing(event: RepositoryEvent?) { + out.println("Missing artifact descriptor for " + event!!.artifact) + } + + override fun artifactInstalled(event: RepositoryEvent?) { + out.println("Installed " + event!!.artifact + " to " + event.file) + } + + override fun artifactInstalling(event: RepositoryEvent?) { + out.println("Installing " + event!!.artifact + " to " + event.file) + } + + override fun artifactResolved(event: RepositoryEvent?) { + out.println("Resolved artifact " + event!!.artifact + " from " + event.repository) + } + + override fun artifactDownloading(event: RepositoryEvent?) { + out.println("Downloading artifact " + event!!.artifact + " from " + event.repository) + } + + override fun artifactDownloaded(event: RepositoryEvent?) { + out.println("Downloaded artifact " + event!!.artifact + " from " + event.repository) + } + + override fun artifactResolving(event: RepositoryEvent?) { + out.println("Resolving artifact " + event!!.artifact) + } + + override fun metadataDeployed(event: RepositoryEvent?) { + out.println("Deployed " + event!!.metadata + " to " + event.repository) + } + + override fun metadataDeploying(event: RepositoryEvent?) { + out.println("Deploying " + event!!.metadata + " to " + event.repository) + } + + override fun metadataInstalled(event: RepositoryEvent?) { + out.println("Installed " + event!!.metadata + " to " + event.file) + } + + override fun metadataInstalling(event: RepositoryEvent?) { + out.println("Installing " + event!!.metadata + " to " + event.file) + } + + override fun metadataInvalid(event: RepositoryEvent?) { + out.println("Invalid metadata " + event!!.metadata) + } + + override fun metadataResolved(event: RepositoryEvent?) { + out.println("Resolved metadata " + event!!.metadata + " from " + event.repository) + } + + override fun metadataResolving(event: RepositoryEvent?) { + out.println("Resolving metadata " + event!!.metadata + " from " + event.repository) + } + +} + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleTransferListener.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleTransferListener.kt new file mode 100644 index 00000000..23833239 --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ConsoleTransferListener.kt @@ -0,0 +1,124 @@ +package com.beust.kobalt.maven.aether + +import org.eclipse.aether.transfer.AbstractTransferListener +import org.eclipse.aether.transfer.MetadataNotFoundException +import org.eclipse.aether.transfer.TransferEvent +import org.eclipse.aether.transfer.TransferResource +import java.io.PrintStream +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class ConsoleTransferListener @JvmOverloads constructor(out: PrintStream? = null) : AbstractTransferListener() { + + private val out: PrintStream + + private val downloads = ConcurrentHashMap() + + private var lastLength: Int = 0 + + init { + this.out = out ?: System.out + } + + override fun transferInitiated(event: TransferEvent?) { + val message = if (event!!.requestType == TransferEvent.RequestType.PUT) "Uploading" else "Downloading" + + out.println(message + ": " + event.resource.repositoryUrl + event.resource.resourceName) + } + + override fun transferProgressed(event: TransferEvent?) { + val resource = event!!.resource + downloads.put(resource, java.lang.Long.valueOf(event.transferredBytes)) + + val buffer = StringBuilder(64) + + for (entry in downloads.entries) { + val total = entry.key.contentLength + val complete = entry.value.toLong() + + buffer.append(getStatus(complete, total)).append(" ") + } + + val pad = lastLength - buffer.length + lastLength = buffer.length + pad(buffer, pad) + buffer.append('\r') + + out.print(buffer) + } + + private fun getStatus(complete: Long, total: Long): String { + if (total >= 1024) { + return toKB(complete).toString() + "/" + toKB(total) + " KB " + } else if (total >= 0) { + return complete.toString() + "/" + total + " B " + } else if (complete >= 1024) { + return toKB(complete).toString() + " KB " + } else { + return complete.toString() + " B " + } + } + + private fun pad(buffer: StringBuilder, spaces: Int) { + var spaces = spaces + val block = " " + while (spaces > 0) { + val n = Math.min(spaces, block.length) + buffer.append(block, 0, n) + spaces -= n + } + } + + override fun transferSucceeded(event: TransferEvent) { + transferCompleted(event) + + val resource = event.resource + val contentLength = event.transferredBytes + if (contentLength >= 0) { + val type = if (event.requestType == TransferEvent.RequestType.PUT) "Uploaded" else "Downloaded" + val len = if (contentLength >= 1024) toKB(contentLength).toString() + " KB" + else contentLength.toString() + " B" + + var throughput = "" + val duration = System.currentTimeMillis() - resource.transferStartTime + if (duration > 0) { + val bytes = contentLength - resource.resumeOffset + val format = DecimalFormat("0.0", DecimalFormatSymbols(Locale.ENGLISH)) + val kbPerSec = bytes / 1024.0 / (duration / 1000.0) + throughput = " at " + format.format(kbPerSec) + " KB/sec" + } + + out.println(type + ": " + resource.repositoryUrl + resource.resourceName + " (" + len + + throughput + ")") + } + } + + override fun transferFailed(event: TransferEvent) { + transferCompleted(event) + + if (event.exception !is MetadataNotFoundException) { + event.exception.printStackTrace(out) + } + } + + private fun transferCompleted(event: TransferEvent) { + downloads.remove(event.resource) + + val buffer = StringBuilder(64) + pad(buffer, lastLength) + buffer.append('\r') + out.print(buffer) + } + + override fun transferCorrupted(event: TransferEvent?) { + event!!.exception.printStackTrace(out) + } + + protected fun toKB(bytes: Long): Long { + return (bytes + 1023) / 1024 + } + +} + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ManualRepositorySystemFactory.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ManualRepositorySystemFactory.kt new file mode 100644 index 00000000..fc21c0de --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/ManualRepositorySystemFactory.kt @@ -0,0 +1,39 @@ +package com.beust.kobalt.maven.aether + +import org.eclipse.aether.RepositorySystem +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory +import org.eclipse.aether.impl.DefaultServiceLocator +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory +import org.eclipse.aether.spi.connector.transport.TransporterFactory +import org.eclipse.aether.transport.file.FileTransporterFactory +import org.eclipse.aether.transport.http.HttpTransporterFactory + +/** + * A factory for repository system instances that employs Aether's built-in service locator infrastructure to wire up + * the system's components. + */ +object ManualRepositorySystemFactory { + + fun newRepositorySystem(): RepositorySystem { + /* + * Aether's components implement org.eclipse.aether.spi.locator.Service to ease manual wiring and using the + * prepopulated DefaultServiceLocator, we only need to register the repository connector and transporter + * factories. + */ + val locator = MavenRepositorySystemUtils.newServiceLocator() + locator.addService(RepositoryConnectorFactory::class.java, BasicRepositoryConnectorFactory::class.java) + locator.addService(TransporterFactory::class.java, FileTransporterFactory::class.java) + locator.addService(TransporterFactory::class.java, HttpTransporterFactory::class.java) + + locator.setErrorHandler(object : DefaultServiceLocator.ErrorHandler() { + override fun serviceCreationFailed(type: Class<*>, impl: Class<*>, exception: Throwable) { + exception.printStackTrace() + } + }) + + return locator.getService(RepositorySystem::class.java) + } + +} + + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/MavenRepositorySystemUtils.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/MavenRepositorySystemUtils.kt new file mode 100644 index 00000000..2b6688a9 --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/MavenRepositorySystemUtils.kt @@ -0,0 +1,61 @@ +package com.beust.kobalt.maven.aether + +import org.apache.maven.repository.internal.* +import org.eclipse.aether.DefaultRepositorySystemSession +import org.eclipse.aether.artifact.DefaultArtifactType +import org.eclipse.aether.impl.* +import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry +import org.eclipse.aether.util.graph.manager.ClassicDependencyManager +import org.eclipse.aether.util.graph.selector.AndDependencySelector +import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector +import org.eclipse.aether.util.graph.selector.OptionalDependencySelector +import org.eclipse.aether.util.graph.selector.ScopeDependencySelector +import org.eclipse.aether.util.graph.transformer.* +import org.eclipse.aether.util.graph.traverser.FatArtifactTraverser +import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy + +object MavenRepositorySystemUtils { + + fun newServiceLocator(): DefaultServiceLocator { + val locator = DefaultServiceLocator() + locator.addService(ArtifactDescriptorReader::class.java, DefaultArtifactDescriptorReader::class.java) + locator.addService(VersionResolver::class.java, DefaultVersionResolver::class.java) + locator.addService(VersionRangeResolver::class.java, DefaultVersionRangeResolver::class.java) + locator.addService(MetadataGeneratorFactory::class.java, SnapshotMetadataGeneratorFactory::class.java) + locator.addService(MetadataGeneratorFactory::class.java, VersionsMetadataGeneratorFactory::class.java) + return locator + } + + fun newSession(): DefaultRepositorySystemSession { + val session = DefaultRepositorySystemSession() + val depTraverser = FatArtifactTraverser() + session.dependencyTraverser = depTraverser + val depManager = ClassicDependencyManager() + session.dependencyManager = depManager + val depFilter = AndDependencySelector(*arrayOf(ScopeDependencySelector(*arrayOf("test", "provided")), OptionalDependencySelector(), ExclusionDependencySelector())) + session.dependencySelector = depFilter + val transformer = ConflictResolver(NearestVersionSelector(), JavaScopeSelector(), SimpleOptionalitySelector(), JavaScopeDeriver()) + ChainedDependencyGraphTransformer(*arrayOf(transformer, JavaDependencyContextRefiner())) + session.dependencyGraphTransformer = transformer + val stereotypes = DefaultArtifactTypeRegistry() + stereotypes.add(DefaultArtifactType("pom")) + stereotypes.add(DefaultArtifactType("maven-plugin", "jar", "", "java")) + stereotypes.add(DefaultArtifactType("jar", "jar", "", "java")) + stereotypes.add(DefaultArtifactType("ejb", "jar", "", "java")) + stereotypes.add(DefaultArtifactType("ejb-client", "jar", "client", "java")) + stereotypes.add(DefaultArtifactType("test-jar", "jar", "tests", "java")) + stereotypes.add(DefaultArtifactType("javadoc", "jar", "javadoc", "java")) + stereotypes.add(DefaultArtifactType("java-source", "jar", "sources", "java", false, false)) + stereotypes.add(DefaultArtifactType("war", "war", "", "java", false, true)) + stereotypes.add(DefaultArtifactType("ear", "ear", "", "java", false, true)) + stereotypes.add(DefaultArtifactType("rar", "rar", "", "java", false, true)) + stereotypes.add(DefaultArtifactType("par", "par", "", "java", false, true)) + session.artifactTypeRegistry = stereotypes + session.artifactDescriptorPolicy = SimpleArtifactDescriptorPolicy(true, true) + val sysProps = System.getProperties() + session.setSystemProperties(sysProps) + session.setConfigProperties(sysProps) + return session + } +} + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/dependency/MavenDependency.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/dependency/MavenDependency.kt index a2df2042..6985b691 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/dependency/MavenDependency.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/dependency/MavenDependency.kt @@ -25,7 +25,7 @@ class MavenDependency @Inject constructor( @Assisted("downloadJavadocs") val downloadJavadocs: Boolean, override val localRepo: LocalRepo, val repoFinder: RepoFinder, - val pomFactory: Pom.IFactory, + val dependencyManager: DependencyManager, val downloadManager: DownloadManager) : LocalDep(mavenId, localRepo), IClasspathDependency, Comparable { override var jarFile: Future by Delegates.notNull() @@ -120,19 +120,21 @@ class MavenDependency @Inject constructor( override fun directDependencies() : List { val result = arrayListOf() - try { - val pom = Pom2(pomFile.get()) - pom.pom.dependencies.filter { + val maybePom = Pom2.parse(pomFile.get(), dependencyManager) + if (maybePom.value != null) { + val pom = maybePom.value + pom.pomProject.dependencies.filter { it.mustDownload }.forEach { if (it.isValid) { result.add(create(MavenId.toId(it.groupId(pom), it.artifactId(pom), it.packaging, it.version(pom)))) } else { - log(2, "Skipping invalid id: ${it.id}") + log(2, "Skipping invalid id: ${it.id(pom)}") } } - } catch(ex: Exception) { - warn("Exception when trying to resolve dependencies for $id: " + ex.message) + } else { + warn("Couldn't parse POM file ${pomFile.get()}: " + maybePom.exception?.message, maybePom.exception!!) + } return result } diff --git a/src/test/kotlin/com/beust/kobalt/maven/DownloadTest.kt b/src/test/kotlin/com/beust/kobalt/maven/DownloadTest.kt index ab1f2055..ea2584fb 100644 --- a/src/test/kotlin/com/beust/kobalt/maven/DownloadTest.kt +++ b/src/test/kotlin/com/beust/kobalt/maven/DownloadTest.kt @@ -2,6 +2,7 @@ package com.beust.kobalt.maven import com.beust.kobalt.HostConfig import com.beust.kobalt.KobaltTest +import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.maven.dependency.MavenDependency import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.Version @@ -23,6 +24,7 @@ class DownloadTest @Inject constructor( val localRepo: LocalRepo, val mdFactory: MavenDependency.IFactory, val dependencyManager: DependencyManager, + val settings: KobaltSettings, val executors: KobaltExecutors) : KobaltTest() { private var executor: ExecutorService by Delegates.notNull() @@ -173,5 +175,24 @@ class DownloadTest @Inject constructor( val d = closure.filter { it.id.contains("eclipse-collections-api")} Assert.assertEquals(d.size, 1) } + + @Test + fun containerPom() { + val repoResult = RepoFinderCallable("org.jetbrains.kotlin:kotlin-project:1.0.0", + HostConfig("http://repo1.maven.org/maven2/"), + localRepo, dependencyManager, settings).call() + val rr = repoResult[0] + Assert.assertTrue(rr.found) + Assert.assertTrue(rr.localPath != null && rr.localPath!!.startsWith("junit/junit")) + Assert.assertEquals(rr.version.toString(), "4.12") + } + + @Test + fun containerPom3() { + val pom = Pom2.parse( + File("/Users/beust/kotlin/kobalt/src/test/resources/guice-parent-4.0.pom"), dependencyManager) + println("POM: ${pom.value?.pomProject}") + println("") + } }