This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new 7fb40bdd92f CXF-8297 - Fix NPE in Aegis for generic array properties 
(e.g. T[]) (#3574)
7fb40bdd92f is described below

commit 7fb40bdd92fa24758254d370360ecb54af040a75
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Wed Oct 14 11:48:58 2026 +0100

    CXF-8297 - Fix NPE in Aegis for generic array properties (e.g. T[]) (#3574)
---
 .../java/org/apache/cxf/aegis/type/TypeUtil.java   |  22 ++++-
 .../cxf/aegis/type/java5/GenericArrayTest.java     | 104 +++++++++++++++++++++
 2 files changed, 125 insertions(+), 1 deletion(-)

diff --git 
a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java 
b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java
index 47842fb455c..86d3099ba9a 100644
--- a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java
+++ b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java
@@ -22,6 +22,8 @@ import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
 import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
@@ -251,7 +253,10 @@ public final class TypeUtil {
         if (type instanceof GenericArrayType) {
             GenericArrayType gat = (GenericArrayType) type;
             Type compType = gat.getGenericComponentType();
-            Class<?> arrayBaseType = getTypeRelatedClass(compType);
+            Class<?> arrayBaseType = 
getTypeRelatedClass(getErasedType(compType));
+            if (arrayBaseType == null) {
+                arrayBaseType = Object.class;
+            }
             // believe it or not, this seems to be the only way to get the
             // Class object for an array of primitive type.
             Object instance = Array.newInstance(arrayBaseType, 0);
@@ -259,4 +264,19 @@ public final class TypeUtil {
         }
         return null;
     }
+
+    /**
+     * Replace a type variable or wildcard by its (first) upper bound, e.g. so 
that
+     * the component type of a generic array such as T[] can be resolved to a 
class.
+     */
+    private static Type getErasedType(Type type) {
+        Type erased = type;
+        while (erased instanceof TypeVariable || erased instanceof 
WildcardType) {
+            Type[] bounds = erased instanceof TypeVariable
+                ? ((TypeVariable<?>) erased).getBounds()
+                : ((WildcardType) erased).getUpperBounds();
+            erased = bounds.length > 0 ? bounds[0] : Object.class;
+        }
+        return erased;
+    }
 }
diff --git 
a/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java
 
b/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java
new file mode 100644
index 00000000000..e061bc4e312
--- /dev/null
+++ 
b/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.apache.cxf.aegis.type.java5;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.aegis.AbstractAegisTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * A bean property whose type is a generic array of a type variable (e.g. T[])
+ * used to cause a NullPointerException in TypeUtil.getTypeRelatedClass.
+ */
+public class GenericArrayTest extends AbstractAegisTest {
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        createService(GenericArrayService.class, "GenericArrayService");
+    }
+
+    @Test
+    public void testGenericArrayProperty() throws Exception {
+        Document doc = getWSDLDocument("GenericArrayService");
+        assertNotNull(doc);
+        assertValid("//xsd:complexType[@name='Page']", doc);
+    }
+
+    @Test
+    public void testBoundedGenericArrayProperty() throws Exception {
+        Document doc = getWSDLDocument("GenericArrayService");
+        assertNotNull(doc);
+        // T extends Score, so T[] should be mapped to an array of Score
+        assertValid("//xsd:complexType[@name='Subject']"
+                    + "//xsd:element[@name='scores' and 
@type='tns:ArrayOfScore']", doc);
+        
assertValid("//xsd:complexType[@name='ArrayOfScore']//xsd:element[@type='tns:Score']",
 doc);
+    }
+
+    public static class Page<T> {
+        private T[] items;
+
+        public T[] getItems() {
+            return items;
+        }
+
+        public void setItems(T[] items) {
+            this.items = items;
+        }
+    }
+
+    public static class Score {
+        private int value;
+
+        public int getValue() {
+            return value;
+        }
+
+        public void setValue(int value) {
+            this.value = value;
+        }
+    }
+
+    public static class Subject<T extends Score> {
+        private T[] scores;
+
+        public T[] getScores() {
+            return scores;
+        }
+
+        public void setScores(T[] scores) {
+            this.scores = scores;
+        }
+    }
+
+    public static class GenericArrayService {
+        public Page<String> getPage() {
+            return new Page<>();
+        }
+
+        public Subject<Score> getSubject() {
+            return new Subject<>();
+        }
+    }
+}

Reply via email to