Skip to content

Commit

Permalink
Merge branch 'spring-projects:main' into gh-16251
Browse files Browse the repository at this point in the history
  • Loading branch information
kwondh5217 authored Jan 29, 2025
2 parents 7146c46 + 174f17e commit 782f0dd
Show file tree
Hide file tree
Showing 306 changed files with 4,443 additions and 428 deletions.
2 changes: 2 additions & 0 deletions .github/dco.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require:
members: false
4 changes: 2 additions & 2 deletions .github/workflows/continuous-integration-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
env:
STRUCTURE101_LICENSEID: ${{ secrets.STRUCTURE101_LICENSEID }}
run: |
./gradlew check s101 -Ps101.licenseId="$STRUCTURE101_LICENSEID" --stacktrace
./gradlew assemble && ./gradlew s101 -Ps101.licenseId="$STRUCTURE101_LICENSEID" --stacktrace
deploy-artifacts:
name: Deploy Artifacts
needs: [ build, test, check-samples, check-tangles ]
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
send-notification:
name: Send Notification
needs: [ perform-release ]
if: ${{ failure() || cancelled() }}
if: ${{ !success() }}
runs-on: ubuntu-latest
steps:
- name: Send Notification
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
# List of active maintenance branches.
branch: [ main, 6.4.x, 6.3.x, 6.2.x, 5.8.x ]
branch: [ main, 6.4.x, 6.3.x ]
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ Please do your best to follow these steps.
Don't worry if you don't get them all correct the first time, we will help you.

[[sign-cla]]
1. If you have not previously done so, please sign the https://cla.spring.io/sign/spring[Contributor License Agreement].
You will be reminded automatically when you submit the PR.
1. All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
[[create-an-issue]]
1. Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier discuss with the team first to determine the right fix or enhancement.
For typos and straightforward bug fixes, starting with a pull request is encouraged.
Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ nohttp {
source.builtBy(project(':spring-security-config').tasks.withType(RncToXsd))
}

tasks.named('checkstyleNohttp') {
maxHeapSize = '1g'
}

tasks.register('cloneRepository', IncludeRepoTask) {
repository = project.getProperties().get("repositoryName")
ref = project.getProperties().get("ref")
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/java/s101/S101Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private void configure(S101Configure configure) {

private void configure(JavaExec exec) {
exec.setDescription("Runs Structure101 headless analysis, installing and configuring if necessary");
exec.dependsOn("check");
exec.dependsOn("assemble");
Project project = exec.getProject();
S101PluginExtension extension = project.getExtensions().getByType(S101PluginExtension.class);
exec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
* @since 4.2
* @see org.springframework.security.jackson2.SecurityJackson2Modules
*/
@SuppressWarnings("serial")
public class CasJackson2Module extends SimpleModule {

public CasJackson2Module() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
Expand Down Expand Up @@ -273,12 +274,14 @@ private AbstractStringAssert<?> assertHasAlertStartingWith(String alertType, Str

/**
* Await until the assertion passes. If the assertion fails, it will display the
* assertion error in stdout.
* assertion error in stdout. WebDriver-related exceptions are ignored, so that
* {@code assertion}s can interact with the page and be retried on error, e.g.
* {@code assertThat(this.driver.findElement(By.Id("some-id")).isNotNull()}.
*/
private void await(Supplier<AbstractAssert<?, ?>> assertion) {
new FluentWait<>(this.driver).withTimeout(Duration.ofSeconds(2))
.pollingEvery(Duration.ofMillis(100))
.ignoring(AssertionError.class)
.ignoring(AssertionError.class, WebDriverException.class)
.until((d) -> {
assertion.get();
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping;
import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
Expand Down Expand Up @@ -235,103 +236,31 @@ private boolean anyPathsDontStartWithLeadingSlash(String... patterns) {
}

private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) {
Map<String, ? extends ServletRegistration> registrations = mappableServletRegistrations(servletContext);
if (registrations.isEmpty()) {
ServletRegistrationsSupport registrations = new ServletRegistrationsSupport(servletContext);
Collection<RegistrationMapping> mappings = registrations.mappings();
if (mappings.isEmpty()) {
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
}
if (!hasDispatcherServlet(registrations)) {
Collection<RegistrationMapping> dispatcherServletMappings = registrations.dispatcherServletMappings();
if (dispatcherServletMappings.isEmpty()) {
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
}
ServletRegistration dispatcherServlet = requireOneRootDispatcherServlet(registrations);
if (dispatcherServlet != null) {
if (registrations.size() == 1) {
return mvc;
}
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, servletContext);
}
dispatcherServlet = requireOnlyPathMappedDispatcherServlet(registrations);
if (dispatcherServlet != null) {
String mapping = dispatcherServlet.getMappings().iterator().next();
mvc.setServletPath(mapping.substring(0, mapping.length() - 2));
return mvc;
if (dispatcherServletMappings.size() > 1) {
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
throw new IllegalArgumentException(errorMessage);
}
String errorMessage = computeErrorMessage(registrations.values());
throw new IllegalArgumentException(errorMessage);
}

private Map<String, ? extends ServletRegistration> mappableServletRegistrations(ServletContext servletContext) {
Map<String, ServletRegistration> mappable = new LinkedHashMap<>();
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations()
.entrySet()) {
if (!entry.getValue().getMappings().isEmpty()) {
mappable.put(entry.getKey(), entry.getValue());
}
}
return mappable;
}

private boolean hasDispatcherServlet(Map<String, ? extends ServletRegistration> registrations) {
if (registrations == null) {
return false;
RegistrationMapping dispatcherServlet = dispatcherServletMappings.iterator().next();
if (mappings.size() > 1 && !dispatcherServlet.isDefault()) {
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
throw new IllegalArgumentException(errorMessage);
}
for (ServletRegistration registration : registrations.values()) {
if (isDispatcherServlet(registration)) {
return true;
}
}
return false;
}

private ServletRegistration requireOneRootDispatcherServlet(
Map<String, ? extends ServletRegistration> registrations) {
ServletRegistration rootDispatcherServlet = null;
for (ServletRegistration registration : registrations.values()) {
if (!isDispatcherServlet(registration)) {
continue;
}
if (registration.getMappings().size() > 1) {
return null;
}
if (!"/".equals(registration.getMappings().iterator().next())) {
return null;
}
rootDispatcherServlet = registration;
}
return rootDispatcherServlet;
}

private ServletRegistration requireOnlyPathMappedDispatcherServlet(
Map<String, ? extends ServletRegistration> registrations) {
ServletRegistration pathDispatcherServlet = null;
for (ServletRegistration registration : registrations.values()) {
if (!isDispatcherServlet(registration)) {
return null;
}
if (registration.getMappings().size() > 1) {
return null;
}
String mapping = registration.getMappings().iterator().next();
if (!mapping.startsWith("/") || !mapping.endsWith("/*")) {
return null;
}
if (pathDispatcherServlet != null) {
return null;
if (dispatcherServlet.isDefault()) {
if (mappings.size() == 1) {
return mvc;
}
pathDispatcherServlet = registration;
}
return pathDispatcherServlet;
}

private boolean isDispatcherServlet(ServletRegistration registration) {
Class<?> dispatcherServlet = ClassUtils.resolveClassName("org.springframework.web.servlet.DispatcherServlet",
null);
try {
Class<?> clazz = Class.forName(registration.getClassName());
return dispatcherServlet.isAssignableFrom(clazz);
}
catch (ClassNotFoundException ex) {
return false;
return new DispatcherServletDelegatingRequestMatcher(ant, mvc);
}
return mvc;
}

private static String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
Expand Down Expand Up @@ -518,18 +447,12 @@ public boolean matches(HttpServletRequest request) {

static class DispatcherServletRequestMatcher implements RequestMatcher {

private final ServletContext servletContext;

DispatcherServletRequestMatcher(ServletContext servletContext) {
this.servletContext = servletContext;
}

@Override
public boolean matches(HttpServletRequest request) {
String name = request.getHttpServletMapping().getServletName();
ServletRegistration registration = this.servletContext.getServletRegistration(name);
ServletRegistration registration = request.getServletContext().getServletRegistration(name);
Assert.notNull(registration,
() -> computeErrorMessage(this.servletContext.getServletRegistrations().values()));
() -> computeErrorMessage(request.getServletContext().getServletRegistrations().values()));
try {
Class<?> clazz = Class.forName(registration.getClassName());
return DispatcherServlet.class.isAssignableFrom(clazz);
Expand All @@ -549,10 +472,8 @@ static class DispatcherServletDelegatingRequestMatcher implements RequestMatcher

private final RequestMatcher dispatcherServlet;

DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc,
ServletContext servletContext) {
this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(),
new DispatcherServletRequestMatcher(servletContext)));
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc) {
this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(), new DispatcherServletRequestMatcher()));
}

DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2002-2025 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.security.config.annotation.web;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;

import org.springframework.util.ClassUtils;

class ServletRegistrationsSupport {

private final Collection<RegistrationMapping> registrations;

ServletRegistrationsSupport(ServletContext servletContext) {
Map<String, ? extends ServletRegistration> registrations = servletContext.getServletRegistrations();
Collection<RegistrationMapping> mappings = new ArrayList<>();
for (Map.Entry<String, ? extends ServletRegistration> entry : registrations.entrySet()) {
if (!entry.getValue().getMappings().isEmpty()) {
for (String mapping : entry.getValue().getMappings()) {
mappings.add(new RegistrationMapping(entry.getValue(), mapping));
}
}
}
this.registrations = mappings;
}

Collection<RegistrationMapping> dispatcherServletMappings() {
Collection<RegistrationMapping> mappings = new ArrayList<>();
for (RegistrationMapping registration : this.registrations) {
if (registration.isDispatcherServlet()) {
mappings.add(registration);
}
}
return mappings;
}

Collection<RegistrationMapping> mappings() {
return this.registrations;
}

record RegistrationMapping(ServletRegistration registration, String mapping) {
boolean isDispatcherServlet() {
Class<?> dispatcherServlet = ClassUtils
.resolveClassName("org.springframework.web.servlet.DispatcherServlet", null);
try {
Class<?> clazz = Class.forName(this.registration.getClassName());
return dispatcherServlet.isAssignableFrom(clazz);
}
catch (ClassNotFoundException ex) {
return false;
}
}

boolean isDefault() {
return "/".equals(this.mapping);
}
}

}
Loading

0 comments on commit 782f0dd

Please sign in to comment.