forked from tchronis/MSE-Mathematica
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimpleJavaReloader.m
More file actions
127 lines (101 loc) · 3.78 KB
/
SimpleJavaReloader.m
File metadata and controls
127 lines (101 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
(*http://mathematica.stackexchange.com/questions/6144/looking-for-longest-common-substring-solution/6376#6376*)
BeginPackage["SimpleJavaReloader`", {"JLink`"}];
JCompileLoad::usage =
"JCompileLoad[javacode_,addToClassPath_] attempts to compile a Java \
class defined by a string javacode, optionally adding to Java compiler classpath \
files and folders from addToClassPath, and load the resulting class into
Mathematica";
Begin["`Private`"]
JCompileLoad::dirmakeerr = "Can not create directory `1`";
$stateValid = True;
$tempJavaDirectory = FileNameJoin[{$UserBaseDirectory, "Temp", "Java"}];
$tempClassDirectory = FileNameJoin[{$tempJavaDirectory, "Classes"}];
$tempJavaLogDirectory = FileNameJoin[{$tempJavaDirectory, "Logs"}];
$tempCompileLogFile = FileNameJoin[{$tempJavaLogDirectory, "javac.log"}];
$jrePath =
FileNameJoin[{$InstallationDirectory, "SystemFiles", "Java", $SystemID}];
$javaPath = FileNameJoin[{$jrePath, "bin"}];
$jlibPath = FileNameJoin[{$jrePath, "lib"}];
$classPath = {$tempClassDirectory, $jlibPath};
Scan[
If[! FileExistsQ[#] && CreateDirectory[#] === $Failed,
Message[JCompileLoad::dirmakeerr, #];
$stateValid = False
] &,
{
$tempJavaDirectory,
$tempClassDirectory,
$tempJavaLogDirectory
}];
(* determine a short name of the class from code *)
Clear[getClass];
getClass[classCode_String] :=
With[{cl =
StringCases[classCode,
"public" ~~ Whitespace ~~ "class"|"interface" ~~ Whitespace ~~
name : (WordCharacter ..) :> name
]},
First@cl /; cl =!= {}];
getClass[__] := Throw[$Failed, error[getClass]];
(* Determine the name of the package for the class *)
Clear[getPackage];
getPackage[classCode_String] :=
With[{pk =
StringCases[classCode,
ShortestMatch["package" ~~ Whitespace ~~ p__ ~~ ";"] :> p
]},
First@pk /; pk =!= {}];
getPackage[classCode_String] := None;
getPackage[__] := Throw[$Failed, error[getPackage]];
ClearAll[getFullClass];
getFullClass[classCode_String] :=
StringJoin[If[# === None, "", # <> "."] &@
getPackage[classCode], getClass[classCode]];
(* Note: So far, tested on Windows only. Some specifics of quoting are
tuned to work around some bugs in Windows command line processor *)
Clear[makeCompileScript];
makeCompileScript[sourceFile_String] :=
StringJoin[
"\"",
"\"", FileNameJoin[{$javaPath, "javac"}] , "\"",
" -g ", sourceFile,
" -d ", $tempClassDirectory,
" -classpath ", "\"", Sequence @@ Riffle[$classPath, ";"], "\"",
" 2> ", $tempCompileLogFile,
"\""
];
Clear[getSourceFile];
getSourceFile[javacode_String] :=
FileNameJoin[{$tempClassDirectory, getClass[javacode] <> ".java"}];
Clear[JCompileLoad];
JCompileLoad::invst = "The loader is not on valid state. Perhaps some temporary \
directories do not exist";
JCompileLoad::cmperr = "The following compilation errors were encountered: `1`";
JCompileLoad[javacode_String, addToClassPath_: {}]/; $stateValid :=
Module[{sourceFile, fullClassName = getFullClass[javacode]},
sourceFile = getSourceFile[javacode];
With[{script =
Block[{$classPath = Join[$classPath, addToClassPath]},
makeCompileScript[sourceFile]
]},
Export[sourceFile, javacode, "String"];
If[Run[script] =!= 0,
Message[
JCompileLoad::cmperr,
Style[#, Red] &@Import[$tempCompileLogFile, "String"]
];
$Failed,
(*else*)
ReinstallJava[];
AddToClassPath @@ Join[$classPath, addToClassPath];
LoadJavaClass[fullClassName]
]
]
];
JCompileLoad[_String, addToClassPath_: {}] :=
(
Message[JCompileLoad::invst];
$Failed
)
End[]
EndPackage[]