/framework/src/bran/ModelClassVisitor.java

https://github.com/branaway/play · Java · 296 lines · 248 code · 26 blank · 22 comment · 2 complexity · 284f3432b0e261f3c785c392e24cd5cf MD5 · raw file

  1. package bran;
  2. import java.io.ByteArrayInputStream;
  3. import org.objectweb.asm.ClassReader;
  4. import org.objectweb.asm.ClassVisitor;
  5. import org.objectweb.asm.ClassWriter;
  6. import org.objectweb.asm.Handle;
  7. import org.objectweb.asm.MethodVisitor;
  8. import org.objectweb.asm.Opcodes;
  9. import org.objectweb.asm.Type;
  10. /**
  11. *
  12. */
  13. /**
  14. * @author bran
  15. *
  16. */
  17. public class ModelClassVisitor extends ClassVisitor implements Opcodes {
  18. /**
  19. *
  20. */
  21. private static final String JPQL = "play/db/jpa/JPQL";
  22. /**
  23. *
  24. */
  25. private static final String GET_JPA_CONFIG = "getJPAConfig";
  26. /**
  27. *
  28. */
  29. private static final String JPA_BASE = "play/db/jpa/JPABase";
  30. String entityName;
  31. private boolean isInterface;
  32. public ModelClassVisitor(ClassWriter cv) {
  33. super(ASM5, cv);
  34. }
  35. /**
  36. *
  37. */
  38. public ModelClassVisitor() {
  39. this(new ClassWriter(ClassWriter.COMPUTE_MAXS));
  40. }
  41. @Override
  42. public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  43. cv.visit(version, access, name, signature, superName, interfaces);
  44. entityName = name;
  45. isInterface = (access & ACC_INTERFACE) != 0;
  46. }
  47. @Override
  48. public void visitEnd() {
  49. if (!isInterface) {
  50. count();
  51. count2();
  52. findAll();
  53. findById();
  54. find();
  55. findQuery();
  56. allQuery();
  57. delete();
  58. deleteAll();
  59. findOneBy();
  60. create();
  61. }
  62. cv.visitEnd();
  63. }
  64. private void count() {
  65. String name = "count";
  66. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "()J", null, null);
  67. mv.visitCode();
  68. getJPQL(mv);
  69. mv.visitLdcInsn(en());
  70. // mv.visitLdcInsn(entityName);
  71. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;)J", false);
  72. mv.visitInsn(LRETURN);
  73. mv.visitMaxs(2, 0);
  74. mv.visitEnd();
  75. }
  76. private String en() {
  77. return entityName.substring(entityName.lastIndexOf('/') + 1);
  78. }
  79. private Type t() {
  80. return Type.getType("L" + entityName + ";");
  81. }
  82. private void count2() {
  83. String name = "count";
  84. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "(Ljava/lang/String;[Ljava/lang/Object;)J",
  85. null, null);
  86. mv.visitCode();
  87. getJPQL(mv);
  88. mv.visitLdcInsn(en());
  89. mv.visitVarInsn(ALOAD, 0);
  90. mv.visitVarInsn(ALOAD, 1);
  91. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)J",
  92. false);
  93. mv.visitInsn(LRETURN);
  94. mv.visitMaxs(4, 2);
  95. mv.visitEnd();
  96. }
  97. private void findAll() {
  98. String name = "findAll";
  99. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "()Ljava/util/List;", null, null);
  100. mv.visitCode();
  101. getJPQL(mv);
  102. mv.visitLdcInsn(en());
  103. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;)Ljava/util/List;", false);
  104. mv.visitInsn(ARETURN);
  105. mv.visitMaxs(2, 0);
  106. mv.visitEnd();
  107. }
  108. private void findQuery() {
  109. String name = "find";
  110. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "()Lplay/db/jpa/GenericModel$JPAQuery;", null,
  111. null);
  112. mv.visitCode();
  113. getJPQL(mv);
  114. mv.visitLdcInsn(en());
  115. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;)Lplay/db/jpa/GenericModel$JPAQuery;", false);
  116. mv.visitInsn(ARETURN);
  117. mv.visitMaxs(2, 0);
  118. mv.visitEnd();
  119. }
  120. private void findById() {
  121. String name = "findById";
  122. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name,
  123. "(Ljava/lang/Object;)Lplay/db/jpa/GenericModel;", null, null);
  124. mv.visitCode();
  125. getJPQL(mv);
  126. mv.visitLdcInsn(t());
  127. mv.visitVarInsn(ALOAD, 0);
  128. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name,
  129. "(Ljava/lang/Class;Ljava/lang/Object;)Lplay/db/jpa/GenericModel;", false);
  130. mv.visitInsn(ARETURN);
  131. mv.visitMaxs(3, 1);
  132. mv.visitEnd();
  133. }
  134. private void allQuery() {
  135. String name = "all";
  136. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "()Lplay/db/jpa/GenericModel$JPAQuery;", null,
  137. null);
  138. mv.visitCode();
  139. getJPQL(mv);
  140. mv.visitLdcInsn(en());
  141. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;)Lplay/db/jpa/GenericModel$JPAQuery;", false);
  142. mv.visitInsn(ARETURN);
  143. mv.visitMaxs(2, 0);
  144. mv.visitEnd();
  145. }
  146. private void find() {
  147. String name = "find";
  148. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name,
  149. "(Ljava/lang/String;[Ljava/lang/Object;)Lplay/db/jpa/GenericModel$JPAQuery;", null, null);
  150. mv.visitCode();
  151. getJPQL(mv);
  152. mv.visitLdcInsn(en());
  153. mv.visitVarInsn(ALOAD, 0);
  154. mv.visitVarInsn(ALOAD, 1);
  155. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name,
  156. "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Lplay/db/jpa/GenericModel$JPAQuery;", false);
  157. mv.visitInsn(ARETURN);
  158. mv.visitMaxs(4, 2);
  159. mv.visitEnd();
  160. }
  161. private void delete() {
  162. String name = "delete";
  163. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "(Ljava/lang/String;[Ljava/lang/Object;)I",
  164. null, null);
  165. mv.visitCode();
  166. getJPQL(mv);
  167. mv.visitLdcInsn(en());
  168. mv.visitVarInsn(ALOAD, 0);
  169. mv.visitVarInsn(ALOAD, 1);
  170. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)I",
  171. false);
  172. mv.visitInsn(IRETURN);
  173. mv.visitMaxs(4, 2);
  174. mv.visitEnd();
  175. }
  176. private void deleteAll() {
  177. String name = "deleteAll";
  178. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name, "()I", null, null);
  179. mv.visitCode();
  180. getJPQL(mv);
  181. mv.visitLdcInsn(en());
  182. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name, "(Ljava/lang/String;)I", false);
  183. mv.visitInsn(IRETURN);
  184. mv.visitMaxs(2, 0);
  185. mv.visitEnd();
  186. }
  187. private void findOneBy() {
  188. String name = "findOneBy";
  189. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, name,
  190. "(Ljava/lang/String;[Ljava/lang/Object;)Lplay/db/jpa/GenericModel;", null, null);
  191. mv.visitCode();
  192. getJPQL(mv);
  193. mv.visitLdcInsn(en());
  194. mv.visitVarInsn(ALOAD, 0);
  195. mv.visitVarInsn(ALOAD, 1);
  196. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, name,
  197. "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Lplay/db/jpa/GenericModel;", false);
  198. mv.visitInsn(ARETURN);
  199. mv.visitMaxs(4, 2);
  200. mv.visitEnd();
  201. }
  202. private void getJPQL(MethodVisitor mv) {
  203. mv.visitLdcInsn(t());
  204. mv.visitMethodInsn(INVOKESTATIC, JPA_BASE, GET_JPA_CONFIG, "(Ljava/lang/Class;)Lplay/db/jpa/JPAConfig;", false);
  205. mv.visitFieldInsn(GETFIELD, "play/db/jpa/JPAConfig", "jpql", "Lplay/db/jpa/JPQL;");
  206. }
  207. private void create() {
  208. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, "create",
  209. "(Ljava/lang/String;Lplay/mvc/Scope$Params;)Lplay/db/jpa/JPABase;", null,
  210. new String[] { "java/lang/Exception" });
  211. mv.visitCode();
  212. getJPQL(mv);
  213. mv.visitLdcInsn(t());
  214. mv.visitVarInsn(ALOAD, 0);
  215. mv.visitVarInsn(ALOAD, 1);
  216. mv.visitMethodInsn(INVOKEVIRTUAL, JPQL, "create",
  217. "(Ljava/lang/Class;Ljava/lang/String;Lplay/mvc/Scope$Params;)Lplay/db/jpa/GenericModel;", false);
  218. mv.visitInsn(ARETURN);
  219. mv.visitMaxs(4, 2);
  220. mv.visitEnd();
  221. }
  222. public static byte[] visitModel(byte[] code) {
  223. try {
  224. ModelClassVisitor modelClassVisitor = new ModelClassVisitor();
  225. new ClassReader(new ByteArrayInputStream(code)).accept(modelClassVisitor, 0);
  226. return modelClassVisitor.output();
  227. } catch (Exception e) {
  228. throw new RuntimeException(e);
  229. }
  230. }
  231. // static ControllerClassVisitor controllerClassVisitor = new
  232. // ControllerClassVisitor();
  233. public byte[] output() {
  234. return ((ClassWriter) super.cv).toByteArray();
  235. }
  236. private void MetRef() {
  237. MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "testMethRef", "()V", null, null);
  238. mv.visitCode();
  239. mv.visitInsn(ICONST_2);
  240. mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  241. mv.visitInsn(DUP);
  242. mv.visitInsn(ICONST_0);
  243. mv.visitLdcInsn("1");
  244. mv.visitInsn(AASTORE);
  245. mv.visitInsn(DUP);
  246. mv.visitInsn(ICONST_1);
  247. mv.visitLdcInsn("2");
  248. mv.visitInsn(AASTORE);
  249. mv.visitMethodInsn(INVOKESTATIC, "java/util/stream/Stream", "of",
  250. "([Ljava/lang/Object;)Ljava/util/stream/Stream;", true);
  251. mv.visitInvokeDynamicInsn(
  252. "accept",
  253. "()Ljava/util/function/Consumer;",
  254. new Handle(
  255. Opcodes.H_INVOKESTATIC,
  256. "java/lang/invoke/LambdaMetafactory",
  257. "metafactory",
  258. "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"),
  259. new Object[] {
  260. Type.getType("(Ljava/lang/Object;)V"),
  261. new Handle(Opcodes.H_INVOKESTATIC, "bran/AsmTests", "findById",
  262. "(Ljava/lang/Object;)Lplay/db/jpa/GenericModel;"),
  263. Type.getType("(Ljava/lang/String;)V") });
  264. mv.visitMethodInsn(INVOKEINTERFACE, "java/util/stream/Stream", "forEach", "(Ljava/util/function/Consumer;)V",
  265. true);
  266. mv.visitInsn(RETURN);
  267. mv.visitMaxs(4, 1);
  268. mv.visitEnd();
  269. }
  270. }