11package com .jsoniter ;
22
33import com .jsoniter .spi .*;
4- import javassist .ClassPool ;
5- import javassist .CtClass ;
6- import javassist .CtMethod ;
7- import javassist .CtNewMethod ;
4+ import javassist .*;
85
6+ import java .io .File ;
7+ import java .io .FileOutputStream ;
8+ import java .io .IOException ;
9+ import java .io .OutputStreamWriter ;
910import java .lang .reflect .*;
1011import java .util .*;
1112
1213class Codegen {
14+ static boolean staticGen = false ;
1315 static boolean strictMode = false ;
1416 static ClassPool pool = ClassPool .getDefault ();
1517
@@ -47,21 +49,17 @@ private synchronized static Decoder gen(String cacheKey, Type type) {
4749 clazz = (Class ) type ;
4850 }
4951 String source = genSource (cacheKey , clazz , typeArgs );
52+ source = "public static Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { "
53+ + source + "}" ;
5054 if ("true" .equals (System .getenv ("JSONITER_DEBUG" ))) {
5155 System .out .println (">>> " + cacheKey );
5256 System .out .println (source );
5357 }
5458 try {
55- CtClass ctClass = pool .makeClass (cacheKey );
56- ctClass .setInterfaces (new CtClass []{pool .get (Decoder .class .getName ())});
57- CtMethod staticMethod = CtNewMethod .make (source , ctClass );
58- ctClass .addMethod (staticMethod );
59- CtMethod interfaceMethod = CtNewMethod .make ("" +
60- "public Object decode(com.jsoniter.JsonIterator iter) {" +
61- "return decode_(iter);" +
62- "}" , ctClass );
63- ctClass .addMethod (interfaceMethod );
64- decoder = (Decoder ) ctClass .toClass ().newInstance ();
59+ if (staticGen ) {
60+ staticGen (cacheKey , source );
61+ }
62+ decoder = dynamicGen (cacheKey , source );
6563 ExtensionManager .addNewDecoder (cacheKey , decoder );
6664 return decoder ;
6765 } catch (Exception e ) {
@@ -71,6 +69,60 @@ private synchronized static Decoder gen(String cacheKey, Type type) {
7169 }
7270 }
7371
72+ private static void staticGen (String cacheKey , String source ) throws IOException {
73+ createDir (cacheKey );
74+ String fileName = cacheKey .replace ('.' , '/' ) + ".java" ;
75+ FileOutputStream fileOutputStream = new FileOutputStream (fileName );
76+ try {
77+ OutputStreamWriter writer = new OutputStreamWriter (fileOutputStream );
78+ try {
79+ staticGen (cacheKey , writer , source );
80+ } finally {
81+ writer .close ();
82+ }
83+ } finally {
84+ fileOutputStream .close ();
85+ }
86+ }
87+
88+ private static void staticGen (String cacheKey , OutputStreamWriter writer , String source ) throws IOException {
89+ String className = cacheKey .substring (cacheKey .lastIndexOf ('.' ) + 1 );
90+ String packageName = cacheKey .substring (0 , cacheKey .lastIndexOf ('.' ));
91+ writer .write ("package " + packageName + ";\n " );
92+ writer .write ("public class " + className + " implements com.jsoniter.spi.Decoder {\n " );
93+ writer .write (source );
94+ writer .write ("public Object decode(com.jsoniter.JsonIterator iter) throws java.io.IOException {\n " );
95+ writer .write ("return decode_(iter);\n " );
96+ writer .write ("}\n " );
97+ writer .write ("}\n " );
98+ }
99+
100+ private static void createDir (String cacheKey ) {
101+ String [] parts = cacheKey .split ("\\ ." );
102+ File parent = new File ("." );
103+ for (int i = 0 ; i < parts .length - 1 ; i ++) {
104+ String part = parts [i ];
105+ File current = new File (parent , part );
106+ current .mkdir ();
107+ parent = current ;
108+ }
109+ }
110+
111+ private static Decoder dynamicGen (String cacheKey , String source ) throws Exception {
112+ Decoder decoder ;
113+ CtClass ctClass = pool .makeClass (cacheKey );
114+ ctClass .setInterfaces (new CtClass []{pool .get (Decoder .class .getName ())});
115+ CtMethod staticMethod = CtNewMethod .make (source , ctClass );
116+ ctClass .addMethod (staticMethod );
117+ CtMethod interfaceMethod = CtNewMethod .make ("" +
118+ "public Object decode(com.jsoniter.JsonIterator iter) {" +
119+ "return decode_(iter);" +
120+ "}" , ctClass );
121+ ctClass .addMethod (interfaceMethod );
122+ decoder = (Decoder ) ctClass .toClass ().newInstance ();
123+ return decoder ;
124+ }
125+
74126 private static String genSource (String cacheKey , Class clazz , Type [] typeArgs ) {
75127 if (CodegenImplNative .NATIVE_READS .containsKey (clazz .getName ())) {
76128 return CodegenImplNative .genNative (clazz .getName ());
@@ -104,4 +156,11 @@ private static String genSource(String cacheKey, Class clazz, Type[] typeArgs) {
104156 }
105157 return CodegenImplObject .genObjectUsingHash (clazz , cacheKey , desc );
106158 }
159+
160+ public static void staticGenDecoders (TypeLiteral [] typeLiterals ) {
161+ staticGen = true ;
162+ for (TypeLiteral typeLiteral : typeLiterals ) {
163+ gen (typeLiteral .getDecoderCacheKey (), typeLiteral .getType ());
164+ }
165+ }
107166}
0 commit comments