All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.buildinit.plugins.internal.maven.Maven2Gradle.groovy Maven / Gradle / Ivy

There is a newer version: 8.11.1
Show newest version
/*
 * Copyright 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



package org.gradle.buildinit.plugins.internal.maven

import groovy.util.slurpersupport.GPathResult
import org.apache.maven.project.MavenProject
import org.gradle.api.artifacts.ModuleIdentifier
import org.gradle.api.internal.artifacts.DefaultModuleIdentifier
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.util.RelativePathUtil

/**
 * This script obtains the effective POM of the current project, reads its dependencies
 * and generates build.gradle scripts. It also generates settings.gradle for multimodule builds. 
* * It currently supports both single-module and multi-module POMs, inheritance, dependency management, properties - everything. */ class Maven2Gradle { def dependentWars = [] def qualifiedNames def workingDir def effectivePom Logger logger = Logging.getLogger(getClass()) private Set mavenProjects Maven2Gradle(Set mavenProjects, File workingDir) { assert !mavenProjects.empty: "No Maven projects provided." this.mavenProjects = mavenProjects this.workingDir = workingDir.canonicalFile; } def convert() { //For now we're building the effective POM XML from the model //and then we parse the XML using slurper. //This way we don't have to rewrite the Maven2Gradle just yet. //Maven2Gradle should be rewritten (with coverage) so that feeds of the maven object model, not XML. def effectivePom = new MavenProjectXmlWriter().toXml(mavenProjects) //use the Groovy XmlSlurper library to parse the text string this.effectivePom = new XmlSlurper().parseText(effectivePom) String build def multimodule = this.effectivePom.name() == "projects" if (multimodule) { def allProjects = this.effectivePom.project qualifiedNames = generateSettings(workingDir.getName(), allProjects[0].artifactId, allProjects); def dependencies = [:]; allProjects.each { project -> dependencies[project.artifactId.text()] = getDependencies(project, allProjects) } def commonDeps = dependencies.get(allProjects[0].artifactId.text()) build = """allprojects { apply plugin: 'maven' ${getArtifactData(allProjects[0])} } subprojects { apply plugin: 'java' ${compilerSettings(allProjects[0], " ")} ${packageSources(allProjects[0])} ${getRepositoriesForProjects(allProjects)} ${globalExclusions(allProjects[0])} ${commonDeps} ${testNg(commonDeps)} } """ modules(allProjects, false).each { module -> def id = module.artifactId.text() String moduleDependencies = dependencies.get(id) boolean warPack = module.packaging.text().equals("war") def hasDependencies = !(moduleDependencies == null || moduleDependencies.length() == 0) File submoduleBuildFile = new File(projectDir(module), 'build.gradle') def group = '' if (module.groupId != allProjects[0].groupId) { group = "group = '${module.groupId}'" } String moduleBuild = "${group}\n" if (warPack) { moduleBuild += """apply plugin: 'war' """ if (dependentWars.any { project -> project.groupId.text() == module.groupId.text() && project.artifactId.text() == id }) { moduleBuild += """jar.enabled = true """ } } if (module.name) { moduleBuild += "description = '${module.name}'\n" } if (hasDependencies) { moduleBuild += moduleDependencies } moduleBuild += testNg(moduleDependencies) if (submoduleBuildFile.exists()) { submoduleBuildFile.renameTo(new File(projectDir(module), "build.gradle.bak")) } def packageTests = packageTests(module); if (packageTests) { moduleBuild += packageTests; } logger.debug("writing build.gradle file at ${submoduleBuildFile.absolutePath}"); submoduleBuildFile.text = moduleBuild } //TODO deployment } else {//simple build = """apply plugin: 'java' apply plugin: 'maven' ${getArtifactData(this.effectivePom)} description = \"""${this.effectivePom.name}\""" ${compilerSettings(this.effectivePom, "")} ${globalExclusions(this.effectivePom)} """ Set repoSet = new LinkedHashSet(); getRepositoriesForModule(this.effectivePom, repoSet) String repos = """repositories { $localRepoUri """ repoSet.each { repos = "${repos} ${it}\n" } build += "${repos}}\n" String dependencies = getDependencies(this.effectivePom, null) build += dependencies String packageTests = packageTests(this.effectivePom); if (packageTests) { build += '//packaging tests' build += packageTests; } generateSettings(workingDir.getName(), this.effectivePom.artifactId, null); } def buildFile = new File(workingDir, "build.gradle") if (buildFile.exists()) { buildFile.renameTo(new File(workingDir, "build.gradle.bak")) } logger.debug("writing build.gradle file at ${buildFile.absolutePath}"); buildFile.text = build } def globalExclusions = { project -> def exclusions = '' def enforcerPlugin = plugin('maven-enforcer-plugin', project) def enforceGoal = pluginGoal('enforce', enforcerPlugin) if (enforceGoal) { exclusions += 'configurations.all {\n' enforceGoal.configuration.rules.bannedDependencies.excludes.childNodes().each { def tokens = it.text().tokenize(':') exclusions += "it.exclude group: '${tokens[0]}'" if (tokens.size() > 1 && tokens[1] != '*') { exclusions += ", module: '${tokens[1]}'" } exclusions += '\n' } } exclusions = exclusions ? exclusions += '}' : exclusions exclusions } def testNg = { moduleDependencies -> if (moduleDependencies.contains('testng')) { """test.useTestNG() """ } else { '' } } def modules = { allProjects, incReactors -> return allProjects.findAll { project -> def parentIsPartOfThisBuild = allProjects.find { proj -> proj.artifactId == project.parent.artifactId && proj.groupId == project.parent.groupId } project.parent.text().length() > 0 && parentIsPartOfThisBuild && (incReactors || project.packaging.text() != 'pom') } } def fqn = { project, allProjects -> def buffer = new StringBuilder() generateFqn(project, allProjects, buffer) return buffer.toString() } private generateFqn(GPathResult project, GPathResult allProjects, StringBuilder buffer) { def artifactId = project.artifactId.text() buffer.insert(0, ":${artifactId}") //we don't need the top-level parent in gradle, so we stop on it if (getModuleIdentifier(project.parent) != getModuleIdentifier(allProjects[0])) { def parentInBuild = allProjects.find { proj -> getModuleIdentifier(proj) == getModuleIdentifier(project.parent) } if (parentInBuild) { generateFqn(parentInBuild, allProjects, buffer) } } } private ModuleIdentifier getModuleIdentifier(GPathResult project) { def artifactId = project.artifactId.text() def groupId = project.groupId ? project.groupId.text() : project.parent.groupId.text() return new DefaultModuleIdentifier(groupId, artifactId) } def localRepoUri = { """mavenLocal() """ } private String getArtifactData(project) { return """group = '$project.groupId' version = '$project.version'"""; } private String getRepositoriesForProjects(projects) { String repos = """repositories { ${localRepoUri()} """ def repoSet = new LinkedHashSet(); projects.each { getRepositoriesForModule(it, repoSet) } repoSet.each { repos = "${repos}${it}\n" } repos = "${repos} }\n" return repos } private void getRepositoriesForModule(module, repoSet) { module.repositories.repository.each { repoSet.add(" maven { url \"${it.url}\" }") } //No need to include plugin repos - who cares about maven plugins? } private String getDependencies(project, allProjects) { // use GPath to navigate the object hierarchy and retrieve the collection of dependency nodes. def dependencies = project.dependencies.dependency def war = project.packaging == "war" def compileTimeScope = [] def runTimeScope = [] def testScope = [] def providedScope = [] def systemScope = [] //cleanup duplicates from parent // using Groovy Looping and mapping a Groovy Closure to each element, we collect together all // the dependency nodes into corresponding collections depending on their scope value. dependencies.each() { if (!duplicateDependency(it, project, allProjects)) { def scope = (elementHasText(it.scope)) ? it.scope : "compile" switch (scope) { case "compile": compileTimeScope.add(it) break case "test": testScope.add(it) break case "provided": providedScope.add(it) break case "runtime": runTimeScope.add(it) break case "system": systemScope.add(it) break } } } /** * print function then checks the exclusions node to see if it exists, if * so it branches off, otherwise we call our simple print function */ def createGradleDep = { String scope, StringBuilder sb, mavenDependency -> def projectDep = allProjects.find { prj -> return prj.artifactId.text() == mavenDependency.artifactId.text() && prj.groupId.text() == mavenDependency.groupId.text() } if (projectDep) { createProjectDependency(projectDep, sb, scope, allProjects) } else { if (!war && scope == 'providedCompile') { scope = 'compileOnly' } def exclusions = mavenDependency.exclusions.exclusion if (exclusions.size() > 0) { createComplexDependency(mavenDependency, sb, scope) } else { createBasicDependency(mavenDependency, sb, scope) } } } StringBuilder build = new StringBuilder() if (!compileTimeScope.isEmpty() || !runTimeScope.isEmpty() || !testScope.isEmpty() || !providedScope.isEmpty() || !systemScope.isEmpty()) { build.append("dependencies {").append("\n") // for each collection, one at a time, we take each element and call our print function if (!compileTimeScope.isEmpty()) { compileTimeScope.each() { createGradleDep("compile", build, it) } } if (!runTimeScope.isEmpty()) { runTimeScope.each() { createGradleDep("runtime", build, it) } } if (!testScope.isEmpty()) { testScope.each() { createGradleDep("testCompile", build, it) } } if (!providedScope.isEmpty()) { providedScope.each() { createGradleDep("providedCompile", build, it) } } if (!systemScope.isEmpty()) { systemScope.each() { createGradleDep("system", build, it) } } build.append("}\n") } return build.toString(); } def compilerSettings = { project, indent -> def configuration = plugin('maven-compiler-plugin', project).configuration def settings = new StringBuilder() settings.append "sourceCompatibility = ${configuration.source.text() ?: '1.5'}\n" settings.append "${indent}targetCompatibility = ${configuration.target.text() ?: '1.5'}\n" def encoding = project.properties.'project.build.sourceEncoding'.text() if (encoding) { settings.append "${indent}tasks.withType(JavaCompile) {\n" settings.append "${indent}\toptions.encoding = '${encoding}'\n" settings.append "${indent}}\n" } return settings } def plugin = { artifactId, project -> project.build.plugins.plugin.find { pluginTag -> pluginTag.artifactId.text() == artifactId } } def pluginGoal = { goalName, plugin -> plugin.executions.execution.find { exec -> exec.goals.goal.find { gl -> gl.text().startsWith(goalName) } } } def packSources = { sourceSets -> def sourceSetStr = '' if (!sourceSets.empty) { sourceSetStr = """task packageSources(type: Jar) { classifier = 'sources' """ sourceSets.each { sourceSet -> sourceSetStr += """from sourceSets.${sourceSet}.allSource """ } sourceSetStr += """ } artifacts.archives packageSources""" } sourceSetStr } def packageTests = { project -> def jarPlugin = plugin('maven-jar-plugin', project) pluginGoal('test-jar', jarPlugin) ? """ task packageTests(type: Jar) { from sourceSets.test.output classifier = 'tests' } artifacts.archives packageTests """ : '' } def packageSources = { project -> def sourcePlugin = plugin('maven-source-plugin', project) def sourceSets = [] if (sourcePlugin) { if (pluginGoal('jar', sourcePlugin)) { sourceSets += 'main' } else if (pluginGoal('test-jar', sourcePlugin)) { sourceSets += 'test' } } packSources(sourceSets) } private boolean duplicateDependency(dependency, project, allProjects) { def parentTag = project.parent if (allProjects == null || parentTag.isEmpty()) {//simple project or no parent return false; } else { def parent = allProjects.find { it.groupId.equals(parentTag.groupId) && it.artifactId.equals(parentTag.artifactId) } def duplicate = parent.dependencies.dependency.any { it.groupId.equals(dependency.groupId) && it.artifactId.equals(dependency.artifactId) } if (duplicate) { return true; } else { duplicateDependency(dependency, parent, allProjects) } } } def artifactId = { File dir -> return new XmlSlurper().parse(new File(dir, 'pom.xml')).artifactId.text() } def projectDir = { project -> return new File(project.build.directory.text()).parentFile } private def generateSettings(def dirName, def mvnProjectName, def projects) { def qualifiedNames = [:] def projectName = ""; if (dirName != mvnProjectName) { projectName = """rootProject.name = '${mvnProjectName}' """ } def modulePoms = modules(projects, true) List moduleNames = new ArrayList(); def artifactIdToDir = [:] if (projects) { modulePoms.each { project -> def fqn = fqn(project, projects) File projectDirectory = projectDir(project) // don't add project if it's the rootproject if (!workingDir.equals(projectDirectory)) { artifactIdToDir[fqn] = RelativePathUtil.relativePath(workingDir, projectDirectory) moduleNames.add(fqn) } } } File settingsFile = new File(workingDir, "settings.gradle") if (settingsFile.exists()) { settingsFile.renameTo(new File(workingDir, "settings.gradle.bak")) } StringBuffer settingsText = new StringBuffer(projectName) if (moduleNames.size() > 0) { moduleNames.each { settingsText.append("include '$it'\n") } } artifactIdToDir.each { entry -> settingsText.append(""" project('$entry.key').projectDir = """ + '"$rootDir/' + "${entry.value}" + '" as File') } settingsFile.text = settingsText.toString() return qualifiedNames } /** * complex print statement does one extra task which is * iterate over each node and print out the artifact id. * It also provides review comments for the user. */ private def createComplexDependency(it, build, scope) { build.append(" ${scope}(${contructSignature(it)}) {\n") it.exclusions.exclusion.each() { build.append("exclude(module: '${it.artifactId}')\n") } build.append(" }\n") } /** * Print out the basic form og gradle dependency */ private def createBasicDependency(mavenDependency, build, String scope) { def classifier = contructSignature(mavenDependency) build.append(" ${scope} ${classifier}\n") } /** * Print out the basic form of gradle dependency */ private def createProjectDependency(projectDep, build, String scope, allProjects) { if (projectDep.packaging.text() == 'war') { dependentWars += projectDep } build.append(" ${scope} project('${fqn(projectDep, allProjects)}')\n") } /** * Construct and return the signature of a dependency, including its version and * classifier if it exists */ private def contructSignature(mavenDependency) { def gradelDep = "group: '${mavenDependency.groupId.text()}', name: '${mavenDependency.artifactId.text()}', version:'${mavenDependency?.version?.text()}'" def classifier = elementHasText(mavenDependency.classifier) ? gradelDep + ", classifier:'" + mavenDependency.classifier.text().trim() + "'" : gradelDep return classifier } /** * Check to see if the selected node has content */ private boolean elementHasText(it) { return it.text().length() != 0 } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy