11package ng .com .idempotent ;
22
3- import java .io .ByteArrayOutputStream ;
43import java .io .File ;
5- import java .io .ObjectOutputStream ;
4+ import java .io .InvalidClassException ;
5+ import java .lang .reflect .Field ;
66import java .lang .reflect .Method ;
7+ import java .lang .reflect .Modifier ;
78import java .lang .reflect .Parameter ;
89import java .nio .file .Files ;
910import java .nio .file .Paths ;
@@ -23,9 +24,9 @@ public final class Compiler {
2324 * /home/dev/src/java/com/test/sjb/HelloWorld.java
2425 * @param fullyQualifiedClassName the fully qualified name of the class e.g
2526 * com.test.sjb.HelloWorld
26- * @return a HashMap containing the base64 encoded string of the
27- * instance of the class and a json docs of the name of the class, methods
28- * and parameters. The returned String will be uploaded to the blockchain.
27+ * @return a HashMap containing the base64 encoded string of the instance of
28+ * the class and a json docs of the name of the class, methods and
29+ * parameters. The returned String will be uploaded to the blockchain.
2930 * @throws Exception
3031 */
3132 public static final HashMap <String , Object > compile (File source , String fullyQualifiedClassName ) throws Exception {
@@ -38,51 +39,86 @@ public static final HashMap<String, Object> compile(File source, String fullyQua
3839 * @param sourceCode a String containing the source code
3940 * @param fullyQualifiedClassName the fully qualified name of the class e.g
4041 * com.test.sjb.HelloWorld
41- * @return a HashMap containing the base64 encoded string of the
42- * instance of the class and a json docs of the name of the class, methods
43- * and parameters. The returned String will be uploaded to the blockchain.
42+ * @return a HashMap containing the base64 encoded string of the instance of
43+ * the class and a json docs of the name of the class, methods and
44+ * parameters. The returned String will be uploaded to the blockchain.
4445 * @throws Exception
4546 */
4647 public static final HashMap <String , Object > compile (String sourceCode , String fullyQualifiedClassName ) throws Exception {
4748 InMemoryJavaCompiler compiler = InMemoryJavaCompiler .newInstance ();
4849 Class <?> compiled = compiler .compile (fullyQualifiedClassName , sourceCode );
50+
51+ Class [] interfaces = compiled .getInterfaces ();
52+ boolean hasSmartBean = false ;
53+ for (Class c : interfaces ) {
54+ if (c .getName ().contains ("SmartBean" )) {
55+ hasSmartBean = true ;
56+ break ;
57+ }
58+ }
59+
60+ if (!hasSmartBean ) {
61+ throw new InvalidClassException (fullyQualifiedClassName + " does not implement the SmartBean Interface. All Smart Classes must implement the smart bean interface" );
62+ }
63+
64+ Field f = compiled .getDeclaredField ("serialVersionUID" );
65+ System .out .println ("Found Field: [" + f +"]" );
66+ if (f == null ) {
67+ throw new InvalidClassException (fullyQualifiedClassName + " does not have a variable called serialVersionUID. All Smart Classes must implement have this variable" );
68+ }
4969
70+ try {
71+ int foundMods = f .getModifiers ();
72+
73+ if (!Modifier .isFinal (foundMods )) {
74+ throw new InvalidClassException (fullyQualifiedClassName + " serialVersionUID does not have a final modifier. Please make serialVersionUID static final" );
75+ }
76+
77+ if (!Modifier .isStatic (foundMods )) {
78+ throw new InvalidClassException (fullyQualifiedClassName + " serialVersionUID does not have a static modifier. Please make serialVersionUID static final" );
79+ }
80+
81+ if (!f .getType ().getName ().equals ("long" )) {
82+ throw new InvalidClassException (fullyQualifiedClassName + " serialVersionUID must be of type long" );
83+ }
84+ } catch (Exception e ) {
85+ throw new InvalidClassException (e .getMessage ());
86+ }
87+
5088 CompiledCode cc = compiler .classLoader .customCompiledCode .get (fullyQualifiedClassName );
51- byte [] byteCode = cc .getByteCode ();
52-
89+ byte [] byteCode = cc .getByteCode ();
90+
5391 HashMap <String , Object > docsMap = new HashMap <>();
5492 docsMap .put ("name" , fullyQualifiedClassName );
5593
5694 List <HashMap <String , Object >> methodsList = new ArrayList <>();
5795 Method [] methods = compiled .getMethods ();
5896
59- for (Method m : methods ) {
97+ for (Method m : methods ) {
6098 String declaringClass = m .getDeclaringClass ().getName ();
6199 if (declaringClass .equals (fullyQualifiedClassName )) {
62100 HashMap <String , Object > methodsMap = new HashMap <>();
63101 String name = m .getName ();
64102 methodsMap .put ("name" , name );
65103
66104 Parameter [] parameters = m .getParameters ();
67- List <HashMap < String , String > > parametersList = new ArrayList <>();
105+ List <String > parametersList = new ArrayList <>();
68106
69107 for (Parameter p : parameters ) {
70- HashMap <String , String > parametersMap = new HashMap <>();
71- parametersMap .put ("type" , p .getType ().getCanonicalName ());
72- parametersList .add (parametersMap );
108+ parametersList .add (p .getType ().getCanonicalName ());
73109 }
74110 methodsMap .put ("parameters" , parametersList );
75111 methodsMap .put ("returnType" , m .getReturnType ().getCanonicalName ());
76112 methodsList .add (methodsMap );
77113 }
78114 }
79-
115+
80116 docsMap .put ("methods" , methodsList );
81117
82118 HashMap <String , Object > returnValue = new HashMap <>();
83119 returnValue .put ("byteCode" , Base64 .getEncoder ().encodeToString (byteCode ));
84120 returnValue .put ("documentation" , docsMap );
85-
121+
86122 return returnValue ;
87123 }
88124}
0 commit comments