Ver código fonte

Merge branch '6.0.x' into 6.1.x

Automate spring-security.xsd

Closes gh-13825
Rob Winch 1 ano atrás
pai
commit
7627c2df46

+ 11 - 10
buildSrc/src/main/groovy/io/spring/gradle/convention/SchemaZipPlugin.groovy

@@ -4,6 +4,7 @@ import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.plugins.JavaPlugin
 import org.gradle.api.tasks.bundling.Zip
+import org.springframework.gradle.xsd.CreateVersionlessXsdTask
 
 public class SchemaZipPlugin implements Plugin<Project> {
 
@@ -15,7 +16,10 @@ public class SchemaZipPlugin implements Plugin<Project> {
 		schemaZip.archiveClassifier = 'schema'
 		schemaZip.description = "Builds -${schemaZip.archiveClassifier} archive containing all " +
 			"XSDs for deployment at static.springframework.org/schema."
-
+		def versionlessXsd = project.tasks.create("versionlessXsd", CreateVersionlessXsdTask) {
+			description = "Generates spring-security.xsd"
+			versionlessXsdFile = project.layout.buildDirectory.file("versionlessXsd/spring-security.xsd")
+		}
 		project.rootProject.subprojects.each { module ->
 
 			module.getPlugins().withType(JavaPlugin.class).all {
@@ -36,17 +40,14 @@ public class SchemaZipPlugin implements Plugin<Project> {
 						duplicatesStrategy 'exclude'
 						from xsdFile.path
 					}
-				}
-				File symlink = module.sourceSets.main.resources.find {
-					it.path.endsWith('org/springframework/security/config/spring-security.xsd')
-				}
-				if (symlink != null) {
-					schemaZip.into('security') {
-						duplicatesStrategy 'exclude'
-						from symlink.path
-					}
+					versionlessXsd.getInputFiles().from(xsdFile.path)
 				}
 			}
 		}
+
+        schemaZip.into("security") {
+            from(versionlessXsd.getOutputs())
+        }
+
 	}
 }

+ 147 - 0
buildSrc/src/main/java/org/springframework/gradle/xsd/CreateVersionlessXsdTask.java

@@ -0,0 +1,147 @@
+/*
+ * Copyright 2019-2023 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.gradle.xsd;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.tasks.*;
+import org.gradle.work.DisableCachingByDefault;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Creates the spring-security.xsd automatically
+ *
+ * @author Rob Winch
+ */
+@DisableCachingByDefault(because = "not worth it")
+public abstract class CreateVersionlessXsdTask extends DefaultTask {
+
+	@InputFiles
+	public abstract ConfigurableFileCollection getInputFiles();
+
+	@OutputFile
+	abstract RegularFileProperty getVersionlessXsdFile();
+
+	@TaskAction
+	void createVersionlessXsd() throws IOException {
+		XsdFileMajorMinorVersion largest = null;
+		ConfigurableFileCollection inputFiles = getInputFiles();
+		if (inputFiles.isEmpty()) {
+			throw new IllegalStateException("No Inputs configured");
+		}
+		for (File file : inputFiles) {
+			XsdFileMajorMinorVersion current = XsdFileMajorMinorVersion.create(file);
+			if (current == null) {
+				continue;
+			}
+			if (largest == null) {
+				largest = current;
+			}
+			else if (current.getVersion().isGreaterThan(largest.getVersion())) {
+				largest = current;
+			}
+		}
+		if (largest == null) {
+			throw new IllegalStateException("Could not create versionless xsd file because no files matching spring-security-<digit>.xsd were found in " + inputFiles.getFiles());
+		}
+		Path to = getVersionlessXsdFile().getAsFile().get().toPath();
+		Path from = largest.getFile().toPath();
+		Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
+	}
+
+	static class XsdFileMajorMinorVersion {
+		private final File file;
+
+		private final MajorMinorVersion version;
+
+		private XsdFileMajorMinorVersion(File file, MajorMinorVersion version) {
+			this.file = file;
+			this.version = version;
+		}
+
+		private static final Pattern FILE_MAJOR_MINOR_VERSION_PATTERN = Pattern.compile("^spring-security-(\\d+)\\.(\\d+)\\.xsd$");
+
+		/**
+		 * If matches xsd with major minor version (e.g. spring-security-5.1.xsd returns it, otherwise null
+		 * @param file
+		 * @return
+		 */
+		static XsdFileMajorMinorVersion create(File file) {
+			String fileName = file.getName();
+			Matcher matcher = FILE_MAJOR_MINOR_VERSION_PATTERN.matcher(fileName);
+			if (!matcher.find()) {
+				return null;
+			}
+			int major = Integer.parseInt(matcher.group(1));
+			int minor = Integer.parseInt(matcher.group(2));
+			MajorMinorVersion version = new MajorMinorVersion(major, minor);
+			return new XsdFileMajorMinorVersion(file, version);
+		}
+
+		public File getFile() {
+			return file;
+		}
+
+		public MajorMinorVersion getVersion() {
+			return version;
+		}
+	}
+
+	static class MajorMinorVersion {
+		private final int major;
+
+		private final int minor;
+
+		MajorMinorVersion(int major, int minor) {
+			this.major = major;
+			this.minor = minor;
+		}
+
+		public int getMajor() {
+			return major;
+		}
+
+		public int getMinor() {
+			return minor;
+		}
+
+		public boolean isGreaterThan(MajorMinorVersion version) {
+			if (getMajor() > version.getMajor()) {
+				return true;
+			}
+			if (getMajor() < version.getMajor()) {
+				return false;
+			}
+			if (getMinor() > version.getMinor()) {
+				return true;
+			}
+			if (getMinor() < version.getMinor()) {
+				return false;
+			}
+			// they are equal
+			return false;
+		}
+	}
+}

+ 94 - 0
buildSrc/src/test/java/org/springframework/gradle/xsd/CreateVersionlessXsdTaskTests.java

@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019-2023 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.gradle.xsd;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.gradle.xsd.CreateVersionlessXsdTask.MajorMinorVersion;
+import org.springframework.gradle.xsd.CreateVersionlessXsdTask.XsdFileMajorMinorVersion;
+
+import java.io.File;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+/**
+ * @author Rob Winch
+ */
+class CreateVersionlessXsdTaskTests {
+
+	@Test
+	void xsdCreateWhenValid() {
+		File file = new File("spring-security-2.0.xsd");
+		XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file);
+		assertThat(xsdFile).isNotNull();
+		assertThat(xsdFile.getFile()).isEqualTo(file);
+		assertThat(xsdFile.getVersion().getMajor()).isEqualTo(2);
+		assertThat(xsdFile.getVersion().getMinor()).isEqualTo(0);
+	}
+
+	@Test
+	void xsdCreateWhenPatchReleaseThenNull() {
+		File file = new File("spring-security-2.0.1.xsd");
+		XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file);
+		assertThat(xsdFile).isNull();
+	}
+
+	@Test
+	void xsdCreateWhenNotXsdFileThenNull() {
+		File file = new File("spring-security-2.0.txt");
+		XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file);
+		assertThat(xsdFile).isNull();
+	}
+
+	@Test
+	void xsdCreateWhenNotStartWithSpringSecurityThenNull() {
+		File file = new File("spring-securityNO-2.0.xsd");
+		XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file);
+		assertThat(xsdFile).isNull();
+	}
+
+	@Test
+	void isGreaterWhenMajorLarger() {
+		MajorMinorVersion larger = new MajorMinorVersion(2,0);
+		MajorMinorVersion smaller = new MajorMinorVersion(1,0);
+		assertThat(larger.isGreaterThan(smaller)).isTrue();
+		assertThat(smaller.isGreaterThan(larger)).isFalse();
+	}
+
+	@Test
+	void isGreaterWhenMinorLarger() {
+		MajorMinorVersion larger = new MajorMinorVersion(1,1);
+		MajorMinorVersion smaller = new MajorMinorVersion(1,0);
+		assertThat(larger.isGreaterThan(smaller)).isTrue();
+		assertThat(smaller.isGreaterThan(larger)).isFalse();
+	}
+
+	@Test
+	void isGreaterWhenMajorAndMinorLarger() {
+		MajorMinorVersion larger = new MajorMinorVersion(2,1);
+		MajorMinorVersion smaller = new MajorMinorVersion(1,0);
+		assertThat(larger.isGreaterThan(smaller)).isTrue();
+		assertThat(smaller.isGreaterThan(larger)).isFalse();
+	}
+
+	@Test
+	void isGreaterWhenSame() {
+		MajorMinorVersion first = new MajorMinorVersion(1,0);
+		MajorMinorVersion second = new MajorMinorVersion(1,0);
+		assertThat(first.isGreaterThan(second)).isFalse();
+		assertThat(second.isGreaterThan(first)).isFalse();
+	}
+}

+ 11 - 0
config/spring-security-config.gradle

@@ -1,4 +1,5 @@
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.springframework.gradle.xsd.CreateVersionlessXsdTask
 import trang.RncToXsd
 
 apply plugin: 'io.spring.convention.spring-module'
@@ -116,6 +117,16 @@ dependencies {
 	testRuntimeOnly 'org.hsqldb:hsqldb'
 }
 
+def versionlessXsd = project.tasks.create("versionlessXsd", CreateVersionlessXsdTask) {
+	inputFiles.from(project.sourceSets.main.resources)
+	versionlessXsdFile = project.layout.buildDirectory.file("versionlessXsd/spring-security.xsd")
+}
+
+processResources {
+	from(versionlessXsd) {
+		into 'org/springframework/security/config/'
+	}
+}
 
 tasks.named('rncToXsd', RncToXsd).configure {
 	rncDir = file('src/main/resources/org/springframework/security/config/')

+ 0 - 1
config/src/main/resources/org/springframework/security/config/spring-security.xsd

@@ -1 +0,0 @@
-spring-security-6.1.xsd