From 8c71fa81743d0e676f81ca8b4bed19968908f2ad Mon Sep 17 00:00:00 2001 From: Unknow Date: Fri, 24 Oct 2025 18:41:54 +0200 Subject: [PATCH 1/2] gh-85 move handler loading to serviceloader --- .../java/unknow/server/bench/BenchJaxb.java | 3 +- .../main/java/unknow/server/jaxb/Context.java | 2 +- .../unknow/server/jaxb/ContextFactory.java | 120 +++++----- .../server/jaxb/IndentedXmlStreamWriter.java | 2 +- .../java/unknow/server/jaxb/XmlHandler.java | 4 + .../unknow/server/jaxb/XmlHandlerLoader.java | 16 ++ .../jaxb/handler/BigDecimalHandler.java | 6 + .../jaxb/handler/BigIntegerHandler.java | 5 + .../server/jaxb/handler/BooleanHandler.java | 5 + .../server/jaxb/handler/ByteHandler.java | 5 + .../server/jaxb/handler/CharHandler.java | 5 + .../server/jaxb/handler/DoubleHandler.java | 5 + .../server/jaxb/handler/DurationHandler.java | 5 + .../server/jaxb/handler/FloatHandler.java | 5 + .../server/jaxb/handler/IntHandler.java | 5 + .../server/jaxb/handler/LocalDateHandler.java | 5 + .../jaxb/handler/LocalDateTimeHandler.java | 5 + .../server/jaxb/handler/LocalTimeHandler.java | 5 + .../server/jaxb/handler/LongHandler.java | 5 + .../jaxb/handler/OffsetDateTimeHandler.java | 5 + .../server/jaxb/handler/PeriodHandler.java | 5 + .../server/jaxb/handler/ShortHandler.java | 5 + .../server/jaxb/handler/StringHandler.java | 5 + .../jaxb/handler/ZonedDateTimeHandler.java | 5 + .../unknow-server-jaxb/resource-config.json | 7 + .../jakarta.xml.bind.JAXBContextFactory | 1 + .../server/jaxb/ContextFactoryTest.java | 2 +- .../java/unknow/server/jaxb/ContextTest.java | 23 -- .../java/unknow/server/jaxb/OHandler.java | 6 + .../java/unknow/server/jaxb/XmlLoader.java | 18 ++ .../jakarta.xml.bind.JAXBContextFactory | 1 - .../unknow.server.jaxb.XmlHandlerLoader | 1 + .../server/maven/AbstractGeneratorMojo.java | 5 +- .../server/maven/ImportGroupsOrdering.java | 77 ++++++ .../java/unknow/server/maven/Indentation.java | 52 ++++ .../main/java/unknow/server/maven/Output.java | 13 +- .../maven/PrettyPrintConfiguration.java | 226 ++++++++++++++++++ .../server/maven/jaxb/JaxbGeneratorMojo.java | 129 ++++++---- .../maven/jaxb/builder/HandlerEnum.java | 4 + .../maven/jaxb/builder/HandlerObject.java | 5 + .../unknow/server/maven/jaxrs/JaxrsMojo.java | 19 ++ .../resource-config.json | 7 +- 42 files changed, 683 insertions(+), 151 deletions(-) create mode 100644 unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandlerLoader.java create mode 100644 unknow-server-jaxb/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-jaxb/resource-config.json create mode 100644 unknow-server-jaxb/src/main/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory delete mode 100644 unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextTest.java create mode 100644 unknow-server-jaxb/src/test/java/unknow/server/jaxb/XmlLoader.java delete mode 100644 unknow-server-jaxb/src/test/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory create mode 100644 unknow-server-jaxb/src/test/resources/META-INF/services/unknow.server.jaxb.XmlHandlerLoader create mode 100644 unknow-server-maven/src/main/java/unknow/server/maven/ImportGroupsOrdering.java create mode 100644 unknow-server-maven/src/main/java/unknow/server/maven/Indentation.java create mode 100644 unknow-server-maven/src/main/java/unknow/server/maven/PrettyPrintConfiguration.java rename unknow-server-servlet/src/main/resources/META-INF/native-image/{ => io.github.unknow0.server/unknow-server-servlet}/resource-config.json (59%) diff --git a/unknow-server-bench/src/main/java/unknow/server/bench/BenchJaxb.java b/unknow-server-bench/src/main/java/unknow/server/bench/BenchJaxb.java index 5a2c2e2e..45bee18e 100644 --- a/unknow-server-bench/src/main/java/unknow/server/bench/BenchJaxb.java +++ b/unknow-server-bench/src/main/java/unknow/server/bench/BenchJaxb.java @@ -12,6 +12,7 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import unknow.server.http.test.xml.Complex; +import unknow.server.jaxb.ContextFactory; public class BenchJaxb { private static final ClassLoader cl = BenchJaxb.class.getClassLoader(); @@ -23,7 +24,7 @@ public class BenchJaxb { static { try { - UNKNOW = new unknow.server.http.test.generated.JaxbContextFactory().createContext(CLASS, null); + UNKNOW = new ContextFactory().createContext(CLASS, null); JAXB = new org.glassfish.jaxb.runtime.v2.JAXBContextFactory().createContext(CLASS, null); MOXY = new org.eclipse.persistence.jaxb.XMLBindingContextFactory().createContext(CLASS, null); } catch (JAXBException e) { diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/Context.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/Context.java index 31e178fd..e15484cc 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/Context.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/Context.java @@ -15,7 +15,7 @@ /** * @author unknow */ -public class Context extends JAXBContext { +public final class Context extends JAXBContext { private final Map> rootElements; private final Map, XmlRootHandler> rootHandlers; diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java index 44f84147..3db86481 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java @@ -3,49 +3,81 @@ */ package unknow.server.jaxb; -import java.math.BigDecimal; -import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.ServiceLoader; import javax.xml.namespace.QName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBContextFactory; import jakarta.xml.bind.JAXBException; -import unknow.server.jaxb.handler.BigDecimalHandler; -import unknow.server.jaxb.handler.BigIntegerHandler; -import unknow.server.jaxb.handler.BooleanHandler; -import unknow.server.jaxb.handler.ByteHandler; -import unknow.server.jaxb.handler.CharHandler; -import unknow.server.jaxb.handler.DoubleHandler; -import unknow.server.jaxb.handler.FloatHandler; -import unknow.server.jaxb.handler.IntHandler; -import unknow.server.jaxb.handler.LongHandler; -import unknow.server.jaxb.handler.ShortHandler; -import unknow.server.jaxb.handler.StringHandler; /** * @author unknow */ -public abstract class ContextFactory implements JAXBContextFactory { - private final Map, XmlHandler> handlers = new HashMap<>(); +public final class ContextFactory implements JAXBContextFactory { + private static final Logger logger = LoggerFactory.getLogger(ContextFactory.class); + + private static final Map, XmlHandler> handlers = new HashMap<>(); + private static final Map>> classes = new HashMap<>(); + + static { + for (XmlHandlerLoader l : ServiceLoader.load(XmlHandlerLoader.class)) { + if (classes.containsKey(l.contextPath())) + logger.warn("Duplicate context {}", l.contextPath()); + Collection> list = l.handlers(); + Class[] c = new Class[list.size()]; + int i = 0; + for (XmlHandler h : list) { + if (handlers.containsKey(h.clazz())) + logger.warn("Duplicate handled {}", l.contextPath()); + c[i++] = h.clazz(); + handlers.put(h.clazz(), h); + } + classes.put(l.contextPath(), Arrays.asList(c)); + } - protected void register(Class cl, XmlHandler h) { - handlers.put(cl, h); +// handlers.put(BigDecimal.class, BigDecimalHandler.INSTANCE); +// handlers.put(BigInteger.class, BigIntegerHandler.INSTANCE); +// handlers.put(String.class, StringHandler.INSTANCE); +// handlers.put(boolean.class, BooleanHandler.INSTANCE); +// handlers.put(Boolean.class, BooleanHandler.INSTANCE); +// handlers.put(byte.class, ByteHandler.INSTANCE); +// handlers.put(Byte.class, ByteHandler.INSTANCE); +// handlers.put(short.class, ShortHandler.INSTANCE); +// handlers.put(Short.class, ShortHandler.INSTANCE); +// handlers.put(char.class, CharHandler.INSTANCE); +// handlers.put(Character.class, CharHandler.INSTANCE); +// handlers.put(int.class, IntHandler.INSTANCE); +// handlers.put(Integer.class, IntHandler.INSTANCE); +// handlers.put(long.class, LongHandler.INSTANCE); +// handlers.put(Long.class, LongHandler.INSTANCE); +// handlers.put(float.class, FloatHandler.INSTANCE); +// handlers.put(Float.class, FloatHandler.INSTANCE); +// handlers.put(double.class, DoubleHandler.INSTANCE); +// handlers.put(Double.class, DoubleHandler.INSTANCE); } @Override public JAXBContext createContext(Class[] classesToBeBound, Map properties) throws JAXBException { + return createContext(Arrays.asList(classesToBeBound)); + } + + private JAXBContext createContext(Collection> classesToBeBound) throws JAXBException { Map, XmlHandler> h = new HashMap<>(); Map, XmlRootHandler> rh = new HashMap<>(); Map> re = new HashMap<>(); for (Class c : classesToBeBound) { XmlHandler x = handlers.get(c); - if (x == null) - x = defaultHandler(c); if (x == null) throw new JAXBException("No handler for class " + c); if (x instanceof XmlRootHandler) { @@ -58,55 +90,17 @@ public JAXBContext createContext(Class[] classesToBeBound, Map pro return new Context(re, rh, h); } - private final XmlHandler defaultHandler(Class cl) { - if (BigDecimal.class == cl) - return BigDecimalHandler.INSTANCE; - if (BigInteger.class == cl) - return BigIntegerHandler.INSTANCE; - if (String.class == cl) - return StringHandler.INSTANCE; - if (boolean.class == cl || Boolean.class == cl) - return BooleanHandler.INSTANCE; - if (byte.class == cl || Byte.class == cl) - return ByteHandler.INSTANCE; - if (short.class == cl || Short.class == cl) - return ShortHandler.INSTANCE; - if (char.class == cl || Character.class == cl) - return CharHandler.INSTANCE; - if (int.class == cl || Integer.class == cl) - return IntHandler.INSTANCE; - if (long.class == cl || Long.class == cl) - return LongHandler.INSTANCE; - if (float.class == cl || Float.class == cl) - return FloatHandler.INSTANCE; - if (double.class == cl || Double.class == cl) - return DoubleHandler.INSTANCE; - return null; - } - - protected abstract Collection> getClasses(String contextPackage); - @Override public JAXBContext createContext(String contextPath, ClassLoader classLoader, Map properties) throws JAXBException { - Map, XmlHandler> h = new HashMap<>(); - Map, XmlRootHandler> rh = new HashMap<>(); - Map> re = new HashMap<>(); - + List> list = new ArrayList<>(); for (String s : contextPath.split(":")) { - for (Class c : getClasses(s)) { - XmlHandler x = handlers.get(c); - if (x == null) - throw new JAXBException("No handler for class " + c); - if (x instanceof XmlRootHandler) { - XmlRootHandler r = (XmlRootHandler) x; - re.put(r.qname(), r); - rh.put(c, r); - } - h.put(c, x); - } + Collection> a = classes.get(s); + if (a == null) + throw new JAXBException("No classes mapped in context " + s); + list.addAll(a); } - return new Context(re, rh, h); + return createContext(list); } } diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/IndentedXmlStreamWriter.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/IndentedXmlStreamWriter.java index a033a4bf..58d4745e 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/IndentedXmlStreamWriter.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/IndentedXmlStreamWriter.java @@ -266,7 +266,7 @@ protected void beforeEndElement() { if (depth > 0 && stack[depth] == WROTE_MARKUP) { // but not data try { writeNewLine(depth - 1); - } catch (Exception ignored) { // ok + } catch (@SuppressWarnings("unused") Exception e) { // ok } } } diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandler.java index 92817918..0eb9bc9c 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandler.java @@ -16,6 +16,10 @@ * @param xmlElement */ public interface XmlHandler { + /** + * @return mapped class + */ + Class clazz(); /** * write object content diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandlerLoader.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandlerLoader.java new file mode 100644 index 00000000..f93a7a1b --- /dev/null +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/XmlHandlerLoader.java @@ -0,0 +1,16 @@ +package unknow.server.jaxb; + +import java.util.Collection; + +public interface XmlHandlerLoader { + /** + * @return the linked context path + */ + String contextPath(); + + /** + * @return the mapped class + */ + Collection> handlers(); + +} diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigDecimalHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigDecimalHandler.java index eb7943f8..ede5369b 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigDecimalHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigDecimalHandler.java @@ -18,6 +18,11 @@ public class BigDecimalHandler implements XmlSimpleHandler { private BigDecimalHandler() { } + @Override + public Class clazz() { + return BigDecimal.class; + } + @Override public String toString(BigDecimal t) { return t.toString(); @@ -27,4 +32,5 @@ public String toString(BigDecimal t) { public BigDecimal toObject(String s) throws JAXBException { return new BigDecimal(s); } + } diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigIntegerHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigIntegerHandler.java index ee901d6e..31701146 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigIntegerHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BigIntegerHandler.java @@ -18,6 +18,11 @@ public class BigIntegerHandler implements XmlSimpleHandler { private BigIntegerHandler() { } + @Override + public Class clazz() { + return BigInteger.class; + } + @Override public String toString(BigInteger t) { return t.toString(); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BooleanHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BooleanHandler.java index 9f3fb649..7bcda16e 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BooleanHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/BooleanHandler.java @@ -15,6 +15,11 @@ public class BooleanHandler implements XmlSimpleHandler { private BooleanHandler() { } + @Override + public Class clazz() { + return Boolean.class; + } + @Override public String toString(Boolean t) { return Boolean.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ByteHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ByteHandler.java index 3e03ac45..74f6ebcb 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ByteHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ByteHandler.java @@ -15,6 +15,11 @@ public class ByteHandler implements XmlSimpleHandler { private ByteHandler() { } + @Override + public Class clazz() { + return Byte.class; + } + @Override public String toString(Byte t) { return Byte.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/CharHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/CharHandler.java index d70d0a6f..7a722ca3 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/CharHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/CharHandler.java @@ -15,6 +15,11 @@ public class CharHandler implements XmlSimpleHandler { private CharHandler() { } + @Override + public Class clazz() { + return Character.class; + } + @Override public String toString(Character t) { return Character.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DoubleHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DoubleHandler.java index bf744599..cdba50c3 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DoubleHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DoubleHandler.java @@ -15,6 +15,11 @@ public class DoubleHandler implements XmlSimpleHandler { private DoubleHandler() { } + @Override + public Class clazz() { + return Double.class; + } + @Override public String toString(Double t) { return Double.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DurationHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DurationHandler.java index 7fde31dc..fd93f3f0 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DurationHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/DurationHandler.java @@ -10,6 +10,11 @@ public class DurationHandler implements XmlSimpleHandler { private DurationHandler() { } + @Override + public Class clazz() { + return Duration.class; + } + @Override public String toString(Duration t) { return t.toString(); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/FloatHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/FloatHandler.java index 1c4e9bf4..49f71551 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/FloatHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/FloatHandler.java @@ -15,6 +15,11 @@ public class FloatHandler implements XmlSimpleHandler { private FloatHandler() { } + @Override + public Class clazz() { + return Float.class; + } + @Override public String toString(Float t) { return Float.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/IntHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/IntHandler.java index e995e0c2..2206cac2 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/IntHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/IntHandler.java @@ -15,6 +15,11 @@ public class IntHandler implements XmlSimpleHandler { private IntHandler() { } + @Override + public Class clazz() { + return Integer.class; + } + @Override public String toString(Integer t) { return Integer.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateHandler.java index 444bfdc5..1733b920 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateHandler.java @@ -13,6 +13,11 @@ public class LocalDateHandler implements XmlSimpleHandler { private LocalDateHandler() { } + @Override + public Class clazz() { + return LocalDate.class; + } + @Override public String toString(LocalDate t) { return t.format(FMT); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateTimeHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateTimeHandler.java index ce56c1d1..82258d02 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateTimeHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalDateTimeHandler.java @@ -13,6 +13,11 @@ public class LocalDateTimeHandler implements XmlSimpleHandler { private LocalDateTimeHandler() { } + @Override + public Class clazz() { + return LocalDateTime.class; + } + @Override public String toString(LocalDateTime t) { return t.format(FMT); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalTimeHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalTimeHandler.java index 3f567bb1..842aca1c 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalTimeHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LocalTimeHandler.java @@ -13,6 +13,11 @@ public class LocalTimeHandler implements XmlSimpleHandler { private LocalTimeHandler() { } + @Override + public Class clazz() { + return LocalTime.class; + } + @Override public String toString(LocalTime t) { return t.format(FMT); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LongHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LongHandler.java index d5c017b2..aef0e2c2 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LongHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/LongHandler.java @@ -15,6 +15,11 @@ public class LongHandler implements XmlSimpleHandler { private LongHandler() { } + @Override + public Class clazz() { + return Long.class; + } + @Override public String toString(Long t) { return Long.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/OffsetDateTimeHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/OffsetDateTimeHandler.java index 01183555..a5bbae81 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/OffsetDateTimeHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/OffsetDateTimeHandler.java @@ -15,6 +15,11 @@ public class OffsetDateTimeHandler implements XmlSimpleHandler { private OffsetDateTimeHandler() { } + @Override + public Class clazz() { + return OffsetDateTime.class; + } + @Override public String toString(OffsetDateTime t) { return t.format(FMT); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/PeriodHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/PeriodHandler.java index e47d4f52..4b9bb79e 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/PeriodHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/PeriodHandler.java @@ -10,6 +10,11 @@ public class PeriodHandler implements XmlSimpleHandler { private PeriodHandler() { } + @Override + public Class clazz() { + return Period.class; + } + @Override public String toString(Period t) { return t.toString(); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ShortHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ShortHandler.java index d409ea13..83805633 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ShortHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ShortHandler.java @@ -15,6 +15,11 @@ public class ShortHandler implements XmlSimpleHandler { private ShortHandler() { } + @Override + public Class clazz() { + return Short.class; + } + @Override public String toString(Short t) { return Short.toString(t); diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/StringHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/StringHandler.java index 7b59141c..d28457ae 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/StringHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/StringHandler.java @@ -15,6 +15,11 @@ public final class StringHandler implements XmlSimpleHandler { private StringHandler() { } + @Override + public Class clazz() { + return String.class; + } + @Override public final String toString(String t) { return t; diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ZonedDateTimeHandler.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ZonedDateTimeHandler.java index 98d03539..14476ea1 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ZonedDateTimeHandler.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/handler/ZonedDateTimeHandler.java @@ -16,6 +16,11 @@ public class ZonedDateTimeHandler implements XmlSimpleHandler { private ZonedDateTimeHandler() { } + @Override + public Class clazz() { + return ZonedDateTime.class; + } + @Override public String toString(ZonedDateTime t) { return t.format(FMT); diff --git a/unknow-server-jaxb/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-jaxb/resource-config.json b/unknow-server-jaxb/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-jaxb/resource-config.json new file mode 100644 index 00000000..1a53928f --- /dev/null +++ b/unknow-server-jaxb/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-jaxb/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources": { + "includes": [ + {"pattern": "\\QMETA-INF/services/jakarta.xml.bind.JAXBContextFactory\\E"} + ] + } +} diff --git a/unknow-server-jaxb/src/main/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory b/unknow-server-jaxb/src/main/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory new file mode 100644 index 00000000..c0748e0d --- /dev/null +++ b/unknow-server-jaxb/src/main/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory @@ -0,0 +1 @@ +unknow.server.jaxb.ContextFactory \ No newline at end of file diff --git a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextFactoryTest.java b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextFactoryTest.java index bbce6c9d..ad2b58a5 100644 --- a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextFactoryTest.java +++ b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextFactoryTest.java @@ -23,7 +23,7 @@ */ public class ContextFactoryTest { private static final XMLInputFactory f = XMLInputFactory.newInstance(); - + @Test void test() throws JAXBException { JAXBContext.newInstance(O.class); diff --git a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextTest.java b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextTest.java deleted file mode 100644 index b1f290a1..00000000 --- a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/ContextTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - */ -package unknow.server.jaxb; - -import java.util.Collection; -import java.util.Collections; - -/** - * @author unknow - */ -public class ContextTest extends ContextFactory { - - public ContextTest() { - register(O.class, new OHandler()); - } - - @Override - protected Collection> getClasses(String contextPackage) { - return Collections.emptyList(); - } - -} diff --git a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/OHandler.java b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/OHandler.java index 5b1ec312..1d05a708 100644 --- a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/OHandler.java +++ b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/OHandler.java @@ -26,6 +26,11 @@ public OHandler() { super(new QName("", "o")); } + @Override + public Class clazz() { + return O.class; + } + @Override public void write(XMLStreamWriter w, O t, MarshallerImpl m, Marshaller.Listener listener) throws XMLStreamException { w.writeAttribute("a", Integer.toString(t.a)); @@ -58,4 +63,5 @@ public O read(XMLStreamReader r, Object parent, UnmarshallerImpl listener) throw } throw new XMLStreamException("EOF"); } + } diff --git a/unknow-server-jaxb/src/test/java/unknow/server/jaxb/XmlLoader.java b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/XmlLoader.java new file mode 100644 index 00000000..3c59cdfe --- /dev/null +++ b/unknow-server-jaxb/src/test/java/unknow/server/jaxb/XmlLoader.java @@ -0,0 +1,18 @@ +package unknow.server.jaxb; + +import java.util.Arrays; +import java.util.Collection; + +public class XmlLoader implements XmlHandlerLoader { + + @Override + public String contextPath() { + return "unknow.server.jaxb"; + } + + @Override + public Collection> handlers() { + return Arrays.asList(OHandler.INSTANCE); + } + +} diff --git a/unknow-server-jaxb/src/test/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory b/unknow-server-jaxb/src/test/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory deleted file mode 100644 index 1a31710a..00000000 --- a/unknow-server-jaxb/src/test/resources/META-INF/services/jakarta.xml.bind.JAXBContextFactory +++ /dev/null @@ -1 +0,0 @@ -unknow.server.jaxb.ContextTest \ No newline at end of file diff --git a/unknow-server-jaxb/src/test/resources/META-INF/services/unknow.server.jaxb.XmlHandlerLoader b/unknow-server-jaxb/src/test/resources/META-INF/services/unknow.server.jaxb.XmlHandlerLoader new file mode 100644 index 00000000..e9506c83 --- /dev/null +++ b/unknow-server-jaxb/src/test/resources/META-INF/services/unknow.server.jaxb.XmlHandlerLoader @@ -0,0 +1 @@ +unknow.server.jaxb.XmlLoader \ No newline at end of file diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/AbstractGeneratorMojo.java b/unknow-server-maven/src/main/java/unknow/server/maven/AbstractGeneratorMojo.java index c2cff0a8..23623b20 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/AbstractGeneratorMojo.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/AbstractGeneratorMojo.java @@ -86,6 +86,9 @@ public abstract class AbstractGeneratorMojo extends AbstractMojo { @Parameter(name = "artifacts") protected List artifacts; + @Parameter(name = "prettyPrint") + protected PrettyPrintConfiguration ppConfig = new PrettyPrintConfiguration(); + protected Output out; /** created with init() */ @@ -136,7 +139,7 @@ protected void init() throws MojoFailureException { addResource(resources); try { - out = new Output(output, packageName); + out = new Output(output, packageName, ppConfig.toPrinterConfiguration()); } catch (IOException e) { throw new MojoFailureException("failed to create output folders", e); } diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/ImportGroupsOrdering.java b/unknow-server-maven/src/main/java/unknow/server/maven/ImportGroupsOrdering.java new file mode 100644 index 00000000..3659bcff --- /dev/null +++ b/unknow-server-maven/src/main/java/unknow/server/maven/ImportGroupsOrdering.java @@ -0,0 +1,77 @@ +package unknow.server.maven; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import com.github.javaparser.ast.ImportDeclaration; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.nodeTypes.NodeWithName; +import com.github.javaparser.printer.configuration.ImportOrderingStrategy; + +/** + * Defines strategies used when ordering import statements. + */ +public class ImportGroupsOrdering implements ImportOrderingStrategy { + private static final Comparator SORT = Comparator.comparing(NodeWithName::getNameAsString); + + private boolean sortImportsAlphabetically = false; + + private final String[][] groups; + + public ImportGroupsOrdering(List groups) { + this.groups = new String[groups.size()][]; + int i = 0; + for (String s : groups) + this.groups[i++] = s.split("[, ]+"); + } + + @Override + public List> sortImports(NodeList nodes) { + @SuppressWarnings("unchecked") + NodeList[] imports = new NodeList[groups.length + 2]; + for (int i = 0; i < imports.length; i++) + imports[i] = new NodeList<>(); + int other = imports.length - 1; + + loop: for (ImportDeclaration importDeclaration : nodes) { + // Check if is a static import + if (importDeclaration.isStatic()) { + imports[0].add(importDeclaration); + continue; + } + String importName = importDeclaration.getNameAsString(); + + for (int i = 0; i < groups.length; i++) { + if (match(importName, groups[i])) { + imports[i + 1].add(importDeclaration); + continue loop; + } + } + imports[other].add(importDeclaration); + } + if (sortImportsAlphabetically) { + for (int i = 0; i < imports.length; i++) + imports[i].sort(SORT); + } + return Arrays.asList(imports); + } + + private boolean match(String importName, String[] group) { + for (int i = 0; i < group.length; i++) { + if (importName.startsWith(group[i])) + return true; + } + return false; + } + + @Override + public void setSortImportsAlphabetically(boolean sortAlphabetically) { + sortImportsAlphabetically = sortAlphabetically; + } + + @Override + public boolean isSortImportsAlphabetically() { + return sortImportsAlphabetically; + } +} \ No newline at end of file diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/Indentation.java b/unknow-server-maven/src/main/java/unknow/server/maven/Indentation.java new file mode 100644 index 00000000..ae2f7d3e --- /dev/null +++ b/unknow-server-maven/src/main/java/unknow/server/maven/Indentation.java @@ -0,0 +1,52 @@ +package unknow.server.maven; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.github.javaparser.printer.configuration.Indentation.IndentType; + +/** +* Represents indentation configuration. +*/ +public class Indentation { + + /** Type of indentation (e.g., SPACES or TABS). */ + @Parameter + private IndentType type = IndentType.TABS; + + /** Number of spaces or tabs used per indentation level. */ + @Parameter + private int value = 1; + + public Indentation() { + } + + public Indentation(IndentType type, int value) { + this.type = type; + this.value = value; + } + + public IndentType getType() { + return type; + } + + public void setType(IndentType type) { + this.type = type; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + @Override + public String toString() { + return type + "(" + value + ")"; + } + + public com.github.javaparser.printer.configuration.Indentation toIndentation() { + return new com.github.javaparser.printer.configuration.Indentation(type, value); + } +} \ No newline at end of file diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/Output.java b/unknow-server-maven/src/main/java/unknow/server/maven/Output.java index d5fcb78a..2137f0ad 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/Output.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/Output.java @@ -14,11 +14,6 @@ import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.TypeDeclaration; -import com.github.javaparser.printer.configuration.DefaultConfigurationOption; -import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration; -import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration.ConfigOption; -import com.github.javaparser.printer.configuration.Indentation; -import com.github.javaparser.printer.configuration.Indentation.IndentType; import com.github.javaparser.printer.configuration.PrinterConfiguration; /** @@ -28,12 +23,8 @@ public class Output { private final Path out; private final PrinterConfiguration pp; - public Output(String output, String packageName) throws IOException { - pp = new DefaultPrinterConfiguration() - .addOption(new DefaultConfigurationOption(ConfigOption.INDENTATION, new Indentation(IndentType.TABS, 1))) - .addOption(new DefaultConfigurationOption(ConfigOption.ORDER_IMPORTS, true)) - .addOption(new DefaultConfigurationOption(ConfigOption.SPACE_AROUND_OPERATORS, true)); - + public Output(String output, String packageName, PrinterConfiguration pp) throws IOException { + this.pp = pp; Path file = Paths.get(output); if (packageName != null) file = file.resolve(packageName.replace('.', '/')); diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/PrettyPrintConfiguration.java b/unknow-server-maven/src/main/java/unknow/server/maven/PrettyPrintConfiguration.java new file mode 100644 index 00000000..3ddd8d19 --- /dev/null +++ b/unknow-server-maven/src/main/java/unknow/server/maven/PrettyPrintConfiguration.java @@ -0,0 +1,226 @@ +package unknow.server.maven; + +import java.util.Arrays; +import java.util.List; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.github.javaparser.printer.configuration.DefaultConfigurationOption; +import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration; +import com.github.javaparser.printer.configuration.DefaultPrinterConfiguration.ConfigOption; +import com.github.javaparser.printer.configuration.Indentation.IndentType; +import com.github.javaparser.printer.configuration.PrinterConfiguration; + +/** + * Configuration du formateur de code (Pretty Printer). + * + *

Chaque option correspond à une valeur de l'enum {@code ConfigOption}. + * Les paramètres définis ici peuvent être configurés directement dans le pom.xml sous le tag + * {@code }.

+ */ +public class PrettyPrintConfiguration { + + /** + * Order imports alphabetically. + */ + @Parameter(defaultValue = "true") + private boolean orderImports; + + /** + * The list of package prefix to group together to use (default ["java.", "javax.", "org.", "com."]) + */ + @Parameter + private List orderImportGroups = Arrays.asList("java.", "javax.", "org.", "com."); + + /** + * Print comments only. It can be combined with {@code PRINT_JAVADOC} to print regular comments and javadoc. + */ + @Parameter(defaultValue = "true") + private boolean printComments; + + /** + * Print javadoc comments only. It can be combined with {@code PRINT_COMMENTS} to print regular javadoc and comments. + */ + @Parameter(defaultValue = "true") + private boolean printJavadoc; + + /** + * Insert spaces around operators. + */ + @Parameter(defaultValue = "true") + private boolean spaceAroundOperators; + + /** + * Align method parameters in columns. + */ + @Parameter(defaultValue = "false") + private boolean columnAlignParameters; + + /** + * Align the first element of a method chain. + */ + @Parameter(defaultValue = "true") + private boolean columnAlignFirstMethodChain; + + /** + * Indent the case when it is true, don't if false + *
{@code
+	 * switch(x) {            switch(x) {
+	 *    case 1:             case 1:
+	 *        return y;           return y;
+	 *    case 2:             case 2:
+	 *        return z;           return x;
+	 * }                       }
+	 * }
+	 */
+	@Parameter(defaultValue = "true")
+	private boolean indentCaseInSwitch;
+
+	/**
+	* By default enum constants get aligned like this:
+	* 
{@code
+	*     enum X {
+	*        A, B, C, D
+	*     }
+	* }
+	* until the amount of constants passes this currentValue (5 by default).
+	* Then they get aligned like this:
+	* 
{@code
+	*     enum X {
+	*        A,
+	*        B,
+	*        C,
+	*        D,
+	*        E,
+	*        F,
+	*        G
+	*     }
+	* }
+ * Set it to a very large number (e.g. {@code Integer.MAX_VALUE} to always align horizontally. + * Set it to 1 or less to always align vertically. + */ + @Parameter(defaultValue = "5") + private int maxEnumConstantsToAlignHorizontally; + + /** + * The end-of-line character used when printing code. Default is system-dependent. + */ + @Parameter + private String endOfLineCharacter = System.getProperty("line.separator"); + + /** + * Indentation property. + */ + @Parameter + private Indentation indentation = new Indentation(IndentType.SPACES, 4); + + public boolean isOrderImports() { + return orderImports; + } + + public void setOrderImports(boolean orderImports) { + this.orderImports = orderImports; + } + + public List getOrderImportGroups() { + return orderImportGroups; + } + + public void setOrderImportGroups(List orderImportGroups) { + this.orderImportGroups = orderImportGroups; + } + + public boolean isPrintComments() { + return printComments; + } + + public void setPrintComments(boolean printComments) { + this.printComments = printComments; + } + + public boolean isPrintJavadoc() { + return printJavadoc; + } + + public void setPrintJavadoc(boolean printJavadoc) { + this.printJavadoc = printJavadoc; + } + + public boolean isSpaceAroundOperators() { + return spaceAroundOperators; + } + + public void setSpaceAroundOperators(boolean spaceAroundOperators) { + this.spaceAroundOperators = spaceAroundOperators; + } + + public boolean isColumnAlignParameters() { + return columnAlignParameters; + } + + public void setColumnAlignParameters(boolean columnAlignParameters) { + this.columnAlignParameters = columnAlignParameters; + } + + public boolean isColumnAlignFirstMethodChain() { + return columnAlignFirstMethodChain; + } + + public void setColumnAlignFirstMethodChain(boolean columnAlignFirstMethodChain) { + this.columnAlignFirstMethodChain = columnAlignFirstMethodChain; + } + + public boolean isIndentCaseInSwitch() { + return indentCaseInSwitch; + } + + public void setIndentCaseInSwitch(boolean indentCaseInSwitch) { + this.indentCaseInSwitch = indentCaseInSwitch; + } + + public int getMaxEnumConstantsToAlignHorizontally() { + return maxEnumConstantsToAlignHorizontally; + } + + public void setMaxEnumConstantsToAlignHorizontally(int maxEnumConstantsToAlignHorizontally) { + this.maxEnumConstantsToAlignHorizontally = maxEnumConstantsToAlignHorizontally; + } + + public String getEndOfLineCharacter() { + return endOfLineCharacter; + } + + public void setEndOfLineCharacter(String endOfLineCharacter) { + this.endOfLineCharacter = endOfLineCharacter; + } + + public Indentation getIndentation() { + return indentation; + } + + public void setIndentation(Indentation indentation) { + this.indentation = indentation; + } + + public PrinterConfiguration toPrinterConfiguration() { + PrinterConfiguration config = new DefaultPrinterConfiguration().addOption(new DefaultConfigurationOption(ConfigOption.ORDER_IMPORTS, orderImports)) + .addOption(new DefaultConfigurationOption(ConfigOption.SORT_IMPORTS_STRATEGY, new ImportGroupsOrdering(orderImportGroups))) + .addOption(new DefaultConfigurationOption(ConfigOption.MAX_ENUM_CONSTANTS_TO_ALIGN_HORIZONTALLY, maxEnumConstantsToAlignHorizontally)) + .addOption(new DefaultConfigurationOption(ConfigOption.END_OF_LINE_CHARACTER, endOfLineCharacter)) + .addOption(new DefaultConfigurationOption(ConfigOption.INDENTATION, indentation.toIndentation())); + if (indentCaseInSwitch) + config.addOption(new DefaultConfigurationOption(ConfigOption.INDENT_CASE_IN_SWITCH)); + if (spaceAroundOperators) + config.addOption(new DefaultConfigurationOption(ConfigOption.SPACE_AROUND_OPERATORS)); + if (columnAlignFirstMethodChain) + config.addOption(new DefaultConfigurationOption(ConfigOption.COLUMN_ALIGN_FIRST_METHOD_CHAIN)); + if (printComments) + config.addOption(new DefaultConfigurationOption(ConfigOption.PRINT_COMMENTS)); + if (printJavadoc) + config.addOption(new DefaultConfigurationOption(ConfigOption.PRINT_JAVADOC)); + if (columnAlignParameters) + config.addOption(new DefaultConfigurationOption(ConfigOption.COLUMN_ALIGN_PARAMETERS)); + return config; + + } +} diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java index 9acf8da1..ba518b29 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java @@ -5,19 +5,16 @@ import java.io.BufferedWriter; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.stream.Collectors; import javax.xml.namespace.QName; @@ -28,26 +25,19 @@ import org.apache.maven.plugins.annotations.ResolutionScope; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.expr.ClassExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.ast.expr.TypeExpr; -import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ReturnStmt; -import com.github.javaparser.ast.stmt.SwitchEntry; -import com.github.javaparser.ast.stmt.SwitchStmt; -import jakarta.xml.bind.JAXBContextFactory; import jakarta.xml.bind.annotation.XmlRootElement; import unknow.model.api.AnnotationModel; import unknow.model.api.TypeModel; -import unknow.server.jaxb.ContextFactory; +import unknow.server.jaxb.XmlHandler; +import unknow.server.jaxb.XmlHandlerLoader; import unknow.server.jaxb.handler.BigDecimalHandler; import unknow.server.jaxb.handler.BigIntegerHandler; import unknow.server.jaxb.handler.BooleanHandler; @@ -120,6 +110,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { xmlLoader.add(type); }); + if (xmlLoader.types().isEmpty()) { + getLog().warn("No xml binding found"); + return; + } + int i = 0; List list = new ArrayList<>(xmlLoader.types()); list.sort((a, b) -> a.name().toString().compareTo(b.name().toString())); @@ -128,10 +123,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { handlers.put(t, packageName + "." + t.type().simpleName() + "_" + i++); } + writeXmlLoader(); + for (XmlType t : xmlLoader.types()) buildHandler(t); - buildContext(); + generateGraalVmResources(); } private void buildHandler(XmlType xml) throws MojoExecutionException { @@ -149,52 +146,100 @@ private void buildHandler(XmlType xml) throws MojoExecutionException { out.save(cu); } - private void buildContext() throws MojoExecutionException { + private void writeXmlLoader() throws MojoExecutionException { CompilationUnit cu = newCu(); TypeCache types = new TypeCache(cu, existingClass); - ClassOrInterfaceDeclaration cl = cu.addClass("JaxbContextFactory").addExtendedType(types.getClass(ContextFactory.class)); - Map> classes = new HashMap<>(); + ClassOrInterfaceDeclaration cl = cu.addClass("XmlLoader", Utils.PUBLIC).addImplementedType(types.getClass(XmlHandlerLoader.class)); - BlockStmt b = new BlockStmt(); - for (Entry t : xmlLoader.entries()) { - String h = handlers.get(t.getValue()); - if (h == null || XmlLoader.XS.equals(t.getValue().name().getNamespaceURI())) - continue; - TypeModel type = loader.get(t.getKey()); - b.addStatement( - new MethodCallExpr(null, "register", Utils.list(new ClassExpr(types.get(t.getKey())), new FieldAccessExpr(new TypeExpr(types.get(h)), "INSTANCE")))); - classes.computeIfAbsent(type.packageName(), k -> new ArrayList<>()).add(type); - } + cl.addMethod("contextPath", Utils.PUBLIC).addMarkerAnnotation(Override.class).setType(types.getClass(String.class)).createBody() + .addStatement(new ReturnStmt(Utils.text(packageName))); - int i = 0; - NodeList entries = new NodeList<>(); - for (Entry> e : classes.entrySet()) { - String n = "p$" + i++; - Expression c = new MethodCallExpr(new TypeExpr(types.get(Arrays.class)), "asList", - e.getValue().stream().map(v -> new ClassExpr(types.get(v))).collect(Collectors.toCollection(() -> Utils.list()))); - cl.addFieldWithInitializer(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY)), n, c, Utils.PSF); - entries.add(new SwitchEntry().setLabels(Utils.list(new StringLiteralExpr(e.getKey()))).addStatement(new ReturnStmt(new NameExpr(n)))); + NodeList list = new NodeList<>(); + for (Entry e : handlers.entrySet()) { + if (XmlLoader.XS.equals(e.getKey().name().getNamespaceURI())) + continue; + list.add(new FieldAccessExpr(new TypeExpr(types.get(e.getValue())), "INSTANCE")); } - entries.add(new SwitchEntry().addStatement(new ReturnStmt(new MethodCallExpr(new TypeExpr(types.get(Collections.class)), "emptyList")))); + cl.addMethod("handlers", Utils.PUBLIC).addMarkerAnnotation(Override.class).setType(types.getClass(Collection.class, types.getClass(XmlHandler.class, TypeCache.ANY))) + .createBody().addStatement(new ReturnStmt(new MethodCallExpr(new TypeExpr(types.get(Arrays.class)), "asList", list))); - cl.addConstructor(Modifier.Keyword.PUBLIC).setBody(b); - cl.addMethod("getClasses", Utils.PUBLIC).addMarkerAnnotation(Override.class).setType(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY))) - .addParameter(types.get(String.class), "contextPackage").createBody().addStatement(new SwitchStmt(new NameExpr("contextPackage"), entries)); out.save(cu); - Path path = Paths.get(resources, "META-INF", "services", JAXBContextFactory.class.getName()); + Path path = Paths.get(resources, "META-INF", "services", XmlHandlerLoader.class.getName()); try { Files.createDirectories(path.getParent()); + try (BufferedWriter w = Files.newBufferedWriter(path)) { + w.append(packageName).write(".XmlLoader\n"); + } } catch (IOException e) { throw new MojoExecutionException(e); } - try (BufferedWriter w = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { - w.append(packageName).write(".JaxbContextFactory\n"); + + } + + private void generateGraalVmResources() throws MojoFailureException { + if (!graalvm) + return; + + try { + Path path = Paths.get(resources + "/META-INF/native-image/" + id() + "/resource-config.json"); + Files.createDirectories(path.getParent()); + try (BufferedWriter w = Files.newBufferedWriter(path)) { + w.write("{\"resources\":{\"includes\":["); + w.append("{\"pattern\":\"\\\\Q").append("META-INF/services/").append(XmlHandlerLoader.class.getName()).write("\\\\E\"}"); + w.write("]}}"); + } } catch (IOException e) { - throw new MojoExecutionException(e); + throw new MojoFailureException("failed generate graalvm resources", e); } } +// private void buildContext() throws MojoExecutionException { +// CompilationUnit cu = newCu(); +// TypeCache types = new TypeCache(cu, existingClass); +// ClassOrInterfaceDeclaration cl = cu.addClass("JaxbContextFactory").addExtendedType(types.getClass(ContextFactory.class)); +// Map> classes = new HashMap<>(); +// +// BlockStmt b = new BlockStmt(); +// for (Entry t : xmlLoader.entries()) { +// String h = handlers.get(t.getValue()); +// if (h == null || XmlLoader.XS.equals(t.getValue().name().getNamespaceURI())) +// continue; +// TypeModel type = loader.get(t.getKey()); +// b.addStatement( +// new MethodCallExpr(null, "register", Utils.list(new ClassExpr(types.get(t.getKey())), new FieldAccessExpr(new TypeExpr(types.get(h)), "INSTANCE")))); +// classes.computeIfAbsent(type.packageName(), k -> new ArrayList<>()).add(type); +// } +// +// int i = 0; +// NodeList entries = new NodeList<>(); +// for (Entry> e : classes.entrySet()) { +// String n = "p$" + i++; +// Expression c = new MethodCallExpr(new TypeExpr(types.get(Arrays.class)), "asList", +// e.getValue().stream().map(v -> new ClassExpr(types.get(v))).collect(Collectors.toCollection(() -> Utils.list()))); +// cl.addFieldWithInitializer(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY)), n, c, Utils.PSF); +// entries.add(new SwitchEntry().setLabels(Utils.list(new StringLiteralExpr(e.getKey()))).addStatement(new ReturnStmt(new NameExpr(n)))); +// } +// +// entries.add(new SwitchEntry().addStatement(new ReturnStmt(new MethodCallExpr(new TypeExpr(types.get(Collections.class)), "emptyList")))); +// +// cl.addConstructor(Modifier.Keyword.PUBLIC).setBody(b); +// cl.addMethod("getClasses", Utils.PUBLIC).addMarkerAnnotation(Override.class).setType(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY))) +// .addParameter(types.get(String.class), "contextPackage").createBody().addStatement(new SwitchStmt(new NameExpr("contextPackage"), entries)); +// out.save(cu); +// +// Path path = Paths.get(resources, "META-INF", "services", JAXBContextFactory.class.getName()); +// try { +// Files.createDirectories(path.getParent()); +// } catch (IOException e) { +// throw new MojoExecutionException(e); +// } +// try (BufferedWriter w = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { +// w.append(packageName).write(".JaxbContextFactory\n"); +// } catch (IOException e) { +// throw new MojoExecutionException(e); +// } +// } /** * @param t the type diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerEnum.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerEnum.java index ee51dcca..59838b51 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerEnum.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerEnum.java @@ -7,6 +7,7 @@ import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.expr.BinaryExpr; +import com.github.javaparser.ast.expr.ClassExpr; import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.NameExpr; @@ -51,6 +52,9 @@ protected void build() { Utils.list(new StringLiteralExpr(qname.getNamespaceURI()), new StringLiteralExpr(qname.getLocalPart())))))); } + cl.addMethod("clazz", Utils.PUBLIC).setType(types.getClass(Class.class, types.getClass(t))).addMarkerAnnotation(Override.class).createBody() + .addStatement(new ReturnStmt(new ClassExpr(types.getClass(t)))); + NodeList list = xml.entries().stream() .map(e -> new SwitchEntry().setLabels(Utils.list(new NameExpr(e.name()))).addStatement(new ReturnStmt(new StringLiteralExpr(e.value())))) .collect(Collectors.toCollection(() -> Utils.list())); diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerObject.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerObject.java index 834d4c47..946f38d4 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerObject.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/builder/HandlerObject.java @@ -9,10 +9,12 @@ import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.expr.ArrayInitializerExpr; +import com.github.javaparser.ast.expr.ClassExpr; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ReturnStmt; import com.github.javaparser.ast.type.ClassOrInterfaceType; import unknow.model.api.TypeModel; @@ -59,6 +61,9 @@ protected void build() { Utils.list(new StringLiteralExpr(qname.getNamespaceURI()), new StringLiteralExpr(qname.getLocalPart())))))); } + cl.addMethod("clazz", Utils.PUBLIC).setType(types.getClass(Class.class, types.getClass(t))).addMarkerAnnotation(Override.class).createBody() + .addStatement(new ReturnStmt(new ClassExpr(types.getClass(t)))); + for (AbstractSourceBuilder m : methods) m.process(cl, types, ctx); } diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/JaxrsMojo.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/JaxrsMojo.java index 2d88124e..3bd34d9a 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/JaxrsMojo.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/JaxrsMojo.java @@ -3,6 +3,7 @@ */ package unknow.server.maven.jaxrs; +import java.io.BufferedWriter; import java.io.IOException; import java.io.Writer; import java.lang.annotation.Annotation; @@ -131,6 +132,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { new OpenApiBuilder().build(openapi.getSpec(project), model, resources + basePath + "/openapi.json"); beans.save(out); mt.save(out); + + generateGraalvmResources(); } /** @@ -262,4 +265,20 @@ private void generateImplicitConverter(ClassOrInterfaceDeclaration clazz, String new ObjectCreationExpr(null, types.getClass(ParamConverter.class, TypeCache.EMPTY), null, Utils.list(), methods), Utils.PSF); } + private void generateGraalvmResources() throws MojoFailureException { + if (!graalvm) + return; + + try { + Path path = Paths.get(resources + "/META-INF/native-image/" + id() + "/resource-config.json"); + Files.createDirectories(path.getParent()); + try (BufferedWriter w = Files.newBufferedWriter(path)) { + w.write("{\"resources\":{\"includes\":["); + w.append("{\"pattern\":\"\\\\Q").append(basePath).write("/openapi.json\\\\E\"}"); + w.write("]}}"); + } + } catch (IOException e) { + throw new MojoFailureException("failed generate graalvm resources", e); + } + } } diff --git a/unknow-server-servlet/src/main/resources/META-INF/native-image/resource-config.json b/unknow-server-servlet/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-servlet/resource-config.json similarity index 59% rename from unknow-server-servlet/src/main/resources/META-INF/native-image/resource-config.json rename to unknow-server-servlet/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-servlet/resource-config.json index 708257b8..7892c0d0 100644 --- a/unknow-server-servlet/src/main/resources/META-INF/native-image/resource-config.json +++ b/unknow-server-servlet/src/main/resources/META-INF/native-image/io.github.unknow0.server/unknow-server-servlet/resource-config.json @@ -2,10 +2,5 @@ "bundles": [ {"name": "jakarta.servlet.http.LocalStrings", "locales":[""]}, {"name": "jakarta.servlet.LocalStrings", "locales":[""]} - ], - "resources": { - "includes": [ - {"pattern": "\\QMETA-INF/nioserver.properties\\E"} - ] - } + ] } From 5d0ea67f4ed60ae0f2a7488bfd5169f7908e5b2f Mon Sep 17 00:00:00 2001 From: Unknow Date: Fri, 24 Oct 2025 19:02:45 +0200 Subject: [PATCH 2/2] gh-85 fix & clean --- .../unknow/server/jaxb/ContextFactory.java | 62 ++++++++++++------- .../server/maven/jaxb/JaxbGeneratorMojo.java | 46 -------------- 2 files changed, 38 insertions(+), 70 deletions(-) diff --git a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java index 3db86481..fbd2e8f1 100644 --- a/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java +++ b/unknow-server-jaxb/src/main/java/unknow/server/jaxb/ContextFactory.java @@ -3,6 +3,8 @@ */ package unknow.server.jaxb; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -19,6 +21,17 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBContextFactory; import jakarta.xml.bind.JAXBException; +import unknow.server.jaxb.handler.BigDecimalHandler; +import unknow.server.jaxb.handler.BigIntegerHandler; +import unknow.server.jaxb.handler.BooleanHandler; +import unknow.server.jaxb.handler.ByteHandler; +import unknow.server.jaxb.handler.CharHandler; +import unknow.server.jaxb.handler.DoubleHandler; +import unknow.server.jaxb.handler.FloatHandler; +import unknow.server.jaxb.handler.IntHandler; +import unknow.server.jaxb.handler.LongHandler; +import unknow.server.jaxb.handler.ShortHandler; +import unknow.server.jaxb.handler.StringHandler; /** * @author unknow @@ -30,40 +43,41 @@ public final class ContextFactory implements JAXBContextFactory { private static final Map>> classes = new HashMap<>(); static { + handlers.put(BigDecimal.class, BigDecimalHandler.INSTANCE); + handlers.put(BigInteger.class, BigIntegerHandler.INSTANCE); + handlers.put(String.class, StringHandler.INSTANCE); + handlers.put(boolean.class, BooleanHandler.INSTANCE); + handlers.put(Boolean.class, BooleanHandler.INSTANCE); + handlers.put(byte.class, ByteHandler.INSTANCE); + handlers.put(Byte.class, ByteHandler.INSTANCE); + handlers.put(short.class, ShortHandler.INSTANCE); + handlers.put(Short.class, ShortHandler.INSTANCE); + handlers.put(char.class, CharHandler.INSTANCE); + handlers.put(Character.class, CharHandler.INSTANCE); + handlers.put(int.class, IntHandler.INSTANCE); + handlers.put(Integer.class, IntHandler.INSTANCE); + handlers.put(long.class, LongHandler.INSTANCE); + handlers.put(Long.class, LongHandler.INSTANCE); + handlers.put(float.class, FloatHandler.INSTANCE); + handlers.put(Float.class, FloatHandler.INSTANCE); + handlers.put(double.class, DoubleHandler.INSTANCE); + handlers.put(Double.class, DoubleHandler.INSTANCE); + for (XmlHandlerLoader l : ServiceLoader.load(XmlHandlerLoader.class)) { - if (classes.containsKey(l.contextPath())) - logger.warn("Duplicate context {}", l.contextPath()); + String contextPath = l.contextPath(); + if (classes.containsKey(contextPath)) + logger.warn("Duplicate context {}", contextPath); Collection> list = l.handlers(); Class[] c = new Class[list.size()]; int i = 0; for (XmlHandler h : list) { if (handlers.containsKey(h.clazz())) - logger.warn("Duplicate handled {}", l.contextPath()); + logger.warn("Duplicate handled {}", h); c[i++] = h.clazz(); handlers.put(h.clazz(), h); } - classes.put(l.contextPath(), Arrays.asList(c)); + classes.put(contextPath, Arrays.asList(c)); } - -// handlers.put(BigDecimal.class, BigDecimalHandler.INSTANCE); -// handlers.put(BigInteger.class, BigIntegerHandler.INSTANCE); -// handlers.put(String.class, StringHandler.INSTANCE); -// handlers.put(boolean.class, BooleanHandler.INSTANCE); -// handlers.put(Boolean.class, BooleanHandler.INSTANCE); -// handlers.put(byte.class, ByteHandler.INSTANCE); -// handlers.put(Byte.class, ByteHandler.INSTANCE); -// handlers.put(short.class, ShortHandler.INSTANCE); -// handlers.put(Short.class, ShortHandler.INSTANCE); -// handlers.put(char.class, CharHandler.INSTANCE); -// handlers.put(Character.class, CharHandler.INSTANCE); -// handlers.put(int.class, IntHandler.INSTANCE); -// handlers.put(Integer.class, IntHandler.INSTANCE); -// handlers.put(long.class, LongHandler.INSTANCE); -// handlers.put(Long.class, LongHandler.INSTANCE); -// handlers.put(float.class, FloatHandler.INSTANCE); -// handlers.put(Float.class, FloatHandler.INSTANCE); -// handlers.put(double.class, DoubleHandler.INSTANCE); -// handlers.put(Double.class, DoubleHandler.INSTANCE); } @Override diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java index ba518b29..f6884dfa 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxb/JaxbGeneratorMojo.java @@ -194,52 +194,6 @@ private void generateGraalVmResources() throws MojoFailureException { throw new MojoFailureException("failed generate graalvm resources", e); } } -// private void buildContext() throws MojoExecutionException { -// CompilationUnit cu = newCu(); -// TypeCache types = new TypeCache(cu, existingClass); -// ClassOrInterfaceDeclaration cl = cu.addClass("JaxbContextFactory").addExtendedType(types.getClass(ContextFactory.class)); -// Map> classes = new HashMap<>(); -// -// BlockStmt b = new BlockStmt(); -// for (Entry t : xmlLoader.entries()) { -// String h = handlers.get(t.getValue()); -// if (h == null || XmlLoader.XS.equals(t.getValue().name().getNamespaceURI())) -// continue; -// TypeModel type = loader.get(t.getKey()); -// b.addStatement( -// new MethodCallExpr(null, "register", Utils.list(new ClassExpr(types.get(t.getKey())), new FieldAccessExpr(new TypeExpr(types.get(h)), "INSTANCE")))); -// classes.computeIfAbsent(type.packageName(), k -> new ArrayList<>()).add(type); -// } -// -// int i = 0; -// NodeList entries = new NodeList<>(); -// for (Entry> e : classes.entrySet()) { -// String n = "p$" + i++; -// Expression c = new MethodCallExpr(new TypeExpr(types.get(Arrays.class)), "asList", -// e.getValue().stream().map(v -> new ClassExpr(types.get(v))).collect(Collectors.toCollection(() -> Utils.list()))); -// cl.addFieldWithInitializer(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY)), n, c, Utils.PSF); -// entries.add(new SwitchEntry().setLabels(Utils.list(new StringLiteralExpr(e.getKey()))).addStatement(new ReturnStmt(new NameExpr(n)))); -// } -// -// entries.add(new SwitchEntry().addStatement(new ReturnStmt(new MethodCallExpr(new TypeExpr(types.get(Collections.class)), "emptyList")))); -// -// cl.addConstructor(Modifier.Keyword.PUBLIC).setBody(b); -// cl.addMethod("getClasses", Utils.PUBLIC).addMarkerAnnotation(Override.class).setType(types.getClass(Collection.class, types.getClass(Class.class, TypeCache.ANY))) -// .addParameter(types.get(String.class), "contextPackage").createBody().addStatement(new SwitchStmt(new NameExpr("contextPackage"), entries)); -// out.save(cu); -// -// Path path = Paths.get(resources, "META-INF", "services", JAXBContextFactory.class.getName()); -// try { -// Files.createDirectories(path.getParent()); -// } catch (IOException e) { -// throw new MojoExecutionException(e); -// } -// try (BufferedWriter w = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { -// w.append(packageName).write(".JaxbContextFactory\n"); -// } catch (IOException e) { -// throw new MojoExecutionException(e); -// } -// } /** * @param t the type