[java-identity-provider] 22/23: IDP-2310 - DumpConfig is causing a Jackson nesting violation

Scott Cantor cantor.2 at osu.edu
Mon Mar 17 15:04:01 UTC 2025


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch maint-5.1
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=d3718eaf72cdacaa562a1f6cb015f4f72a2eb745

commit d3718eaf72cdacaa562a1f6cb015f4f72a2eb745
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Feb 19 12:40:21 2025 -0500

    IDP-2310 - DumpConfig is causing a Jackson nesting violation
    
    https://shibboleth.atlassian.net/browse/IDP-2310
    
    Adjusted collection handling and added additional custom serializer.
---
 .../shibboleth/idp/admin/impl/OutputConfig.java    | 79 +++++++++++++++++-----
 1 file changed, 63 insertions(+), 16 deletions(-)

diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/OutputConfig.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/OutputConfig.java
index 2f136adeb..7c6b3141d 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/OutputConfig.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/OutputConfig.java
@@ -32,6 +32,7 @@ import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
 import org.slf4j.Logger;
 import org.springframework.core.annotation.AnnotationUtils;
 
@@ -177,9 +178,10 @@ public class OutputConfig extends AbstractProfileAction {
             
             final ObjectMapper mapper = new ObjectMapper();
             mapper.registerModule(new JavaTimeModule());
-            final SimpleModule principalModule = new SimpleModule();
-            principalModule.addSerializer(new PrincipalSerializer());
-            mapper.registerModule(principalModule);
+            final SimpleModule customlModule = new SimpleModule();
+            customlModule.addSerializer(new PrincipalSerializer());
+            customlModule.addSerializer(new RequestedAttributeSerializer());
+            mapper.registerModule(customlModule);
             
             // These don't do much of anything, except the first one I think.
             mapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
@@ -228,7 +230,6 @@ public class OutputConfig extends AbstractProfileAction {
      * 
      * @return map of settings
      */
-// Checkstyle: CyclomaticComplexity OFF
     @Nonnull @NullableElements @Unmodifiable @NotLive
     private Map<String,Object> getSettings(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final Object target) {
@@ -254,17 +255,7 @@ public class OutputConfig extends AbstractProfileAction {
                     if (ret == null) {
                         continue;
                     }
-                    if (ret instanceof IdentifiableComponent comp) {
-                        settings.put(annotation.name(), comp.getId());
-                    } else if (ret instanceof Collection<?> c) {
-                        if (!c.isEmpty()) {
-                            settings.put(annotation.name(), ret);
-                        }
-                    } else if (isPrimitive(ret)) {
-                        settings.put(annotation.name(), ret);
-                    } else {
-                        settings.put(annotation.name(), ret.getClass().getName());
-                    }
+                    addSetting(settings, annotation.name(), ret);
                 } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                     log.error("{} Error introspecting configuration setting '{}'", getLogPrefix(), annotation.name(),
                             e);
@@ -274,8 +265,34 @@ public class OutputConfig extends AbstractProfileAction {
         
         return settings;
     }
-// Checkstyle: CyclomaticComplexity ON    
 
+    /**
+     * Process a setting by adding it to the map if it's suitable for output.
+     * 
+     * @param settings map of settings to be serialized to caller by Jackson
+     * @param name name of setting
+     * @param obj native/original value of setting
+     */
+    private void addSetting(@Nonnull final Map<String,Object> settings, @Nonnull final String name,
+            @Nonnull final Object obj) {
+        if (obj instanceof IdentifiableComponent comp) {
+            settings.put(name, comp.getId());
+        } else if (obj instanceof Collection<?> c) {
+            if (!c.isEmpty()) {
+                final Object member = c.iterator().next();
+                if (isPrimitive(member)) {
+                    settings.put(name, obj);
+                } else if (member instanceof RequestedAttribute || member instanceof Principal) {
+                    settings.put(name, obj);
+                }
+            }
+        } else if (isPrimitive(obj)) {
+            settings.put(name, obj);
+        } else {
+            settings.put(name, obj.getClass().getName());
+        }
+    }
+    
     /**
      * Check an object for whether it's a boxed primitive type or one of the time wrappers.
      * 
@@ -318,5 +335,35 @@ public class OutputConfig extends AbstractProfileAction {
             
         }
     }
+
+    /**
+     * Custom serializer for {@link Principal} objects in config.
+     */
+    private static class RequestedAttributeSerializer extends StdSerializer<RequestedAttribute> {
+
+        /**
+         * Constructor.
+         */
+        protected RequestedAttributeSerializer() {
+            super(RequestedAttribute.class);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void serialize(final RequestedAttribute value, final JsonGenerator gen,
+                final SerializerProvider provider)
+                throws IOException {
+            gen.writeStartObject();
+            gen.writeStringField("type", RequestedAttribute.class.getName());
+            gen.writeStringField("name", value.getName());
+            gen.writeStringField("nameFormat", value.getNameFormat());
+            final Boolean isRequired = value.isRequired();
+            if (isRequired != null) {
+                gen.writeBooleanField("isRequired", isRequired);
+            }
+            gen.writeEndObject();
+            
+        }
+    }
     
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list