Browse Source
This commit merges back the "spring-beans-groovy" module into the main "spring-beans" one. The build is configured so: * Java and Groovy sources are jointly compiled * Kotlin sources are compiled after With this change, the `MergePlugin` is not used anymore in the project build and therefore is removed. The `DetectSplitPackagesPlugin` wasn't applied so it's been removed as well. Issue: SPR-15885pull/1503/head
11 changed files with 33 additions and 398 deletions
@ -1,158 +0,0 @@
@@ -1,158 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 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.springframework.build.gradle |
||||
|
||||
import org.gradle.api.DefaultTask |
||||
import org.gradle.api.GradleException |
||||
import org.gradle.api.Plugin |
||||
import org.gradle.api.Project |
||||
import org.gradle.api.Task |
||||
import org.gradle.api.tasks.Input |
||||
import org.gradle.api.tasks.TaskAction |
||||
|
||||
|
||||
/** |
||||
* Gradle plugin that detects identically named, non-empty packages split across multiple |
||||
* subprojects, e.g. "org.springframework.context.annotation" existing in both spring-core |
||||
* and spring-aspects. Adds a 'detectSplitPackages' task to the current project's task |
||||
* collection. If the project already contains a 'check' task (i.e. is a typical Gradle |
||||
* project with the "java" plugin applied), the 'check' task will be updated to depend on |
||||
* the execution of 'detectSplitPackages'. |
||||
* |
||||
* By default, all subprojects will be scanned. Use the 'projectsToScan' task property to |
||||
* modify this value. Example usage: |
||||
* |
||||
* apply plugin: 'detect-split-packages // typically applied to root project |
||||
* |
||||
* detectSplitPackages { |
||||
* packagesToScan -= project(":spring-xyz") // scan every project but spring-xyz |
||||
* } |
||||
* |
||||
* @author Rob Winch |
||||
* @author Glyn Normington |
||||
* @author Chris Beams |
||||
*/ |
||||
public class DetectSplitPackagesPlugin implements Plugin<Project> { |
||||
public void apply(Project project) { |
||||
def tasks = project.tasks |
||||
Task detectSplitPackages = tasks.create("detectSplitPackages", DetectSplitPackagesTask.class) |
||||
if (tasks.asMap.containsKey("check")) { |
||||
tasks.getByName("check").dependsOn detectSplitPackages |
||||
} |
||||
} |
||||
} |
||||
|
||||
public class DetectSplitPackagesTask extends DefaultTask { |
||||
|
||||
private static final String JAVA_FILE_SUFFIX = ".java" |
||||
private static final String PACKAGE_SEPARATOR = "." |
||||
private static final String HIDDEN_DIRECTORY_PREFIX = "." |
||||
|
||||
@Input |
||||
Set<Project> projectsToScan = project.subprojects |
||||
|
||||
public DetectSplitPackagesTask() { |
||||
this.group = "Verification" |
||||
this.description = "Detects packages split across two or more subprojects." |
||||
} |
||||
|
||||
@TaskAction |
||||
public void detectSplitPackages() { |
||||
def splitPackages = doDetectSplitPackages() |
||||
if (!splitPackages.isEmpty()) { |
||||
def message = "The following split package(s) have been detected:\n" |
||||
splitPackages.each { pkg, mod -> |
||||
message += " - ${pkg} (split across ${mod[0].name} and ${mod[1].name})\n" |
||||
} |
||||
throw new GradleException(message) |
||||
} |
||||
} |
||||
|
||||
private Map<String, List<Project>> doDetectSplitPackages() { |
||||
def splitPackages = [:] |
||||
def mergedProjects = findMergedProjects() |
||||
def packagesByProject = mapPackagesByProject() |
||||
|
||||
def projects = packagesByProject.keySet().toArray() |
||||
def nProjects = projects.length |
||||
|
||||
for (int i = 0; i < nProjects - 1; i++) { |
||||
for (int j = i + 1; j < nProjects - 1; j++) { |
||||
def prj_i = projects[i] |
||||
def prj_j = projects[j] |
||||
|
||||
def pkgs_i = new HashSet(packagesByProject.get(prj_i)) |
||||
def pkgs_j = packagesByProject.get(prj_j) |
||||
pkgs_i.retainAll(pkgs_j) |
||||
|
||||
if (!pkgs_i.isEmpty() |
||||
&& mergedProjects.get(prj_i) != prj_j |
||||
&& mergedProjects.get(prj_j) != prj_i) { |
||||
pkgs_i.each { pkg -> |
||||
def readablePkg = pkg.substring(1).replaceAll(File.separator, PACKAGE_SEPARATOR) |
||||
splitPackages[readablePkg] = [prj_i, prj_j] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return splitPackages; |
||||
} |
||||
|
||||
private Map<Project, Set<String>> mapPackagesByProject() { |
||||
def packagesByProject = [:] |
||||
this.projectsToScan.each { Project p -> |
||||
def packages = new HashSet<String>() |
||||
p.sourceSets.main.java.srcDirs.each { File dir -> |
||||
findPackages(packages, dir, "") |
||||
} |
||||
if (!packages.isEmpty()) { |
||||
packagesByProject.put(p, packages) |
||||
} |
||||
} |
||||
return packagesByProject; |
||||
} |
||||
|
||||
private Map<Project, Project> findMergedProjects() { |
||||
def mergedProjects = [:] |
||||
this.projectsToScan.findAll { p -> |
||||
p.plugins.findPlugin(MergePlugin) |
||||
}.findAll { p -> |
||||
p.merge.into |
||||
}.each { p -> |
||||
mergedProjects.put(p, p.merge.into) |
||||
} |
||||
return mergedProjects |
||||
} |
||||
|
||||
private static void findPackages(Set<String> packages, File dir, String packagePath) { |
||||
def scanDir = new File(dir, packagePath) |
||||
def File[] javaFiles = scanDir.listFiles({ file -> |
||||
!file.isDirectory() && file.name.endsWith(JAVA_FILE_SUFFIX) |
||||
} as FileFilter) |
||||
|
||||
if (javaFiles != null && javaFiles.length != 0) { |
||||
packages.add(packagePath) |
||||
} |
||||
|
||||
scanDir.listFiles({ File file -> |
||||
file.isDirectory() && !file.name.startsWith(HIDDEN_DIRECTORY_PREFIX) |
||||
} as FileFilter).each { File subDir -> |
||||
findPackages(packages, dir, packagePath + File.separator + subDir.name) |
||||
} |
||||
} |
||||
} |
||||
|
||||
@ -1,177 +0,0 @@
@@ -1,177 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2015 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.springframework.build.gradle |
||||
|
||||
import org.gradle.api.* |
||||
import org.gradle.api.artifacts.Configuration |
||||
import org.gradle.api.artifacts.ProjectDependency; |
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping |
||||
import org.gradle.api.plugins.MavenPlugin |
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin |
||||
import org.gradle.plugins.ide.idea.IdeaPlugin |
||||
import org.gradle.api.invocation.* |
||||
|
||||
/** |
||||
* Gradle plugin that allows projects to merged together. Primarily developed to |
||||
* allow Spring to support multiple incompatible versions of third-party |
||||
* dependencies (for example Hibernate v3 and v4). |
||||
* <p> |
||||
* The 'merge' extension should be used to define how projects are merged, for example: |
||||
* <pre class="code"> |
||||
* configure(subprojects) { |
||||
* apply plugin: MergePlugin |
||||
* } |
||||
* |
||||
* project("myproject") { |
||||
* } |
||||
* |
||||
* project("myproject-extra") { |
||||
* merge.into = project("myproject") |
||||
* } |
||||
* </pre> |
||||
* <p> |
||||
* This plugin adds two new configurations: |
||||
* <ul> |
||||
* <li>merging - Contains the projects being merged into this project<li> |
||||
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used |
||||
* to allow an IDE to reference merge projects.</li> |
||||
* <ul> |
||||
* |
||||
* @author Rob Winch |
||||
* @author Phillip Webb |
||||
*/ |
||||
class MergePlugin implements Plugin<Project> { |
||||
|
||||
private static boolean attachedProjectsEvaluated; |
||||
|
||||
public void apply(Project project) { |
||||
project.plugins.apply(MavenPlugin) |
||||
project.plugins.apply(EclipsePlugin) |
||||
project.plugins.apply(IdeaPlugin) |
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel) |
||||
model.project = project |
||||
project.configurations.create("merging") |
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge") |
||||
|
||||
// Ensure the IDE can reference merged projects |
||||
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ] |
||||
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ] |
||||
|
||||
// Hook to perform the actual merge logic |
||||
project.afterEvaluate{ |
||||
if (it.merge.into != null) { |
||||
setup(it) |
||||
} |
||||
setupIdeDependencies(it) |
||||
} |
||||
|
||||
// Hook to build runtimeMerge dependencies |
||||
if (!attachedProjectsEvaluated) { |
||||
project.gradle.projectsEvaluated{ |
||||
postProcessProjects(it) |
||||
} |
||||
attachedProjectsEvaluated = true; |
||||
} |
||||
} |
||||
|
||||
private void setup(Project project) { |
||||
project.merge.into.dependencies.add("merging", project) |
||||
project.dependencies.add("provided", project.merge.into.sourceSets.main.output) |
||||
project.dependencies.add("runtimeMerge", project.merge.into) |
||||
setupTaskDependencies(project) |
||||
setupMaven(project) |
||||
} |
||||
|
||||
private void setupTaskDependencies(Project project) { |
||||
// invoking a task will invoke the task with the same name on 'into' project |
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each { |
||||
def task = project.tasks.findByPath(it) |
||||
if (task) { |
||||
task.enabled = false |
||||
task.dependsOn(project.merge.into.tasks.findByPath(it)) |
||||
} |
||||
} |
||||
|
||||
// update 'into' project artifacts to contain the source artifact contents |
||||
project.merge.into.sourcesJar.from(project.sourcesJar.source) |
||||
project.merge.into.jar.from(project.sourceSets.main.output) |
||||
project.merge.into.javadoc { |
||||
source += project.javadoc.source |
||||
classpath += project.javadoc.classpath |
||||
} |
||||
} |
||||
|
||||
private void setupIdeDependencies(Project project) { |
||||
project.configurations.each { c -> |
||||
c.dependencies.findAll( { it instanceof org.gradle.api.artifacts.ProjectDependency } ).each { d -> |
||||
d.dependencyProject.merge.from.each { from -> |
||||
project.dependencies.add("runtimeMerge", from) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void setupMaven(Project project) { |
||||
project.configurations.each { configuration -> |
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration]) |
||||
if (mapping.scope) { |
||||
Configuration intoConfiguration = project.merge.into.configurations.create( |
||||
project.name + "-" + configuration.name) |
||||
configuration.excludeRules.each { |
||||
configuration.exclude([ |
||||
(ExcludeRule.GROUP_KEY) : it.group, |
||||
(ExcludeRule.MODULE_KEY) : it.module]) |
||||
} |
||||
configuration.dependencies.each { |
||||
def intoCompile = project.merge.into.configurations.getByName("compile") |
||||
// Protect against changing a compile scope dependency (SPR-10218) |
||||
if (!intoCompile.dependencies.contains(it)) { |
||||
intoConfiguration.dependencies.add(it) |
||||
} |
||||
} |
||||
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project} |
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping( |
||||
mapping.priority + 100 + index, intoConfiguration, mapping.scope) |
||||
} |
||||
} |
||||
} |
||||
|
||||
private postProcessProjects(Gradle gradle) { |
||||
gradle.allprojects(new Action<Project>() { |
||||
public void execute(Project project) { |
||||
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{ |
||||
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging"); |
||||
dependsOnMergedFrom.dependencies.each{ dep -> |
||||
project.dependencies.add("runtimeMerge", dep.dependencyProject) |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
class MergeModel { |
||||
Project project; |
||||
Project into; |
||||
List<Project> from = []; |
||||
|
||||
public void setInto(Project into) { |
||||
this.into = into; |
||||
into.merge.from.add(project); |
||||
} |
||||
} |
||||
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin |
||||
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
implementation-class=org.springframework.build.gradle.MergePlugin |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
description = "Spring Beans" |
||||
|
||||
apply plugin: "groovy" |
||||
|
||||
dependencies { |
||||
compile(project(':spring-core')) |
||||
optional("javax.inject:javax.inject:1") |
||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") |
||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}") |
||||
optional("org.yaml:snakeyaml:1.18") |
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}") |
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}") |
||||
} |
||||
|
||||
// This modules does joint compilation for Java and Groovy code, |
||||
// with the compileGroovy task. |
||||
sourceSets { |
||||
main.groovy.srcDirs += "src/main/java" |
||||
main.java.srcDirs = [] |
||||
} |
||||
|
||||
compileGroovy { |
||||
sourceCompatibility = 1.8 |
||||
targetCompatibility = 1.8 |
||||
} |
||||
|
||||
// This module also builds Kotlin code and the compileKotlin task |
||||
// naturally depends on compileJava. |
||||
// We need to redefine dependencies to break task cycles. |
||||
compileGroovy.dependsOn = compileGroovy.taskDependencies.values - 'compileJava' |
||||
compileKotlin.dependsOn(compileGroovy) |
||||
compileKotlin.classpath += files(compileGroovy.destinationDir) |
||||
|
||||
Loading…
Reference in new issue