diff --git a/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionRuntimeHints.java b/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionRuntimeHints.java new file mode 100644 index 00000000..53508443 --- /dev/null +++ b/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionRuntimeHints.java @@ -0,0 +1,48 @@ +/* + * Copyright 2014-2022 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.session.aot.hint; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.TreeSet; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; + +/** + * A {@link RuntimeHintsRegistrar} for common session hints. + * + * @author Marcus Da Coregio + */ +class CommonSessionRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + Arrays.asList(TypeReference.of(String.class), TypeReference.of(ArrayList.class), + TypeReference.of(TreeSet.class), TypeReference.of(Number.class), TypeReference.of(Long.class), + TypeReference.of(Integer.class), TypeReference.of(StackTraceElement.class), + TypeReference.of(Throwable.class), TypeReference.of(Exception.class), + TypeReference.of(RuntimeException.class), + TypeReference.of("java.util.Collections$UnmodifiableCollection"), + TypeReference.of("java.util.Collections$UnmodifiableList"), + TypeReference.of("java.util.Collections$EmptyList"), + TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"), + TypeReference.of("java.util.Collections$UnmodifiableSet")).forEach(hints.serialization()::registerType); + } + +} diff --git a/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHints.java b/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHints.java index 10db91ec..8d6340e5 100644 --- a/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHints.java +++ b/spring-session-core/src/main/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHints.java @@ -16,28 +16,11 @@ package org.springframework.session.aot.hint; -import java.util.ArrayList; import java.util.Arrays; -import java.util.TreeSet; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.authentication.AccountExpiredException; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.CredentialsExpiredException; -import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.InsufficientAuthenticationException; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.authentication.ProviderNotFoundException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextImpl; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UsernameNotFoundException; /** * A {@link RuntimeHintsRegistrar} for common session security hints. @@ -48,33 +31,34 @@ class CommonSessionSecurityRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - Arrays.asList(TypeReference.of(String.class), TypeReference.of(ArrayList.class), - TypeReference.of(TreeSet.class), TypeReference.of(SecurityContextImpl.class), - TypeReference.of(SimpleGrantedAuthority.class), TypeReference.of(User.class), - TypeReference.of(Number.class), TypeReference.of(Long.class), TypeReference.of(Integer.class), - TypeReference.of(AbstractAuthenticationToken.class), - TypeReference.of(UsernamePasswordAuthenticationToken.class), TypeReference.of(StackTraceElement.class), - TypeReference.of(Throwable.class), TypeReference.of(Exception.class), - TypeReference.of(RuntimeException.class), TypeReference.of(AuthenticationException.class), - TypeReference.of(BadCredentialsException.class), TypeReference.of(UsernameNotFoundException.class), - TypeReference.of(AccountExpiredException.class), TypeReference.of(ProviderNotFoundException.class), - TypeReference.of(DisabledException.class), TypeReference.of(LockedException.class), - TypeReference.of(AuthenticationServiceException.class), - TypeReference.of(CredentialsExpiredException.class), - TypeReference.of(InsufficientAuthenticationException.class), + registerSecurityHintsIfNeeded(hints); + registerOAuth2ClientHintsIfNeeded(hints); + registerOAuth2ResourceServerHintsIfNeeded(hints); + } + + private void registerSecurityHintsIfNeeded(RuntimeHints hints) { + Arrays.asList(TypeReference.of("org.springframework.security.core.context.SecurityContextImpl"), + TypeReference.of("org.springframework.security.core.authority.SimpleGrantedAuthority"), + TypeReference.of("org.springframework.security.core.userdetails.User"), + TypeReference.of("org.springframework.security.authentication.AbstractAuthenticationToken"), + TypeReference.of("org.springframework.security.authentication.UsernamePasswordAuthenticationToken"), + TypeReference.of("org.springframework.security.core.AuthenticationException"), + TypeReference.of("org.springframework.security.authentication.BadCredentialsException"), + TypeReference.of("org.springframework.security.core.userdetails.UsernameNotFoundException"), + TypeReference.of("org.springframework.security.authentication.AccountExpiredException"), + TypeReference.of("org.springframework.security.authentication.ProviderNotFoundException"), + TypeReference.of("org.springframework.security.authentication.DisabledException"), + TypeReference.of("org.springframework.security.authentication.LockedException"), + TypeReference.of("org.springframework.security.authentication.AuthenticationServiceException"), + TypeReference.of("org.springframework.security.authentication.CredentialsExpiredException"), + TypeReference.of("org.springframework.security.authentication.InsufficientAuthenticationException"), TypeReference .of("org.springframework.security.web.authentication.session.SessionAuthenticationException"), TypeReference.of( "org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException"), - TypeReference.of("java.util.Collections$UnmodifiableCollection"), - TypeReference.of("java.util.Collections$UnmodifiableList"), - TypeReference.of("java.util.Collections$EmptyList"), - TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"), - TypeReference.of("java.util.Collections$UnmodifiableSet"), TypeReference.of("org.springframework.security.core.userdetails.User$AuthorityComparator")) - .forEach(hints.serialization()::registerType); - registerOAuth2ClientHintsIfNeeded(hints); - registerOAuth2ResourceServerHintsIfNeeded(hints); + .forEach((type) -> hints.serialization().registerType(type, (hint) -> hint.onReachableType( + TypeReference.of("org.springframework.security.core.context.SecurityContextImpl")))); } private void registerOAuth2ResourceServerHintsIfNeeded(RuntimeHints hints) { diff --git a/spring-session-core/src/main/resources/META-INF/spring/aot.factories b/spring-session-core/src/main/resources/META-INF/spring/aot.factories index d9cd3040..1dec07e7 100644 --- a/spring-session-core/src/main/resources/META-INF/spring/aot.factories +++ b/spring-session-core/src/main/resources/META-INF/spring/aot.factories @@ -1,4 +1,5 @@ org.springframework.aot.hint.RuntimeHintsRegistrar=\ +org.springframework.session.aot.hint.CommonSessionRuntimeHints,\ org.springframework.session.aot.hint.CommonSessionSecurityRuntimeHints,\ org.springframework.session.aot.hint.servlet.HttpSessionSecurityRuntimeHints,\ org.springframework.session.aot.hint.server.WebSessionSecurityRuntimeHints diff --git a/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionRuntimeHintsTests.java b/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionRuntimeHintsTests.java new file mode 100644 index 00000000..b800cefa --- /dev/null +++ b/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionRuntimeHintsTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2014-2022 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.session.aot.hint; + +import java.util.ArrayList; +import java.util.TreeSet; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.core.io.support.SpringFactoriesLoader; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CommonSessionRuntimeHints} + * + * @author Marcus Da Coregio + */ +class CommonSessionRuntimeHintsTests { + + private final RuntimeHints hints = new RuntimeHints(); + + private final CommonSessionRuntimeHints commonSessionRuntimeHints = new CommonSessionRuntimeHints(); + + @ParameterizedTest + @MethodSource("getSerializationHintTypes") + void commonSessionTypesHasHints(TypeReference typeReference) { + this.commonSessionRuntimeHints.registerHints(this.hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.serialization().onType(typeReference)).accepts(this.hints); + } + + @Test + void aotFactoriesContainsRegistrar() { + boolean match = SpringFactoriesLoader.forResourceLocation("META-INF/spring/aot.factories") + .load(RuntimeHintsRegistrar.class).stream() + .anyMatch((registrar) -> registrar instanceof CommonSessionRuntimeHints); + assertThat(match).isTrue(); + } + + private static Stream getSerializationHintTypes() { + return Stream.of(TypeReference.of(String.class), TypeReference.of(ArrayList.class), + TypeReference.of(TreeSet.class), TypeReference.of(Number.class), TypeReference.of(Long.class), + TypeReference.of(Integer.class), TypeReference.of(StackTraceElement.class), + TypeReference.of(Throwable.class), TypeReference.of(Exception.class), + TypeReference.of(RuntimeException.class), + TypeReference.of("java.util.Collections$UnmodifiableCollection"), + TypeReference.of("java.util.Collections$UnmodifiableList"), + TypeReference.of("java.util.Collections$EmptyList"), + TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"), + TypeReference.of("java.util.Collections$UnmodifiableSet")); + } + +} diff --git a/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHintsTests.java b/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHintsTests.java index cd2ce3e3..f168e80f 100644 --- a/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHintsTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/aot/hint/CommonSessionSecurityRuntimeHintsTests.java @@ -16,8 +16,6 @@ package org.springframework.session.aot.hint; -import java.util.ArrayList; -import java.util.TreeSet; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -29,21 +27,6 @@ import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.core.io.support.SpringFactoriesLoader; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.authentication.AccountExpiredException; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.CredentialsExpiredException; -import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.InsufficientAuthenticationException; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.authentication.ProviderNotFoundException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextImpl; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import static org.assertj.core.api.Assertions.assertThat; @@ -60,7 +43,7 @@ class CommonSessionSecurityRuntimeHintsTests { @ParameterizedTest @MethodSource("getSerializationHintTypes") - void coreTypesHasHints(TypeReference typeReference) { + void commonSecurityTypesHasHints(TypeReference typeReference) { this.commonSessionSecurityRuntimeHints.registerHints(this.hints, getClass().getClassLoader()); assertThat(RuntimeHintsPredicates.serialization().onType(typeReference)).accepts(this.hints); } @@ -74,29 +57,25 @@ class CommonSessionSecurityRuntimeHintsTests { } private static Stream getSerializationHintTypes() { - return Stream.of(TypeReference.of(String.class), TypeReference.of(ArrayList.class), - TypeReference.of(TreeSet.class), TypeReference.of(SecurityContextImpl.class), - TypeReference.of(SimpleGrantedAuthority.class), TypeReference.of(User.class), - TypeReference.of(Number.class), TypeReference.of(Long.class), TypeReference.of(Integer.class), - TypeReference.of(AbstractAuthenticationToken.class), - TypeReference.of(UsernamePasswordAuthenticationToken.class), TypeReference.of(StackTraceElement.class), - TypeReference.of(Throwable.class), TypeReference.of(Exception.class), - TypeReference.of(RuntimeException.class), TypeReference.of(AuthenticationException.class), - TypeReference.of(BadCredentialsException.class), TypeReference.of(UsernameNotFoundException.class), - TypeReference.of(AccountExpiredException.class), TypeReference.of(ProviderNotFoundException.class), - TypeReference.of(DisabledException.class), TypeReference.of(LockedException.class), - TypeReference.of(AuthenticationServiceException.class), - TypeReference.of(CredentialsExpiredException.class), - TypeReference.of(InsufficientAuthenticationException.class), + return Stream.of(TypeReference.of("org.springframework.security.core.context.SecurityContextImpl"), + TypeReference.of("org.springframework.security.core.authority.SimpleGrantedAuthority"), + TypeReference.of("org.springframework.security.core.userdetails.User"), + TypeReference.of("org.springframework.security.authentication.AbstractAuthenticationToken"), + TypeReference.of("org.springframework.security.authentication.UsernamePasswordAuthenticationToken"), + TypeReference.of("org.springframework.security.core.AuthenticationException"), + TypeReference.of("org.springframework.security.authentication.BadCredentialsException"), + TypeReference.of("org.springframework.security.core.userdetails.UsernameNotFoundException"), + TypeReference.of("org.springframework.security.authentication.AccountExpiredException"), + TypeReference.of("org.springframework.security.authentication.ProviderNotFoundException"), + TypeReference.of("org.springframework.security.authentication.DisabledException"), + TypeReference.of("org.springframework.security.authentication.LockedException"), + TypeReference.of("org.springframework.security.authentication.AuthenticationServiceException"), + TypeReference.of("org.springframework.security.authentication.CredentialsExpiredException"), + TypeReference.of("org.springframework.security.authentication.InsufficientAuthenticationException"), TypeReference .of("org.springframework.security.web.authentication.session.SessionAuthenticationException"), TypeReference.of( "org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException"), - TypeReference.of("java.util.Collections$UnmodifiableCollection"), - TypeReference.of("java.util.Collections$UnmodifiableList"), - TypeReference.of("java.util.Collections$EmptyList"), - TypeReference.of("java.util.Collections$UnmodifiableRandomAccessList"), - TypeReference.of("java.util.Collections$UnmodifiableSet"), TypeReference.of("org.springframework.security.core.userdetails.User$AuthorityComparator"), TypeReference.of("org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken"), TypeReference.of(