Skip to content

Commit

Permalink
This commit introduces AOT hints for types and resources used across …
Browse files Browse the repository at this point in the history
…the codebase and, more interestingly, specifically by the various JDBC-persisting repository implementations. This follows up on #1380
  • Loading branch information
joshlong committed Nov 15, 2023
1 parent a382ee9 commit a346692
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 265 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 the original author or authors.
* Copyright 2020-2021 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.
Expand All @@ -13,27 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.aot.hint;
package org.springframework.security.oauth2.server.authorization;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;

import org.thymeleaf.expression.Lists;
import sample.web.AuthorizationConsentController;

import org.springframework.aot.hint.BindingReflectionHintsRegistrar;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.*;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.jackson2.CoreJackson2Module;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module;
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
Expand All @@ -48,75 +35,78 @@
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.jackson2.WebServletJackson2Module;
import org.springframework.util.ClassUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
* {@link RuntimeHintsRegistrar} that registers {@link RuntimeHints} required for the sample.
* Statically registered via META-INF/spring/aot.factories.
* {@link RuntimeHintsRegistrar} that registers {@link RuntimeHints} required for the
* sample. Statically registered via META-INF/spring/aot.factories.
*
* @author Joe Grandja
* @author Josh Long
* @since 1.2
*/
class DemoAuthorizationServerRuntimeHints implements RuntimeHintsRegistrar {
class AuthorizationServerRuntimeHintsRegistrar implements RuntimeHintsRegistrar {

private final BindingReflectionHintsRegistrar reflectionHintsRegistrar = new BindingReflectionHintsRegistrar();

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {

// Thymeleaf
hints.reflection().registerTypes(
Arrays.asList(
TypeReference.of(AuthorizationConsentController.ScopeWithDescription.class),
TypeReference.of(Lists.class)
), builder ->
builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS)
);

// Collections -> UnmodifiableSet, UnmodifiableList, UnmodifiableMap, UnmodifiableRandomAccessList, etc.
hints.reflection().registerType(
Collections.class, MemberCategory.DECLARED_CLASSES);
// Collections -> UnmodifiableSet, UnmodifiableList, UnmodifiableMap,
// UnmodifiableRandomAccessList, etc.
hints.reflection().registerType(Collections.class, MemberCategory.DECLARED_CLASSES);

// HashSet
hints.reflection().registerType(
HashSet.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS);
hints.reflection().registerType(HashSet.class, MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS);

// Spring Security and Spring Authorization Server
hints.reflection().registerTypes(
Arrays.asList(
TypeReference.of(AbstractAuthenticationToken.class),
TypeReference.of(WebAuthenticationDetails.class),
TypeReference.of(UsernamePasswordAuthenticationToken.class),
TypeReference.of(User.class),
TypeReference.of(OAuth2AuthenticationToken.class),
TypeReference.of(DefaultOidcUser.class),
TypeReference.of(DefaultOAuth2User.class),
TypeReference.of(OidcUserAuthority.class),
TypeReference.of(OAuth2UserAuthority.class),
TypeReference.of(SimpleGrantedAuthority.class),
TypeReference.of(OidcIdToken.class),
TypeReference.of(AbstractOAuth2Token.class),
TypeReference.of(OidcUserInfo.class),
TypeReference.of(OAuth2AuthorizationRequest.class),
TypeReference.of(AuthorizationGrantType.class),
TypeReference.of(OAuth2AuthorizationResponseType.class),
TypeReference.of(OAuth2TokenFormat.class)
), builder ->
builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS)
);
if (ClassUtils.isPresent("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken",
ClassUtils.getDefaultClassLoader()))
hints.reflection().registerType(
TypeReference
.of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken"),
builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));

hints.reflection().registerTypes(Arrays.asList(TypeReference.of(AbstractAuthenticationToken.class),
TypeReference.of(WebAuthenticationDetails.class),
TypeReference.of(UsernamePasswordAuthenticationToken.class), TypeReference.of(User.class),
TypeReference.of(DefaultOidcUser.class), TypeReference.of(DefaultOAuth2User.class),
TypeReference.of(OidcUserAuthority.class), TypeReference.of(OAuth2UserAuthority.class),
TypeReference.of(SimpleGrantedAuthority.class), TypeReference.of(OidcIdToken.class),
TypeReference.of(AbstractOAuth2Token.class), TypeReference.of(OidcUserInfo.class),
TypeReference.of(OAuth2AuthorizationRequest.class), TypeReference.of(AuthorizationGrantType.class),
TypeReference.of(OAuth2AuthorizationResponseType.class), TypeReference.of(OAuth2TokenFormat.class)),
builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));

// Jackson Modules - Spring Security and Spring Authorization Server
hints.reflection().registerTypes(
Arrays.asList(
TypeReference.of(CoreJackson2Module.class),
TypeReference.of(WebServletJackson2Module.class),
TypeReference.of(OAuth2ClientJackson2Module.class),
TypeReference.of(OAuth2AuthorizationServerJackson2Module.class)
), builder ->
builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS)
);
Set.of(CoreJackson2Module.class.getName(), WebServletJackson2Module.class.getName(),
OAuth2AuthorizationServerJackson2Module.class.getName()).stream().map(TypeReference::of)
.toList(),
builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));

if (ClassUtils.isPresent("org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module",
ClassUtils.getDefaultClassLoader()))
hints.reflection().registerType(
TypeReference.of("org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module"),
b -> b.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS));

hints.reflection().registerTypes(
Set.of(CoreJackson2Module.class.getName(), WebServletJackson2Module.class.getName(),
OAuth2AuthorizationServerJackson2Module.class.getName()).stream().map(TypeReference::of)
.toList(),
builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS));

// Jackson Mixins - Spring Security and Spring Authorization Server
try {
Expand All @@ -126,8 +116,8 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
Class.forName("org.springframework.security.jackson2.UnmodifiableListMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.jackson2.UnmodifiableMapMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), Class
.forName("org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.server.authorization.jackson2.HashSetMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Expand All @@ -136,8 +126,8 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
Class.forName("org.springframework.security.jackson2.UsernamePasswordAuthenticationTokenMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.jackson2.UserMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.client.jackson2.OAuth2AuthenticationTokenMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), Class
.forName("org.springframework.security.oauth2.client.jackson2.OAuth2AuthenticationTokenMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.client.jackson2.DefaultOidcUserMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Expand All @@ -152,21 +142,15 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
Class.forName("org.springframework.security.oauth2.client.jackson2.OidcIdTokenMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.client.jackson2.OidcUserInfoMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationRequestMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
Class.forName("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2TokenFormatMixin"));
} catch (ClassNotFoundException ex) {
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), Class.forName(
"org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationRequestMixin"));
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), Class.forName(
"org.springframework.security.oauth2.server.authorization.jackson2.OAuth2TokenFormatMixin"));
}
catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}

// Sql Schema Resources
hints.resources().registerPattern(
"org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql");
hints.resources().registerPattern(
"org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql");
hints.resources().registerPattern(
"org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql");
}

}
Loading

0 comments on commit a346692

Please sign in to comment.