FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
node-java/src-node/nodeJavaBridge.js at master · joeferner/node-java · GitHub
joeferner
/
node-java
Public
Notifications
You must be signed in to change notification settings
Fork
288
Star
1.9k
Code
Issues
208
Pull requests
7
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
node-java
/
src-node
/
nodeJavaBridge.js
Copy path
More file actions
More file actions
Latest commit
History
History
History
327 lines (287 loc) · 11.2 KB
Breadcrumbs
node-java
/
src-node
/
nodeJavaBridge.js
Copy path
File metadata and controls
327 lines (287 loc) · 11.2 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
"use strict"
;
process
.
env
.
PATH
+=
require
(
"../build/jvm_dll_path.json"
)
;
const
path
=
require
(
"path"
)
;
const
fs
=
require
(
"fs"
)
;
const
util
=
require
(
"util"
)
;
let
binaryPath
=
null
;
try
{
if
(
fs
.
statSync
&&
fs
.
statSync
(
path
.
join
(
__dirname
,
"../build/Debug/nodejavabridge_bindings.node"
)
)
.
isFile
(
)
)
{
binaryPath
=
path
.
resolve
(
path
.
join
(
__dirname
,
"../build/Debug/nodejavabridge_bindings.node"
)
)
;
console
.
log
(
"****** NODE-JAVA RUNNING IN DEBUG MODE ******"
)
;
}
}
catch
(
_err
)
{
// do nothing fs.statSync just couldn't find the file
}
if
(
!
binaryPath
)
{
binaryPath
=
path
.
resolve
(
path
.
join
(
__dirname
,
"../build/Release/nodejavabridge_bindings.node"
)
)
;
}
const
bindings
=
require
(
binaryPath
)
;
const
java
=
(
module
.
exports
=
new
bindings
.
Java
(
)
)
;
java
.
promisify
=
util
.
promisify
;
java
.
classpath
.
push
(
path
.
resolve
(
__dirname
,
"../src-java/commons-lang3-node-java.jar"
)
)
;
java
.
classpath
.
push
(
path
.
resolve
(
__dirname
,
__dirname
,
"../src-java"
)
)
;
java
.
classpath
.
pushDir
=
function
(
dir
)
{
fs
.
readdirSync
(
dir
)
.
forEach
(
function
(
file
)
{
java
.
classpath
.
push
(
path
.
resolve
(
dir
,
file
)
)
;
}
)
;
}
;
java
.
nativeBindingLocation
=
binaryPath
;
const
callStaticMethod
=
java
.
callStaticMethod
;
const
callStaticMethodSync
=
java
.
callStaticMethodSync
;
const
newInstanceSync
=
java
.
newInstanceSync
;
let
syncSuffix
=
undefined
;
let
asyncSuffix
=
undefined
;
let
ifReadOnlySuffix
=
"_"
;
const
SyncCall
=
function
(
obj
,
method
)
{
if
(
syncSuffix
===
undefined
)
{
throw
new
Error
(
"Sync call made before jvm created"
)
;
}
const
syncMethodName
=
method
+
syncSuffix
;
if
(
syncMethodName
in
obj
)
{
return
obj
[
syncMethodName
]
.
bind
(
obj
)
;
}
else
{
throw
new
Error
(
"Sync method not found:"
+
syncMethodName
)
;
}
}
;
java
.
isJvmCreated
=
function
(
)
{
return
typeof
java
.
onJvmCreated
!==
"function"
;
}
;
const
clients
=
[
]
;
// We provide two methods for 'clients' of node-java to 'register' their use of java.
// By registering, a client gets the opportunity to be called asynchronously just before the JVM is created,
// and just after the JVM is created. The before hook function will typically be used to add to java.classpath.
// The function may peform asynchronous operations, such as async [glob](https://github.com/isaacs/node-glob)
// resolutions of wild-carded file system paths, and then notify when it has finished via either calling
// a node-style callback function, or by resolving a promise.
// A client can register function hooks to be called before and after the JVM is created.
// If the client doesn't need to be called back for either function, it can pass null or undefined.
// Both before and after here are assumed to be functions that accept one argument that is a node-callback function.
java
.
registerClient
=
function
(
before
,
after
)
{
if
(
java
.
isJvmCreated
(
)
)
{
throw
new
Error
(
"java.registerClient() called after JVM already created."
)
;
}
const
before_
=
before
&&
before
.
length
===
0
?
function
(
cb
)
{
before
(
)
;
cb
(
)
;
}
:
before
;
const
after_
=
after
&&
after
.
length
===
0
?
function
(
cb
)
{
after
(
)
;
cb
(
)
;
}
:
after
;
clients
.
push
(
{
before
:
before_
,
after
:
after_
}
)
;
}
;
// A client can register function hooks to be called before and after the JVM is created.
// If the client doesn't need to be called back for either function, it can pass null or undefined.
// Both before and after here are assumed to be functions that return Promises/A+ `thenable` objects.
java
.
registerClientP
=
function
(
beforeP
,
afterP
)
{
if
(
java
.
isJvmCreated
(
)
)
{
throw
new
Error
(
"java.registerClient() called after JVM already created."
)
;
}
clients
.
push
(
{
beforeP
:
beforeP
,
afterP
:
afterP
}
)
;
}
;
async
function
runBeforeHooks
(
)
{
for
(
const
client
of
clients
)
{
if
(
client
.
before
)
{
await
new
Promise
(
(
resolve
,
reject
)
=>
{
client
.
before
(
(
err
)
=>
{
if
(
err
)
{
return
reject
(
err
)
;
}
return
resolve
(
)
;
}
)
;
}
)
;
}
if
(
client
.
beforeP
)
{
await
client
.
beforeP
(
)
;
}
}
}
function
createJVMAsync
(
)
{
const
_ignore
=
java
.
newLong
(
0
)
;
// called just for the side effect that it will create the JVM
}
async
function
runAfterHooks
(
)
{
for
(
const
client
of
clients
)
{
if
(
client
.
after
)
{
await
new
Promise
(
(
resolve
,
reject
)
=>
{
client
.
after
(
(
err
)
=>
{
if
(
err
)
{
return
reject
(
err
)
;
}
return
resolve
(
)
;
}
)
;
}
)
;
}
if
(
client
.
afterP
)
{
await
client
.
afterP
(
)
;
}
}
}
async
function
initializeAll
(
)
{
await
runBeforeHooks
(
)
;
createJVMAsync
(
)
;
await
runAfterHooks
(
)
;
}
// This function ensures that the JVM has been launched, asynchronously. The application can be notified
// when the JVM is fully created via either a node callback function, or via a promise.
// If the parameter `callback` is provided, it is assume be a node callback function.
// This function may be called multiple times -- the 2nd and subsequent calls are no-ops.
// However, once this method has been called (or the JVM is launched as a side effect of calling other java
// methods), then clients can no longer use the registerClient API.
java
.
ensureJvm
=
function
(
callback
)
{
// First see if the promise-style API should be used.
// This must be done first in order to ensure the proper API is used.
if
(
typeof
callback
===
"undefined"
)
{
// Create a promisified version of this function.
const
launchJvmPromise
=
util
.
promisify
(
java
.
ensureJvm
.
bind
(
java
)
)
;
// Call the promisified function, returning its result, which should be a promise.
return
launchJvmPromise
(
)
;
}
// If we get here, callback must be a node-style callback function. If not, throw an error.
else
if
(
typeof
callback
!==
"function"
)
{
throw
new
Error
(
"java.launchJvm(cb) requires its one argument to be a callback function."
)
;
}
// Now check if the JVM has already been created. If so, we assume that the jvm was already successfully
// launched, and we can just implement idempotent behavior, i.e. silently notify that the JVM has been created.
else
if
(
java
.
isJvmCreated
(
)
)
{
return
setImmediate
(
callback
)
;
}
// Finally, queue the initializeAll function.
else
{
return
setImmediate
(
async
(
)
=>
{
try
{
await
initializeAll
(
)
;
callback
(
)
;
}
catch
(
err
)
{
callback
(
err
)
;
}
}
)
;
}
}
;
java
.
onJvmCreated
=
function
(
)
{
if
(
java
.
asyncOptions
)
{
syncSuffix
=
java
.
asyncOptions
.
syncSuffix
;
asyncSuffix
=
java
.
asyncOptions
.
asyncSuffix
;
if
(
typeof
syncSuffix
!==
"string"
)
{
throw
new
Error
(
"In asyncOptions, syncSuffix must be defined and must a string"
)
;
}
const
promiseSuffix
=
java
.
asyncOptions
.
promiseSuffix
;
if
(
typeof
promiseSuffix
===
"string"
)
{
const
methods
=
[
"newInstance"
,
"callMethod"
,
"callStaticMethod"
]
;
methods
.
forEach
(
function
(
name
)
{
java
[
name
+
promiseSuffix
]
=
util
.
promisify
(
java
[
name
]
)
;
}
)
;
}
if
(
typeof
java
.
asyncOptions
.
ifReadOnlySuffix
===
"string"
&&
java
.
asyncOptions
.
ifReadOnlySuffix
!==
""
)
{
ifReadOnlySuffix
=
java
.
asyncOptions
.
ifReadOnlySuffix
;
}
}
else
{
syncSuffix
=
"Sync"
;
asyncSuffix
=
""
;
}
}
;
const
MODIFIER_PUBLIC
=
1
;
const
MODIFIER_STATIC
=
8
;
function
isWritable
(
prop
)
{
// If the property has no descriptor, or wasn't explicitly marked as not writable or not configurable, assume it is.
// We check both desc.writable and desc.configurable, since checking desc.writable alone is not sufficient
// (e.g. for either .caller or .arguments).
// It may be that checking desc.configurable is sufficient, but the specification doesn't make this definitive,
// and there is no harm in checking both.
if
(
prop
===
"caller"
||
prop
===
"arguments"
)
{
return
false
;
}
const
desc
=
Object
.
getOwnPropertyDescriptor
(
function
(
)
{
}
,
prop
)
||
{
}
;
return
desc
.
writable
!==
false
&&
desc
.
configurable
!==
false
;
}
function
usableName
(
name
)
{
if
(
!
isWritable
(
name
)
)
{
name
=
name
+
ifReadOnlySuffix
;
}
return
name
;
}
java
.
import
=
function
(
name
)
{
const
clazz
=
java
.
findClassSync
(
name
)
;
// TODO: change to Class.forName when classloader issue is resolved.
const
result
=
function
javaClassConstructorProxy
(
)
{
const
args
=
[
name
]
;
for
(
let
i
=
0
;
i
<
arguments
.
length
;
i
++
)
{
args
.
push
(
arguments
[
i
]
)
;
}
return
newInstanceSync
.
apply
(
java
,
args
)
;
}
;
result
.
class
=
clazz
;
// copy static fields
const
fields
=
SyncCall
(
clazz
,
"getDeclaredFields"
)
(
)
;
for
(
let
i
=
0
;
i
<
fields
.
length
;
i
++
)
{
const
modifiers
=
SyncCall
(
fields
[
i
]
,
"getModifiers"
)
(
)
;
if
(
(
modifiers
&
MODIFIER_PUBLIC
)
===
MODIFIER_PUBLIC
&&
(
modifiers
&
MODIFIER_STATIC
)
===
MODIFIER_STATIC
)
{
const
fieldName
=
SyncCall
(
fields
[
i
]
,
"getName"
)
(
)
;
const
jsfieldName
=
usableName
(
fieldName
)
;
result
.
__defineGetter__
(
jsfieldName
,
function
(
name
,
fieldName
)
{
return
java
.
getStaticFieldValue
(
name
,
fieldName
)
;
}
.
bind
(
this
,
name
,
fieldName
)
)
;
result
.
__defineSetter__
(
jsfieldName
,
function
(
name
,
fieldName
,
val
)
{
java
.
setStaticFieldValue
(
name
,
fieldName
,
val
)
;
}
.
bind
(
this
,
name
,
fieldName
)
)
;
}
}
let
promiseSuffix
;
if
(
java
.
asyncOptions
)
{
promiseSuffix
=
java
.
asyncOptions
.
promiseSuffix
;
}
// copy static methods
const
methods
=
SyncCall
(
clazz
,
"getDeclaredMethods"
)
(
)
;
for
(
let
i
=
0
;
i
<
methods
.
length
;
i
++
)
{
const
modifiers
=
SyncCall
(
methods
[
i
]
,
"getModifiers"
)
(
)
;
if
(
(
modifiers
&
MODIFIER_PUBLIC
)
===
MODIFIER_PUBLIC
&&
(
modifiers
&
MODIFIER_STATIC
)
===
MODIFIER_STATIC
)
{
const
methodName
=
SyncCall
(
methods
[
i
]
,
"getName"
)
(
)
;
if
(
typeof
syncSuffix
===
"string"
)
{
const
syncName
=
usableName
(
methodName
+
syncSuffix
)
;
result
[
syncName
]
=
callStaticMethodSync
.
bind
(
java
,
name
,
methodName
)
;
}
if
(
typeof
asyncSuffix
===
"string"
)
{
const
asyncName
=
usableName
(
methodName
+
asyncSuffix
)
;
result
[
asyncName
]
=
callStaticMethod
.
bind
(
java
,
name
,
methodName
)
;
}
if
(
typeof
promiseSuffix
===
"string"
)
{
const
promiseName
=
usableName
(
methodName
+
promiseSuffix
)
;
result
[
promiseName
]
=
util
.
promisify
(
callStaticMethod
.
bind
(
java
,
name
,
methodName
)
)
;
}
}
}
// copy static classes/enums
const
classes
=
SyncCall
(
clazz
,
"getDeclaredClasses"
)
(
)
;
for
(
let
i
=
0
;
i
<
classes
.
length
;
i
++
)
{
const
modifiers
=
SyncCall
(
classes
[
i
]
,
"getModifiers"
)
(
)
;
if
(
(
modifiers
&
MODIFIER_PUBLIC
)
===
MODIFIER_PUBLIC
&&
(
modifiers
&
MODIFIER_STATIC
)
===
MODIFIER_STATIC
)
{
const
className
=
SyncCall
(
classes
[
i
]
,
"getName"
)
(
)
;
const
simpleName
=
SyncCall
(
classes
[
i
]
,
"getSimpleName"
)
(
)
;
Object
.
defineProperty
(
result
,
simpleName
,
{
get
:
function
(
result
,
simpleName
,
className
)
{
const
c
=
java
.
import
(
className
)
;
// memoize the import
const
d
=
Object
.
getOwnPropertyDescriptor
(
result
,
simpleName
)
;
d
.
get
=
function
(
c
)
{
return
c
;
}
.
bind
(
null
,
c
)
;
Object
.
defineProperty
(
result
,
simpleName
,
d
)
;
return
c
;
}
.
bind
(
this
,
result
,
simpleName
,
className
)
,
enumerable
:
true
,
configurable
:
true
,
}
)
;
}
}
return
result
;
}
;
Back
|
FazBrowse Home
|
New Git URL