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

ffang pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/4.1.x-fixes by this push:
     new 7fbcaabd6bd [CXF-9147]To accommodate the behaviour that several schema 
namespaces… (#3093)
7fbcaabd6bd is described below

commit 7fbcaabd6bd417afe4292cef2cae0bd92a8b9c09
Author: Freeman(Yue) Fang <[email protected]>
AuthorDate: Fri May 8 15:01:39 2026 -0400

    [CXF-9147]To accommodate the behaviour that several schema namespaces… 
(#3093)
    
    * [CXF-9147]To accommodate the behaviour that several schema namespaces are 
explicitly mapped to the same Java package
    
    * [CXF-9147]remove unnecessary fallback code
    
    (cherry picked from commit a04c05c22f81dea96be28228852d14897d0b806d)
---
 .../wsdlto/databinding/jaxb/JAXBDataBinding.java   |  85 ++++++++++++++
 .../wsdlto/jaxb/JAXBCodeGenNamespaceTest.java      |  57 ++++++++++
 .../cxf9147/cxf9147-shared-package.wsdl            | 123 +++++++++++++++++++++
 3 files changed, 265 insertions(+)

diff --git 
a/tools/wsdlto/databinding/jaxb/src/main/java/org/apache/cxf/tools/wsdlto/databinding/jaxb/JAXBDataBinding.java
 
b/tools/wsdlto/databinding/jaxb/src/main/java/org/apache/cxf/tools/wsdlto/databinding/jaxb/JAXBDataBinding.java
index e897581bd93..c2c371395db 100644
--- 
a/tools/wsdlto/databinding/jaxb/src/main/java/org/apache/cxf/tools/wsdlto/databinding/jaxb/JAXBDataBinding.java
+++ 
b/tools/wsdlto/databinding/jaxb/src/main/java/org/apache/cxf/tools/wsdlto/databinding/jaxb/JAXBDataBinding.java
@@ -72,6 +72,7 @@ import org.xml.sax.helpers.XMLFilterImpl;
 
 import com.sun.codemodel.ClassType;
 import com.sun.codemodel.CodeWriter;
+import com.sun.codemodel.JAnnotationUse;
 import com.sun.codemodel.JClass;
 import com.sun.codemodel.JCodeModel;
 import com.sun.codemodel.JDefinedClass;
@@ -126,6 +127,8 @@ import org.apache.cxf.wsdl.WSDLConstants;
 import org.apache.ws.commons.schema.XmlSchema;
 import org.apache.ws.commons.schema.XmlSchemaSerializer;
 import 
org.apache.ws.commons.schema.XmlSchemaSerializer.XmlSchemaSerializerException;
+import org.apache.ws.commons.schema.XmlSchemaType;
+
 
 public class JAXBDataBinding implements DataBindingProfile {
     static final String XJCVERSION;
@@ -833,6 +836,7 @@ public class JAXBDataBinding implements DataBindingProfile {
             }
 
             JCodeModel jcodeModel = schem2JavaJaxbModel.generateCode(null, 
null);
+            fixXmlTypeNamespacesForSharedPackages(schem2JavaJaxbModel, 
jcodeModel);
 
             if (!isSuppressCodeGen()) {
                 jcodeModel.build(fileCodeWriter);
@@ -851,6 +855,87 @@ public class JAXBDataBinding implements DataBindingProfile 
{
         }
     }
 
+
+    private void fixXmlTypeNamespacesForSharedPackages(S2JJAXBModel model, 
JCodeModel codeModel) {
+        Map<String, Set<String>> packageToNamespaces = new HashMap<>();
+        for (Map.Entry<String, String> entry : 
context.getNamespacePackageMap().entrySet()) {
+            packageToNamespaces.computeIfAbsent(entry.getValue(), k -> new 
HashSet<>()).add(entry.getKey());
+        }
+
+        Set<String> sharedPackageNamespaces = new HashSet<>();
+        for (Set<String> namespaces : packageToNamespaces.values()) {
+            if (namespaces.size() > 1) {
+                sharedPackageNamespaces.addAll(namespaces);
+            }
+        }
+        if (sharedPackageNamespaces.isEmpty()) {
+            return;
+        }
+
+        SchemaCollection schemas = (SchemaCollection) 
context.get(ToolConstants.XML_SCHEMA_COLLECTION);
+        if (schemas == null) {
+            return;
+        }
+
+        Map<String, String> classToNamespace = new HashMap<>();
+        for (XmlSchema schema : schemas.getXmlSchemas()) {
+            String namespace = schema.getTargetNamespace();
+            if (StringUtils.isEmpty(namespace) || 
!sharedPackageNamespaces.contains(namespace)) {
+                continue;
+            }
+            for (QName typeName : schema.getSchemaTypes().keySet()) {
+                XmlSchemaType schemaType = schema.getTypeByName(typeName);
+                if (schemaType == null) {
+                    continue;
+                }
+                TypeAndAnnotation type = model.getJavaType(typeName);
+                if (type != null && type.getTypeClass() instanceof 
JDefinedClass) {
+                    JDefinedClass cls = (JDefinedClass)type.getTypeClass();
+                    classToNamespace.put(cls.fullName(), namespace);
+                }
+            }
+        }
+
+        for (Map.Entry<String, String> entry : classToNamespace.entrySet()) {
+            JDefinedClass cls = codeModel._getClass(entry.getKey());
+            if (cls == null) {
+                continue;
+            }
+            JAnnotationUse xmlType = getAnnotation(cls, 
"jakarta.xml.bind.annotation.XmlType");
+            if (xmlType != null && !hasAnnotationMember(xmlType, "namespace")) 
{
+                xmlType.param("namespace", entry.getValue());
+            }
+        }
+    }
+
+    private JAnnotationUse getAnnotation(JDefinedClass cls, String 
annotationClassName) {
+        for (JAnnotationUse annotation : cls.annotations()) {
+            if 
(annotation.getAnnotationClass().fullName().equals(annotationClassName)) {
+                return annotation;
+            }
+        }
+        return null;
+    }
+
+    private boolean hasAnnotationMember(JAnnotationUse annotation, String 
name) {
+        try {
+            return annotation.getAnnotationMembers().containsKey(name);
+        } catch (NoSuchMethodError ex) {
+            return hasAnnotationMemberUsingReflection(annotation, name);
+        }
+    }
+
+    private boolean hasAnnotationMemberUsingReflection(JAnnotationUse 
annotation, String name) {
+        try {
+            Field f = annotation.getClass().getDeclaredField("memberValues");
+            ReflectionUtil.setAccessible(f);
+            Map<?, ?> map = (Map<?, ?>)f.get(annotation);
+            return map.containsKey(name);
+        } catch (IllegalAccessException | NoSuchFieldException | 
SecurityException ex) {
+            return false;
+        }
+    }
+
     public String getType(QName qname, boolean element) {
         TypeAndAnnotation typeAnno = rawJaxbModelGenCode.getJavaType(qname);
         if (element) {
diff --git 
a/tools/wsdlto/test/src/test/java/org/apache/cxf/tools/wsdlto/jaxb/JAXBCodeGenNamespaceTest.java
 
b/tools/wsdlto/test/src/test/java/org/apache/cxf/tools/wsdlto/jaxb/JAXBCodeGenNamespaceTest.java
new file mode 100644
index 00000000000..8191f830712
--- /dev/null
+++ 
b/tools/wsdlto/test/src/test/java/org/apache/cxf/tools/wsdlto/jaxb/JAXBCodeGenNamespaceTest.java
@@ -0,0 +1,57 @@
+/**
+ * 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.tools.wsdlto.jaxb;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+
+import org.apache.cxf.tools.common.ToolConstants;
+import org.apache.cxf.tools.wsdlto.AbstractCodeGenTest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+public class JAXBCodeGenNamespaceTest extends AbstractCodeGenTest {
+    private static final String PERMISSION_SET_NS =
+        "http://cxf.apache.org/cxf9147/data/PermissionSet";;
+
+    @Test
+    public void testXmlTypeNamespaceWithSharedPackageMappings() throws 
Exception {
+        env.put(ToolConstants.CFG_WSDLURL,
+                
getLocation("/wsdl2java_wsdl/cxf9147/cxf9147-shared-package.wsdl"));
+        env.put(ToolConstants.CFG_PACKAGENAME, new String[] {
+            
"http://cxf.apache.org/cxf9147/service=org.apache.cxf.cxf9147.service";,
+            
"http://cxf.apache.org/cxf9147/request=org.apache.cxf.cxf9147.request";,
+            PERMISSION_SET_NS + "=org.apache.cxf.cxf9147.shared",
+            
"http://cxf.apache.org/cxf9147/data/Permission=org.apache.cxf.cxf9147.shared";,
+            
"http://cxf.apache.org/cxf9147/data/UserPermission=org.apache.cxf.cxf9147.shared";
+        });
+
+        processor.setContext(env);
+        processor.execute();
+
+        File generated = new File(output, 
"org/apache/cxf/cxf9147/shared/ArrayOfPermissionSet.java");
+        assertTrue(generated.getAbsolutePath(), generated.exists());
+
+        String source = Files.readString(generated.toPath(), 
StandardCharsets.UTF_8);
+        assertTrue(source, source.contains("namespace = \"" + 
PERMISSION_SET_NS + "\""));
+    }
+}
diff --git 
a/tools/wsdlto/test/src/test/resources/wsdl2java_wsdl/cxf9147/cxf9147-shared-package.wsdl
 
b/tools/wsdlto/test/src/test/resources/wsdl2java_wsdl/cxf9147/cxf9147-shared-package.wsdl
new file mode 100644
index 00000000000..811ae26e621
--- /dev/null
+++ 
b/tools/wsdlto/test/src/test/resources/wsdl2java_wsdl/cxf9147/cxf9147-shared-package.wsdl
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<wsdl:definitions
+    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";
+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+    xmlns:xs="http://www.w3.org/2001/XMLSchema";
+    xmlns:tns="http://cxf.apache.org/cxf9147/service";
+    xmlns:req="http://cxf.apache.org/cxf9147/request";
+    xmlns:ps="http://cxf.apache.org/cxf9147/data/PermissionSet";
+    targetNamespace="http://cxf.apache.org/cxf9147/service";
+    name="Cxf9147Service">
+
+    <wsdl:types>
+        <xs:schema
+            targetNamespace="http://cxf.apache.org/cxf9147/data/PermissionSet";
+            xmlns:tns="http://cxf.apache.org/cxf9147/data/PermissionSet";
+            elementFormDefault="qualified">
+            <xs:complexType name="PermissionSet">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0"/>
+                </xs:sequence>
+            </xs:complexType>
+            <xs:complexType name="ArrayOfPermissionSet">
+                <xs:sequence>
+                    <xs:element name="permissionSet" type="tns:PermissionSet"
+                                minOccurs="0" maxOccurs="unbounded"/>
+                </xs:sequence>
+            </xs:complexType>
+        </xs:schema>
+
+        <xs:schema
+            targetNamespace="http://cxf.apache.org/cxf9147/data/Permission";
+            xmlns:tns="http://cxf.apache.org/cxf9147/data/Permission";
+            elementFormDefault="qualified">
+            <xs:complexType name="Permission">
+                <xs:sequence>
+                    <xs:element name="value" type="xs:string" minOccurs="0"/>
+                </xs:sequence>
+            </xs:complexType>
+        </xs:schema>
+
+        <xs:schema
+            targetNamespace="http://cxf.apache.org/cxf9147/data/UserPermission";
+            xmlns:tns="http://cxf.apache.org/cxf9147/data/UserPermission";
+            elementFormDefault="qualified">
+            <xs:complexType name="UserPermission">
+                <xs:sequence>
+                    <xs:element name="user" type="xs:string" minOccurs="0"/>
+                </xs:sequence>
+            </xs:complexType>
+        </xs:schema>
+
+        <xs:schema
+            targetNamespace="http://cxf.apache.org/cxf9147/request";
+            xmlns:tns="http://cxf.apache.org/cxf9147/request";
+            xmlns:ps="http://cxf.apache.org/cxf9147/data/PermissionSet";
+            elementFormDefault="qualified">
+            <xs:import 
namespace="http://cxf.apache.org/cxf9147/data/PermissionSet"/>
+            <xs:element name="getPermissions" type="tns:GetPermissions"/>
+            <xs:element name="getPermissionsResponse" 
type="tns:GetPermissionsResponse"/>
+            <xs:complexType name="GetPermissions">
+                <xs:sequence>
+                    <xs:element name="id" type="xs:string" minOccurs="0"/>
+                </xs:sequence>
+            </xs:complexType>
+            <xs:complexType name="GetPermissionsResponse">
+                <xs:sequence>
+                    <xs:element name="permissionSets" 
type="ps:ArrayOfPermissionSet" minOccurs="0"/>
+                </xs:sequence>
+            </xs:complexType>
+        </xs:schema>
+    </wsdl:types>
+
+    <wsdl:message name="GetPermissionsRequest">
+        <wsdl:part name="parameters" element="req:getPermissions"/>
+    </wsdl:message>
+    <wsdl:message name="GetPermissionsResponse">
+        <wsdl:part name="parameters" element="req:getPermissionsResponse"/>
+    </wsdl:message>
+
+    <wsdl:portType name="Cxf9147PortType">
+        <wsdl:operation name="getPermissions">
+            <wsdl:input message="tns:GetPermissionsRequest"/>
+            <wsdl:output message="tns:GetPermissionsResponse"/>
+        </wsdl:operation>
+    </wsdl:portType>
+
+    <wsdl:binding name="Cxf9147Binding" type="tns:Cxf9147PortType">
+        <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="getPermissions">
+            <soap:operation soapAction="urn:getPermissions"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+
+    <wsdl:service name="Cxf9147Service">
+        <wsdl:port name="Cxf9147Port" binding="tns:Cxf9147Binding">
+            <soap:address location="http://localhost/cxf9147"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

Reply via email to