@@ -22,43 +22,62 @@ public final class JtdCodegen {
2222
2323 static final Logger LOG = Logger .getLogger (JtdCodegen .class .getName ());
2424 private static final AtomicLong COUNTER = new AtomicLong ();
25+ private static final String DEFAULT_PACKAGE = "json.java21.jtd.codegen" ;
2526
2627 private JtdCodegen () {}
2728
2829 /// Result of compilation including the validator and generated class statistics.
29- public record CompileResult (JtdValidator validator , int classfileBytes , byte [] classBytes ) {}
30+ public record CompileResult (JtdValidator validator , int classfileBytes , byte [] classBytes ) {}
3031
31- /// Public factory invoked by [JtdValidator.compileGenerated] via reflection.
32- public static JtdValidator compile (JsonValue schema ) {
33- return compileWithStats (schema ).validator ();
34- }
32+ /// Public factory invoked by [JtdValidator.compileGenerated] via reflection.
33+ public static JtdValidator compile (JsonValue schema ) {
34+ return compileWithStats (schema ).validator ();
35+ }
3536
36- /// Compiles the schema and returns both the validator and the generated
37- /// classfile size in bytes. Useful for benchmarking and diagnostics.
38- public static CompileResult compileWithStats (JsonValue schema ) {
39- return compileWithStats (schema , "json.java21.jtd.codegen" , "Generated_" + COUNTER .incrementAndGet ());
40- }
37+ /// Compiles the schema and returns both the validator and the generated
38+ /// classfile size in bytes. Useful for benchmarking and diagnostics.
39+ public static CompileResult compileWithStats (JsonValue schema ) {
40+ final var className = "Generated_" + COUNTER .incrementAndGet ();
41+ final var bytes = buildBytes (schema , DEFAULT_PACKAGE , className );
42+ return instantiate (schema , bytes , DEFAULT_PACKAGE , className );
43+ }
44+
45+ /// Compiles the schema into a named validator class and returns the raw bytes.
46+ ///
47+ /// @param schema the JTD schema as a parsed [JsonValue]
48+ /// @param packageName Java package for the generated validator
49+ /// @param className Generated validator class name
50+ /// @return the generated class bytes
51+ public static byte [] compileBytes (JsonValue schema , String packageName , String className ) {
52+ return buildBytes (schema , packageName , className ).clone ();
53+ }
4154
42- /// Compiles the schema into a named validator class.
43- ///
44- /// @param schema the JTD schema as a parsed [JsonValue]
45- /// @param packageName Java package for the generated validator
46- /// @param className Generated validator class name
47- /// @return the validator, classfile size, and generated bytes
48- public static CompileResult compileWithStats (JsonValue schema , String packageName , String className ) {
49- final var jtd = new Jtd ();
50- final var compiled = jtd .compileToSchema (schema );
51- final var schemaJson = schema .toString ();
55+ private static CompileResult instantiate (JsonValue schema , byte [] bytes , String packageName , String className ) {
56+ final var internalName = packageName .replace ('.' , '/' ) + "/" + className ;
57+ final var schemaJson = schema .toString ();
58+ try {
59+ final var lookup = MethodHandles .lookup ();
60+ final var clazz = lookup .defineClass (bytes );
61+ final var ctor = clazz .getConstructor (String .class );
62+ final var validator = (JtdValidator ) ctor .newInstance (schemaJson );
63+ return new CompileResult (validator , bytes .length , bytes .clone ());
64+ } catch (Exception e ) {
65+ throw new RuntimeException ("Failed to load generated validator: " + internalName , e );
66+ }
67+ }
5268
53- final var internalName = packageName .replace ('.' , '/' ) + "/" + className ;
54- final var classDesc = ClassDesc .ofInternalName (internalName );
69+ private static byte [] buildBytes (JsonValue schema , String packageName , String className ) {
70+ final var jtd = new Jtd ();
71+ final var compiled = jtd .compileToSchema (schema );
72+ final var internalName = packageName .replace ('.' , '/' ) + "/" + className ;
73+ final var classDesc = ClassDesc .ofInternalName (internalName );
5574
56- LOG .fine (() -> "Generating validator class: " + internalName );
75+ LOG .fine (() -> "Generating validator class: " + internalName );
5776
58- final var bytes = ClassFile .of ().build (classDesc , clb -> {
59- clb .withVersion (ClassFile .JAVA_21_VERSION , 0 );
60- clb .withFlags (ClassFile .ACC_PUBLIC | ClassFile .ACC_FINAL );
61- clb .withSuperclass (Descriptors .CD_Object );
77+ return ClassFile .of ().build (classDesc , clb -> {
78+ clb .withVersion (ClassFile .JAVA_21_VERSION , 0 );
79+ clb .withFlags (ClassFile .ACC_PUBLIC | ClassFile .ACC_FINAL );
80+ clb .withSuperclass (Descriptors .CD_Object );
6281 clb .withInterfaceSymbols (Descriptors .CD_JtdValidator );
6382 clb .with (SourceFileAttribute .of ("JtdCodegen" ));
6483
@@ -69,20 +88,5 @@ public static CompileResult compileWithStats(JsonValue schema, String packageNam
6988 EmitScaffold .emitToString (clb , classDesc );
7089 EmitScaffold .emitValidateMethod (clb , classDesc , compiled );
7190 });
72-
73- final JtdValidator validator ;
74- if ("json.java21.jtd.codegen" .equals (packageName )) {
75- try {
76- final var lookup = MethodHandles .lookup ();
77- final var clazz = lookup .defineClass (bytes );
78- final var ctor = clazz .getConstructor (String .class );
79- validator = (JtdValidator ) ctor .newInstance (schemaJson );
80- } catch (Exception e ) {
81- throw new RuntimeException ("Failed to load generated validator: " + internalName , e );
82- }
83- } else {
84- validator = JtdValidator .compile (schema );
85- }
86- return new CompileResult (validator , bytes .length , bytes .clone ());
87- }
91+ }
8892}
0 commit comments