diff --git a/jaxb-ri/codemodel/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java b/jaxb-ri/codemodel/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java index 919cef3d6..5e2aa9241 100644 --- a/jaxb-ri/codemodel/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java +++ b/jaxb-ri/codemodel/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -67,6 +68,9 @@ public final class JCodeModel { /** The packages that this JCodeWriter contains. */ private final HashMap packages = new HashMap<>(); + /** The adapters that this JCodeWriter contains. */ + private final HashMap adapters = new HashMap<>(); + /** Java module in {@code module-info.java} file. */ private JModule module; @@ -242,6 +246,22 @@ public JDefinedClass _getClass(String fullyQualifiedName) { ._getClass( fullyQualifiedName.substring(idx+1) ); } + /** + * Adds an adapter to this code writer + * @param adapter the adapter to reference in this code writer + */ + public void _adapter(JDefinedClass adapter) { + this.adapters.put(adapter.name(), adapter); + } + + /** + * Returns an iterator that walks the adapters defined using this code writer. + * @return an iterator of the adapters used by this code writer + */ + public Iterator adapters() { + return adapters.values().iterator(); + } + /** * Creates a new anonymous class. * diff --git a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/addon/at_generated/PluginImpl.java b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/addon/at_generated/PluginImpl.java index 911067c0d..2d1059d38 100644 --- a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/addon/at_generated/PluginImpl.java +++ b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/addon/at_generated/PluginImpl.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -13,6 +14,7 @@ import com.sun.codemodel.JAnnotatable; import com.sun.codemodel.JAnnotationUse; import com.sun.codemodel.JClass; +import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JMethod; import com.sun.tools.xjc.BadCommandLineException; @@ -26,6 +28,7 @@ import java.io.IOException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.Iterator; import org.xml.sax.ErrorHandler; @@ -72,25 +75,31 @@ public boolean run( Outline model, Options opt, ErrorHandler errorHandler ) { annotation = model.getCodeModel().ref(genAnnotation); for (ClassOutline co : model.getClasses()) { - augument(co); + augment(co); } for (EnumOutline eo : model.getEnums()) { - augument(eo); + augment(eo); } for (PackageOutline po : model.getAllPackageContexts()) { - augument(po); + augment(po); + } + + // annotate XmlAdapter generated-classes + Iterator it = model.getCodeModel().adapters(); + while (it.hasNext()) { + annotate(it.next()); } return true; } - private void augument(EnumOutline eo) { + private void augment(EnumOutline eo) { annotate(eo.clazz); } /** * Adds "@Generated" to the classes, methods, and fields. */ - private void augument(ClassOutline co) { + private void augment(ClassOutline co) { annotate(co.implClass); for (JMethod m : co.implClass.methods()) annotate(m); @@ -98,7 +107,7 @@ private void augument(ClassOutline co) { annotate(f); } - private void augument(PackageOutline po) { + private void augment(PackageOutline po) { annotate(po.objectFactory()); } diff --git a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/reader/xmlschema/bindinfo/BIConversion.java b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/reader/xmlschema/bindinfo/BIConversion.java index f15e0a38d..91a6cd104 100644 --- a/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/reader/xmlschema/bindinfo/BIConversion.java +++ b/jaxb-ri/xjc/src/main/java/com/sun/tools/xjc/reader/xmlschema/bindinfo/BIConversion.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2024 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -168,6 +169,8 @@ private JDefinedClass generateAdapter(String parseMethod, String printMethod,XSS try { JPackage pkg = Ring.get(ClassSelector.class).getClassScope().getOwnerPackage(); adapter = pkg._class("Adapter"+id); + // reference adapter in the CodeModel instance + pkg.owner()._adapter(adapter); } catch (JClassAlreadyExistsException e) { // try another name in search for an unique name. // this isn't too efficient, but we expect people to usually use diff --git a/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java b/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java index 23742aeee..15da978f2 100644 --- a/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java +++ b/jaxb-ri/xjc/src/test/java/com/sun/tools/xjc/CodeGenTest.java @@ -11,6 +11,7 @@ package com.sun.tools.xjc; +import com.sun.codemodel.JAnnotationUse; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDeclaration; import com.sun.codemodel.JDefinedClass; @@ -223,6 +224,56 @@ public void testIssue1788() throws FileNotFoundException, URISyntaxException { } } + + /** + * Test issues #1440 for mark-generated on adapters + * + * @throws FileNotFoundException When the test schema or binding file cannot be read. + * @throws URISyntaxException When the test {@link InputSource} cannot be parsed. + * + * @see Issue #1440 + */ + public void testIssue1440() throws FileNotFoundException, URISyntaxException, BadCommandLineException { + String schemaFileName = "/schemas/issue1440/schema.xsd"; + String bindingFileName = "/schemas/issue1440/binding.xjb"; + String packageName = "org.example.issue1440"; + String someClassName = packageName + ".Gh1440Type"; + + ErrorListener errorListener = new ConsoleErrorReporter(); + + // Parse the XML schema. + SchemaCompiler sc = XJC.createSchemaCompiler(); + sc.setErrorListener(errorListener); + sc.forcePackageName(packageName); + sc.parseSchema(getInputSource(schemaFileName)); + sc.getOptions().addGrammar(getInputSource(schemaFileName)); + sc.getOptions().addBindFile(getInputSource(bindingFileName)); + sc.getOptions().parseArguments(new String[] { "-mark-generated" }); + + // Generate the defined class. + S2JJAXBModel model = sc.bind(); + Plugin[] extensions = new Plugin[]{ new com.sun.tools.xjc.addon.at_generated.PluginImpl() }; + JCodeModel cm = model.generateCode(extensions, errorListener); + JDefinedClass dc = cm._getClass(someClassName); + assertNotNull(someClassName, dc); + + // Assert Class includes narrow type + Iterator conIter = dc.constructors(); + while (conIter.hasNext()) { + JMethod con = conIter.next(); + assertTrue(toString(con).contains("java.lang.Class")); + } + + Iterator adaptersIt = cm.adapters(); + assertTrue("Should have one adapter", adaptersIt.hasNext()); + JDefinedClass adapter = adaptersIt.next(); + assertNotNull("Adapter should not be null", adapter); + assertEquals("Should have one annotations", 1, adapter.annotations().size()); + JAnnotationUse annotation = adapter.annotations().iterator().next(); + assertNotNull("Annotation should not be null", annotation); + assertEquals("Annotation should be @Generated", "jakarta.annotation.Generated", annotation.getAnnotationClass().fullName()); + } + private void assertNonEmptyJavadocBlocks(String cmString) throws IOException { int lineNo = 0; try ( LineNumberReader lnr = new LineNumberReader(new StringReader(cmString)) ) { diff --git a/jaxb-ri/xjc/src/test/resources/schemas/issue1440/binding.xjb b/jaxb-ri/xjc/src/test/resources/schemas/issue1440/binding.xjb new file mode 100644 index 000000000..338b8ebbe --- /dev/null +++ b/jaxb-ri/xjc/src/test/resources/schemas/issue1440/binding.xjb @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/jaxb-ri/xjc/src/test/resources/schemas/issue1440/schema.xsd b/jaxb-ri/xjc/src/test/resources/schemas/issue1440/schema.xsd new file mode 100644 index 000000000..a4015be19 --- /dev/null +++ b/jaxb-ri/xjc/src/test/resources/schemas/issue1440/schema.xsd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + \ No newline at end of file