Browse Source
This commit removes JDiff from the Spring Framework build and instead, adds a Gradle plugin that configure JApiCmp tasks on the framework modules. Fixes gh-22942 See gh-23282pull/23487/head
17 changed files with 142 additions and 1690 deletions
@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
|
||||
/* |
||||
* Copyright 2002-2019 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 |
||||
* |
||||
* https://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.api; |
||||
|
||||
import java.io.File; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.Paths; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import me.champeau.gradle.japicmp.JapicmpPlugin; |
||||
import me.champeau.gradle.japicmp.JapicmpTask; |
||||
import org.gradle.api.Plugin; |
||||
import org.gradle.api.Project; |
||||
import org.gradle.api.artifacts.Configuration; |
||||
import org.gradle.api.artifacts.Dependency; |
||||
import org.gradle.api.plugins.JavaBasePlugin; |
||||
import org.gradle.api.plugins.JavaPlugin; |
||||
import org.gradle.api.tasks.TaskProvider; |
||||
import org.gradle.jvm.tasks.Jar; |
||||
|
||||
/** |
||||
* {@link Plugin} that applies the {@code "japicmp-gradle-plugin"} |
||||
* and create tasks for all subprojects, diffing the public API one by one |
||||
* and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}. |
||||
* <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the |
||||
* reports for the API diff between the baseline version and the current one for all modules. |
||||
* You can limit the report to a single module with |
||||
* {@code "./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE"}. |
||||
* |
||||
* @author Brian Clozel |
||||
*/ |
||||
public class ApiDiffPlugin implements Plugin<Project> { |
||||
|
||||
public static final String TASK_NAME = "apiDiff"; |
||||
|
||||
private static final String BASELINE_VERSION_PROPERTY = "baselineVersion"; |
||||
|
||||
private static final List<String> PACKAGE_INCLUDES = Collections.singletonList("org.springframework.*"); |
||||
|
||||
@Override |
||||
public void apply(Project project) { |
||||
if (project.hasProperty(BASELINE_VERSION_PROPERTY) && project.equals(project.getRootProject())) { |
||||
project.getPluginManager().apply(JapicmpPlugin.class); |
||||
project.getPlugins().withType(JapicmpPlugin.class, |
||||
plugin -> applyApiDiffConventions(project)); |
||||
} |
||||
} |
||||
|
||||
private void applyApiDiffConventions(Project project) { |
||||
String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString(); |
||||
project.subprojects(subProject -> createApiDiffTask(baselineVersion, subProject)); |
||||
} |
||||
|
||||
private void createApiDiffTask(String baselineVersion, Project project) { |
||||
if (isProjectEligible(project)) { |
||||
JapicmpTask apiDiff = project.getTasks().create(TASK_NAME, JapicmpTask.class); |
||||
apiDiff.setDescription("Generates an API diff report with japicmp"); |
||||
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP); |
||||
|
||||
apiDiff.setOldClasspath(project.files(createBaselineConfiguration(baselineVersion, project))); |
||||
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar"); |
||||
apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile())); |
||||
apiDiff.setNewClasspath(getRuntimeClassPath(project)); |
||||
apiDiff.setPackageIncludes(PACKAGE_INCLUDES); |
||||
apiDiff.setOnlyModified(true); |
||||
apiDiff.setIgnoreMissingClasses(true); |
||||
// Ignore Kotlin metadata annotations since they contain
|
||||
// illegal HTML characters and fail the report generation
|
||||
apiDiff.setAnnotationExcludes(Collections.singletonList("@kotlin.Metadata")); |
||||
|
||||
apiDiff.setHtmlOutputFile(getOutputFile(baselineVersion, project)); |
||||
|
||||
apiDiff.dependsOn(project.getTasks().getByName("jar")); |
||||
} |
||||
} |
||||
|
||||
private boolean isProjectEligible(Project project) { |
||||
return project.getPlugins().hasPlugin(JavaPlugin.class) |
||||
&& !project.getName().equals("spring-core-coroutines") |
||||
&& !project.getName().equals("spring-framework-bom"); |
||||
} |
||||
|
||||
private Configuration createBaselineConfiguration(String baselineVersion, Project project) { |
||||
String baseline = String.join(":", |
||||
project.getGroup().toString(), project.getName(), baselineVersion); |
||||
Dependency baselineDependency = project.getDependencies().create(baseline + "@jar"); |
||||
return project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency); |
||||
} |
||||
|
||||
private Configuration getRuntimeClassPath(Project project) { |
||||
return project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); |
||||
} |
||||
|
||||
private File getOutputFile(String baseLineVersion, Project project) { |
||||
Path outDir = Paths.get(project.getRootProject().getBuildDir().getAbsolutePath(), |
||||
"reports", "api-diff", |
||||
baseLineVersion + "_to_" + project.getRootProject().getVersion()); |
||||
return project.file(outDir.resolve(project.getName() + ".html").toString()); |
||||
} |
||||
|
||||
} |
||||
@ -1,76 +0,0 @@
@@ -1,76 +0,0 @@
|
||||
/** |
||||
* Generate a JDiff report between the current version and an older version. |
||||
* |
||||
* Usage: |
||||
* gradle jdiff -D OLD_VERSION=3.1.3.RELEASE -D OLD_VERSION_ROOT=/path/to/3.1.3.RELEASE |
||||
* |
||||
* View generated report at: |
||||
* build/reports/jdiff/changes.html |
||||
* |
||||
* @param OLD_VERSION required |
||||
* @param OLD_VERSION_ROOT required, typically pointing to a separate git clone dir |
||||
*/ |
||||
task jdiff { |
||||
description = "Generates a JDiff report" |
||||
group = "Documentation" |
||||
|
||||
def jdiffHome = "${rootProject.rootDir}/gradle/jdiff" |
||||
|
||||
ant.taskdef( |
||||
name: "jdiff", |
||||
classname: "jdiff.JDiffAntTask", |
||||
classpath: "${jdiffHome}/antjdiff.jar") |
||||
|
||||
def currentVersion = rootProject.version |
||||
def currentVersionRoot = rootProject.rootDir |
||||
|
||||
def oldVersion = System.getProperty("OLD_VERSION") |
||||
def oldVersionRoot = System.getProperty("OLD_VERSION_ROOT") |
||||
|
||||
def outputDir = "${rootProject.buildDir}/reports/jdiff/${oldVersion}_to_${currentVersion}" |
||||
|
||||
doLast { |
||||
if (oldVersion == null) |
||||
throw new IllegalArgumentException( |
||||
"Set OLD_VERSION property to indicate older of the two versions being compared") |
||||
if (oldVersionRoot == null) |
||||
throw new IllegalArgumentException( |
||||
"Set OLD_VERSION_ROOT property to indicate the root directory for ${oldVersion}") |
||||
|
||||
oldVersionRoot = new File(oldVersionRoot) |
||||
|
||||
ant.property(name: "JDIFF_HOME", value: jdiffHome) |
||||
ant.mkdir(dir: outputDir) |
||||
ant.jdiff( |
||||
destdir: outputDir, |
||||
source: "1.8", |
||||
verbose: "off", |
||||
stats: "on", |
||||
docchanges: "off") { |
||||
old(name: "Spring Framework ${oldVersion}") { |
||||
oldVersionRoot.eachDirMatch( { |
||||
def candidate = new File(it) |
||||
candidate.name.matches("org.springframework.*") || |
||||
candidate.name.matches("spring-.*") }) { match -> |
||||
match.eachDirRecurse { subdir -> |
||||
if (subdir.path ==~ '.*/src/main/java$') { |
||||
dirset(dir: subdir.path, includes: "org/**") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
"new"(name: "Spring Framework ${currentVersion}") { |
||||
currentVersionRoot.eachDirMatch( { |
||||
def candidate = new File(it) |
||||
candidate.name.matches("org.springframework.*") || |
||||
candidate.name.matches("spring-.*") }) { match -> |
||||
match.eachDirRecurse { subdir -> |
||||
if (subdir.path ==~ '.*/src/main/java$') { |
||||
dirset(dir: subdir.path, includes: "org/**") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,9 +0,0 @@
@@ -1,9 +0,0 @@
|
||||
/** |
||||
* This class is used only as a "null" argument for Javadoc when comparing |
||||
* two API files. Javadoc has to have a package, .java or .class file as an |
||||
* argument, even though JDiff doesn't use it. |
||||
*/ |
||||
public class Null { |
||||
public Null() { |
||||
} |
||||
} |
||||
@ -1,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
This distribution of JDiff 1.1.1 is included in the Spring Framework build |
||||
because JDiff has a hard requirement on a JDIFF_HOME directory containing |
||||
jdiff.jar and xerces.jar as well as other presentation resources. |
||||
|
||||
The actual generation of JDiff reports is driven by the `jdiff` task declared |
||||
in build.gradle in the project root. |
||||
@ -1,59 +0,0 @@
@@ -1,59 +0,0 @@
|
||||
|
||||
JDiff Doclet |
||||
------------ |
||||
|
||||
Matthew Doar |
||||
mdoar@pobox.com |
||||
|
||||
|
||||
The JDiff doclet is used to generate a report describing the |
||||
difference between two public Java APIs. |
||||
|
||||
The file jdiff.html contains the reference page for JDiff. The latest |
||||
version of JDiff can be downloaded at: |
||||
https://sourceforge.net/projects/javadiff |
||||
|
||||
To use the Ant task on your own project, see example.xml. More examples |
||||
of using JDiff to compare the public APIs of J2SE1.3 and J2SE1.4 can |
||||
be seen at http://javadiff.sourceforge.net/ |
||||
|
||||
For an example with the source distribution, run "ant" and |
||||
look at the HTML output in ./build/reports/example/changes.html |
||||
The page at ./build/reports/example/changes/com.acme.sp.SPImpl.html |
||||
shows what a typical page of changes looks like. |
||||
|
||||
System Requirements |
||||
------------------- |
||||
|
||||
JDiff has been tested with all releases of Java since J2SE1.2 but |
||||
releases of JDiff after 1.10.0 focus on JDK1.5. |
||||
|
||||
License |
||||
------- |
||||
|
||||
JDiff is licensed under the Lesser GNU General Public License (LGPL). |
||||
See the file LICENSE.txt. |
||||
|
||||
Acknowledgements |
||||
---------------- |
||||
|
||||
JDiff uses Stuart D. Gathman's Java translation of Gene Myers' O(ND) |
||||
difference algorithm. |
||||
|
||||
JDiff uses Xerces 1.4.2 from https://www.apache.org. |
||||
|
||||
JDiff also includes a script to use the classdoc application from |
||||
http://classdoc.sourceforge.net or http://www.jensgulden.de, by Jens |
||||
Gulden, (mail@jensgulden.de), to call a doclet such as jdiff on a .jar |
||||
file rather than on source. |
||||
|
||||
Many thanks to the reviewers at Sun and Vitria who gave feedback on early |
||||
versions of JDiff output, and also to the distillers of Laphroaig, and to |
||||
Arturo Fuente for his consistently fine cigars which helped inspire |
||||
much of this work. |
||||
|
||||
|
||||
Footnote: |
||||
|
||||
If you are looking for a generalized diff tool for XML, try diffmk from |
||||
https://wwws.sun.com/software/xml/developers/diffmk/ |
||||
Binary file not shown.
|
Before Width: | Height: | Size: 559 B |
|
Before Width: | Height: | Size: 799 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 116 B |
Binary file not shown.
Loading…
Reference in new issue