11package net .b07z .sepia .server .core .tools ;
22
3+ import java .io .File ;
34import java .lang .reflect .Constructor ;
45import java .util .ArrayList ;
56import java .util .List ;
7+ import java .util .Locale ;
68
9+ import javax .tools .Diagnostic ;
710import javax .tools .DiagnosticCollector ;
811import javax .tools .JavaCompiler ;
912import javax .tools .JavaFileObject ;
13+ import javax .tools .StandardJavaFileManager ;
1014import javax .tools .ToolProvider ;
1115
1216/**
@@ -22,19 +26,18 @@ public class ClassBuilder {
2226 * NOTE! Because getClass always returns non-primitives like "Integer" instead of "int" but they are rarely used, all
2327 * classes are cast to primitives if possible. That means the constructor will not be found if it has "Integer" instead of "int".
2428 * Same is most likely true for the constructors containing the class "Object".
25- *
26- * @param package_name - name of the package, e.g. "java.util". Can be empty.
27- * @param module_name - name of the class inside the package as string, e.g.: "Date"
28- * @param arguments - arguments usually passed to the constructor
29+ * @param classLoader - loader that has access to the class. Use null or 'ClassLoader.getSystemClassLoader()' for default.
30+ * @param canonicalClassName - canonical name of the class, e.g.: "java.lang.String"
31+ * @param arguments - arguments usually passed to the constructor (optional).
2932 * @return constructed class
3033 */
31- public static Object construct (String package_name , String module_name , Object ... arguments ){
32- if (!package_name .isEmpty ()){
33- module_name = package_name + "." + module_name ; //package_name and module_name are separated in case the package_name changes
34- }
34+ public static Object construct (ClassLoader classLoader , String canonicalClassName , Object ... arguments ){
3535 try {
36+ if (classLoader == null ){
37+ classLoader = ClassLoader .getSystemClassLoader ();
38+ }
3639 Object clazz ;
37- if (arguments .length > 0 ){
40+ if (arguments != null && arguments .length > 0 ){
3841 Class <?>[] arg_clazzes = new Class [arguments .length ];
3942 for (int i =0 ; i <arguments .length ; i ++){
4043 arg_clazzes [i ] = arguments [i ].getClass ();
@@ -56,55 +59,76 @@ public static Object construct(String package_name, String module_name, Object..
5659 arg_clazzes [i ] = Short .TYPE ;
5760 }
5861 }
59- Constructor <?> conztructor = Class .forName (module_name ).getConstructor (arg_clazzes );
62+ Constructor <?> conztructor = Class .forName (canonicalClassName , true , classLoader ).getConstructor (arg_clazzes );
6063 clazz = conztructor .newInstance (arguments );
6164 }else {
62- Constructor <?> conztructor = Class .forName (module_name ).getConstructor ();
65+ Constructor <?> conztructor = Class .forName (canonicalClassName , true , classLoader ).getConstructor ();
6366 clazz = conztructor .newInstance ();
6467 }
6568 return clazz ;
6669
6770 }catch (Exception e ){
6871 e .printStackTrace ();
69- throw new RuntimeException (DateTime .getLogDate () + " ERROR - Class not found: " + module_name , e );
72+ throw new RuntimeException (DateTime .getLogDate () + " ERROR - Class not found: " + canonicalClassName , e );
7073 }
7174 }
7275
7376 /**
7477 * Constructs a new instance of a class just by using the name of the class.<br>
7578 *
76- * @param module_name - name of the class inside the package as string , e.g.: "Date "
79+ * @param canonicalClassName - canonical name of the class, e.g.: "java.lang.String "
7780 * @return constructed class
7881 */
79- public static Object construct (String module_name ){
80- try {
81- Object clazz ;
82- Constructor <?> conztructor = Class .forName (module_name ).getConstructor ();
83- clazz = conztructor .newInstance ();
84- return clazz ;
85-
86- }catch (Exception e ){
87- e .printStackTrace ();
88- throw new RuntimeException (DateTime .getLogDate () + " ERROR - Class not found: " + module_name , e );
89- }
82+ public static Object construct (String canonicalClassName ){
83+ return construct (null , canonicalClassName );
9084 }
9185
9286 /**
9387 * Experimental string source-code compiler.
94- * @param className
95- * @param classCode
96- * @param fileName
88+ * @param className - full class name including package, e.g. com.example.my_package.MyNewClass
89+ * @param classCode - source-code as seen in Java files
90+ * @param targetFolder - parent directory of compiled class file (without package-path) or null
9791 */
98- public static void compile (String className , String classCode , String fileName ){
92+ public static void compile (String className , String classCode , File targetFolder ){
9993 JavaCompiler compiler = ToolProvider .getSystemJavaCompiler ();
94+ if (compiler == null ){
95+ String msg = "Cannot find Java compiler! "
96+ + "Please upgrade from JRE to JDK or check JAVA_HOME: " + System .getProperty ("java.home" );
97+ //Debugger.println(msg, 1);
98+ throw new RuntimeException (msg );
99+ }
100100 DiagnosticCollector <JavaFileObject > diagnostics = new DiagnosticCollector <JavaFileObject >();
101101
102102 List <JavaFileObject > compilationUnits = new ArrayList <JavaFileObject >();
103103 JavaFileObject file = new SourceCodeFromString (className , classCode );
104104 compilationUnits .add (file );
105+
106+ // This sets up the class path that the compiler will use.
107+ // I've added the .jar file that contains the DoStuff interface within in it...
108+ List <String > optionList = new ArrayList <>();
109+ String folderOrMemory = "MEMORY ONLY" ;
110+ if (targetFolder != null ){
111+ folderOrMemory = targetFolder .getAbsolutePath ().toString ();
112+ optionList .add ("-d" );
113+ optionList .add (folderOrMemory );
114+ }
115+ /*
116+ optionList.add("-classpath");
117+ optionList.add(System.getProperty("java.class.path") + ";dist/InlineCompiler.jar"); //example for classpath
118+ */
119+ StandardJavaFileManager fileManager = compiler .getStandardFileManager (diagnostics , null , null );
105120
106- JavaCompiler .CompilationTask task = compiler .getTask (null , null , diagnostics , null , null , compilationUnits );
107- System .out .println (task .call () + diagnostics .getDiagnostics ().toString ()); //passes every time
121+ JavaCompiler .CompilationTask task = compiler .getTask (null , fileManager , diagnostics , optionList , null , compilationUnits );
122+ if (task .call ()){
123+ //Done
124+ Debugger .println ("Compiled '" + className + "' to '" + folderOrMemory , 3 );
125+ }else {
126+ //Error(s)
127+ for (Diagnostic <? extends JavaFileObject > diagnostic : diagnostics .getDiagnostics ()){
128+ Debugger .println ("ClassBuilder - compiling of '" + diagnostic .getSource ().toUri () + "' failed. Error: \n " +
129+ "Line " + diagnostic .getLineNumber () + ": " + diagnostic .getMessage (Locale .ENGLISH ), 1 );
130+ }
131+ }
108132 }
109133
110134}
0 commit comments