js4j 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +684 -0
- package/examples/01-basic.js +75 -0
- package/examples/02-collections.js +108 -0
- package/examples/03-objects.js +99 -0
- package/examples/04-callbacks.js +97 -0
- package/examples/05-stdlib.js +123 -0
- package/examples/_gateway.js +78 -0
- package/index.d.ts +455 -0
- package/index.js +78 -0
- package/java/TestEntryPoint.java +262 -0
- package/java/py4j.jar +0 -0
- package/package.json +29 -0
- package/src/callbackServer.js +269 -0
- package/src/clientServer.js +81 -0
- package/src/collections.js +325 -0
- package/src/connection.js +253 -0
- package/src/exceptions.js +68 -0
- package/src/gateway.js +222 -0
- package/src/javaObject.js +267 -0
- package/src/jvmView.js +224 -0
- package/src/launcher.js +150 -0
- package/src/protocol.js +413 -0
- package/tests/comparison/run_comparison.js +279 -0
- package/tests/comparison/test_js4j.js +187 -0
- package/tests/comparison/test_py4j.py +171 -0
- package/tests/integration/gateway.integration.test.js +384 -0
- package/tests/unit/collections.test.js +313 -0
- package/tests/unit/exceptions.test.js +104 -0
- package/tests/unit/gateway.test.js +178 -0
- package/tests/unit/jvmView.test.js +126 -0
- package/tests/unit/launcher.test.js +27 -0
- package/tests/unit/protocol.test.js +280 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example 01 — Basic usage
|
|
6
|
+
*
|
|
7
|
+
* Shows how to connect to a Java gateway, call methods on the entry point
|
|
8
|
+
* object, and work with primitive types (numbers, strings, booleans, null).
|
|
9
|
+
*
|
|
10
|
+
* Run:
|
|
11
|
+
* node examples/01-basic.js
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { startTestGateway } = require('./_gateway');
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
console.log('Connecting to Java gateway...\n');
|
|
18
|
+
const { gateway, kill } = await startTestGateway();
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const ep = gateway.entry_point;
|
|
22
|
+
|
|
23
|
+
// -----------------------------------------------------------------------
|
|
24
|
+
// Arithmetic
|
|
25
|
+
// -----------------------------------------------------------------------
|
|
26
|
+
console.log('--- Arithmetic ---');
|
|
27
|
+
console.log('add(3, 4) =', await ep.add(3, 4)); // 7
|
|
28
|
+
console.log('multiply(6, 7) =', await ep.multiply(6, 7)); // 42
|
|
29
|
+
console.log('divide(5.5, 2.2) =', await ep.divide(5.5, 2.2)); // 2.5
|
|
30
|
+
console.log('addDoubles(1.1, 2.2) =', await ep.addDoubles(1.1, 2.2)); // 3.3
|
|
31
|
+
console.log('addLongs(2^32, 1) =', await ep.addLongs(4294967296, 1)); // 4294967297
|
|
32
|
+
|
|
33
|
+
// -----------------------------------------------------------------------
|
|
34
|
+
// Strings
|
|
35
|
+
// -----------------------------------------------------------------------
|
|
36
|
+
console.log('\n--- Strings ---');
|
|
37
|
+
console.log(await ep.greet('World')); // Hello, World!
|
|
38
|
+
console.log(await ep.concatenate('foo', 'bar')); // foobar
|
|
39
|
+
console.log('length("hello") =', await ep.stringLength('hello')); // 5
|
|
40
|
+
console.log(await ep.toUpperCase('js4j')); // JS4J
|
|
41
|
+
console.log('containsSubstring =', await ep.containsSubstring('hello world', 'world')); // true
|
|
42
|
+
console.log(await ep.repeatString('ab', 3)); // ababab
|
|
43
|
+
|
|
44
|
+
// -----------------------------------------------------------------------
|
|
45
|
+
// Booleans
|
|
46
|
+
// -----------------------------------------------------------------------
|
|
47
|
+
console.log('\n--- Booleans ---');
|
|
48
|
+
console.log('true && false =', await ep.andBool(true, false)); // false
|
|
49
|
+
console.log('true || false =', await ep.orBool(true, false)); // true
|
|
50
|
+
console.log('!true =', await ep.notBool(true)); // false
|
|
51
|
+
|
|
52
|
+
// -----------------------------------------------------------------------
|
|
53
|
+
// Null handling
|
|
54
|
+
// -----------------------------------------------------------------------
|
|
55
|
+
console.log('\n--- Null ---');
|
|
56
|
+
console.log('maybeNull(false) =', await ep.maybeNull(false)); // "not null"
|
|
57
|
+
console.log('maybeNull(true) =', await ep.maybeNull(true)); // null
|
|
58
|
+
console.log('isNull(null) =', await ep.isNull(null)); // true
|
|
59
|
+
|
|
60
|
+
// -----------------------------------------------------------------------
|
|
61
|
+
// Type round-trips
|
|
62
|
+
// -----------------------------------------------------------------------
|
|
63
|
+
console.log('\n--- Type round-trips ---');
|
|
64
|
+
console.log('echoInt(42) =', await ep.echoInt(42));
|
|
65
|
+
console.log('echoDouble(3.14) =', await ep.echoDouble(3.14));
|
|
66
|
+
console.log('echoBool(true) =', await ep.echoBool(true));
|
|
67
|
+
console.log('echoString("hi") =', await ep.echoString('hi'));
|
|
68
|
+
|
|
69
|
+
} finally {
|
|
70
|
+
await kill();
|
|
71
|
+
console.log('\nGateway shut down.');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
main().catch((err) => { console.error(err.message); process.exit(1); });
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example 02 — Java collections
|
|
6
|
+
*
|
|
7
|
+
* Demonstrates JavaList, JavaSet, JavaMap, and JavaArray — the wrappers
|
|
8
|
+
* js4j creates automatically when Java methods return collection types.
|
|
9
|
+
*
|
|
10
|
+
* Run:
|
|
11
|
+
* node examples/02-collections.js
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { startTestGateway } = require('./_gateway');
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
console.log('Connecting to Java gateway...\n');
|
|
18
|
+
const { gateway, kill } = await startTestGateway();
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const ep = gateway.entry_point;
|
|
22
|
+
|
|
23
|
+
// -----------------------------------------------------------------------
|
|
24
|
+
// JavaList
|
|
25
|
+
// -----------------------------------------------------------------------
|
|
26
|
+
console.log('--- JavaList ---');
|
|
27
|
+
const list = await ep.getStringList(); // returns ArrayList<String>
|
|
28
|
+
|
|
29
|
+
console.log('size() =', await list.size()); // 3
|
|
30
|
+
console.log('get(0) =', await list.get(0)); // alpha
|
|
31
|
+
console.log('get(2) =', await list.get(2)); // gamma
|
|
32
|
+
console.log('contains("beta")=', await list.contains('beta')); // true
|
|
33
|
+
console.log('indexOf("gamma")=', await list.indexOf('gamma')); // 2
|
|
34
|
+
|
|
35
|
+
// Mutation
|
|
36
|
+
await list.add('delta');
|
|
37
|
+
console.log('after add("delta"), size =', await list.size()); // 4
|
|
38
|
+
|
|
39
|
+
// Convert to a plain JS array
|
|
40
|
+
const arr = await list.toArray();
|
|
41
|
+
console.log('toArray() =', arr); // ['alpha','beta','gamma','delta']
|
|
42
|
+
|
|
43
|
+
// Iteration with for-await
|
|
44
|
+
process.stdout.write('for-await: ');
|
|
45
|
+
for await (const item of list) process.stdout.write(item + ' ');
|
|
46
|
+
console.log();
|
|
47
|
+
|
|
48
|
+
// -----------------------------------------------------------------------
|
|
49
|
+
// JavaSet
|
|
50
|
+
// -----------------------------------------------------------------------
|
|
51
|
+
console.log('\n--- JavaSet ---');
|
|
52
|
+
const set = await ep.getStringSet(); // returns LinkedHashSet<String>
|
|
53
|
+
|
|
54
|
+
console.log('size() =', await set.size()); // 3
|
|
55
|
+
console.log('contains("one") =', await set.contains('one')); // true
|
|
56
|
+
console.log('contains("four")=', await set.contains('four')); // false
|
|
57
|
+
|
|
58
|
+
await set.add('four');
|
|
59
|
+
console.log('after add("four"), size =', await set.size()); // 4
|
|
60
|
+
|
|
61
|
+
const nativeSet = await set.toSet(); // JS Set
|
|
62
|
+
console.log('toSet() =', nativeSet);
|
|
63
|
+
|
|
64
|
+
// -----------------------------------------------------------------------
|
|
65
|
+
// JavaMap
|
|
66
|
+
// -----------------------------------------------------------------------
|
|
67
|
+
console.log('\n--- JavaMap ---');
|
|
68
|
+
const map = await ep.getStringIntMap(); // returns LinkedHashMap<String,Integer>
|
|
69
|
+
|
|
70
|
+
console.log('size() =', await map.size()); // 3
|
|
71
|
+
console.log('get("a") =', await map.get('a')); // 1
|
|
72
|
+
console.log('get("z") =', await map.get('z')); // null
|
|
73
|
+
console.log('containsKey("b")=', await map.containsKey('b')); // true
|
|
74
|
+
|
|
75
|
+
await map.put('d', 4);
|
|
76
|
+
console.log('after put("d",4), size =', await map.size()); // 4
|
|
77
|
+
|
|
78
|
+
// Convert to a plain JS object
|
|
79
|
+
const obj = await map.toObject();
|
|
80
|
+
console.log('toObject() =', obj); // { a:1, b:2, c:3, d:4 }
|
|
81
|
+
|
|
82
|
+
// -----------------------------------------------------------------------
|
|
83
|
+
// JavaArray
|
|
84
|
+
// -----------------------------------------------------------------------
|
|
85
|
+
console.log('\n--- JavaArray ---');
|
|
86
|
+
const intArr = await ep.getIntArray(); // int[]{10,20,30,40,50}
|
|
87
|
+
|
|
88
|
+
console.log('length() =', await intArr.length()); // 5
|
|
89
|
+
console.log('get(0) =', await intArr.get(0)); // 10
|
|
90
|
+
console.log('get(4) =', await intArr.get(4)); // 50
|
|
91
|
+
|
|
92
|
+
// Convert all elements to a JS array
|
|
93
|
+
console.log('toArray() =', await intArr.toArray()); // [10,20,30,40,50]
|
|
94
|
+
|
|
95
|
+
// Create a new Java array from the JS side
|
|
96
|
+
const newArr = await gateway.newArray(gateway.jvm.java.lang.Integer, 3);
|
|
97
|
+
await newArr.set(0, 100);
|
|
98
|
+
await newArr.set(1, 200);
|
|
99
|
+
await newArr.set(2, 300);
|
|
100
|
+
console.log('newArray result =', await newArr.toArray()); // [100,200,300]
|
|
101
|
+
|
|
102
|
+
} finally {
|
|
103
|
+
await kill();
|
|
104
|
+
console.log('\nGateway shut down.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main().catch((err) => { console.error(err.message); process.exit(1); });
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example 03 — Java objects
|
|
6
|
+
*
|
|
7
|
+
* Shows how to work with Java objects returned from the gateway:
|
|
8
|
+
* - Calling methods on entry-point-created objects (Counter)
|
|
9
|
+
* - Creating Java standard-library objects from the JS side (StringBuilder)
|
|
10
|
+
* - Reading and writing fields via gateway.getField / gateway.setField
|
|
11
|
+
* - Introspection: getMethods, getFields, getStaticMembers, help
|
|
12
|
+
*
|
|
13
|
+
* Run:
|
|
14
|
+
* node examples/03-objects.js
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { startTestGateway } = require('./_gateway');
|
|
18
|
+
|
|
19
|
+
async function main() {
|
|
20
|
+
console.log('Connecting to Java gateway...\n');
|
|
21
|
+
const { gateway, kill } = await startTestGateway();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const ep = gateway.entry_point;
|
|
25
|
+
const jvm = gateway.jvm;
|
|
26
|
+
|
|
27
|
+
// -----------------------------------------------------------------------
|
|
28
|
+
// Objects returned by the entry point
|
|
29
|
+
// -----------------------------------------------------------------------
|
|
30
|
+
console.log('--- Counter object ---');
|
|
31
|
+
const counter = await ep.createCounter(10);
|
|
32
|
+
|
|
33
|
+
console.log('getValue() =', await counter.getValue()); // 10
|
|
34
|
+
await counter.increment();
|
|
35
|
+
await counter.increment();
|
|
36
|
+
console.log('after 2x increment:', await counter.getValue()); // 12
|
|
37
|
+
await counter.add(8);
|
|
38
|
+
console.log('after add(8) =', await counter.getValue()); // 20
|
|
39
|
+
await counter.decrement();
|
|
40
|
+
console.log('after decrement =', await counter.getValue()); // 19
|
|
41
|
+
await counter.reset();
|
|
42
|
+
console.log('after reset =', await counter.getValue()); // 0
|
|
43
|
+
|
|
44
|
+
console.log('toString() =', await counter.toString()); // Counter(0)
|
|
45
|
+
|
|
46
|
+
// -----------------------------------------------------------------------
|
|
47
|
+
// Creating Java objects from the JS side via gateway.jvm
|
|
48
|
+
// -----------------------------------------------------------------------
|
|
49
|
+
console.log('\n--- StringBuilder (created from JS) ---');
|
|
50
|
+
const sb = await jvm.java.lang.StringBuilder('Hello');
|
|
51
|
+
await sb.append(', ');
|
|
52
|
+
await sb.append('World');
|
|
53
|
+
await sb.append('!');
|
|
54
|
+
console.log('toString() =', await sb.toString()); // Hello, World!
|
|
55
|
+
console.log('length() =', await sb.length()); // 13
|
|
56
|
+
|
|
57
|
+
// -----------------------------------------------------------------------
|
|
58
|
+
// Static methods via the jvm namespace
|
|
59
|
+
// -----------------------------------------------------------------------
|
|
60
|
+
console.log('\n--- Static methods ---');
|
|
61
|
+
const absVal = await jvm.java.lang.Math.abs(-42);
|
|
62
|
+
console.log('Math.abs(-42) =', absVal); // 42
|
|
63
|
+
|
|
64
|
+
const maxVal = await jvm.java.lang.Math.max(17, 99);
|
|
65
|
+
console.log('Math.max(17,99) =', maxVal); // 99
|
|
66
|
+
|
|
67
|
+
const sqrtVal = await jvm.java.lang.Math.sqrt(12.25);
|
|
68
|
+
console.log('Math.sqrt(12.25) =', sqrtVal); // 3.5
|
|
69
|
+
|
|
70
|
+
const parsed = await jvm.java.lang.Integer.parseInt('255');
|
|
71
|
+
console.log('Integer.parseInt("255") =', parsed); // 255
|
|
72
|
+
|
|
73
|
+
// -----------------------------------------------------------------------
|
|
74
|
+
// Static fields via gateway.getField
|
|
75
|
+
// -----------------------------------------------------------------------
|
|
76
|
+
console.log('\n--- Static fields ---');
|
|
77
|
+
const pi = await gateway.getField(jvm.java.lang.Math, 'PI');
|
|
78
|
+
const maxInt = await gateway.getField(jvm.java.lang.Integer, 'MAX_VALUE');
|
|
79
|
+
console.log('Math.PI =', pi); // 3.141592...
|
|
80
|
+
console.log('Integer.MAX_VALUE =', maxInt); // 2147483647
|
|
81
|
+
|
|
82
|
+
// -----------------------------------------------------------------------
|
|
83
|
+
// Introspection
|
|
84
|
+
// -----------------------------------------------------------------------
|
|
85
|
+
console.log('\n--- Introspection ---');
|
|
86
|
+
const methods = await gateway.getMethods(counter);
|
|
87
|
+
console.log('Counter methods:', methods.sort().join(', '));
|
|
88
|
+
|
|
89
|
+
const staticMembers = await gateway.getStaticMembers(jvm.java.lang.Math);
|
|
90
|
+
const mathStatics = staticMembers.filter(m => ['abs', 'max', 'min', 'sqrt', 'PI', 'E'].includes(m));
|
|
91
|
+
console.log('Math static members (subset):', mathStatics.sort().join(', '));
|
|
92
|
+
|
|
93
|
+
} finally {
|
|
94
|
+
await kill();
|
|
95
|
+
console.log('\nGateway shut down.');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
main().catch((err) => { console.error(err.message); process.exit(1); });
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example 04 — Callbacks (Java → JS)
|
|
6
|
+
*
|
|
7
|
+
* Demonstrates passing JavaScript objects to Java as interface implementations.
|
|
8
|
+
* Java calls back into Node.js over a separate TCP connection handled by the
|
|
9
|
+
* CallbackServer.
|
|
10
|
+
*
|
|
11
|
+
* Run:
|
|
12
|
+
* node examples/04-callbacks.js
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { startTestGateway } = require('./_gateway');
|
|
16
|
+
const { createJavaProxy } = require('../src/callbackServer');
|
|
17
|
+
const { ClientServer } = require('../src/clientServer');
|
|
18
|
+
const { GatewayParameters, CallbackServerParameters } = require('../src/gateway');
|
|
19
|
+
|
|
20
|
+
async function main() {
|
|
21
|
+
console.log('Connecting to Java gateway (with callback server)...\n');
|
|
22
|
+
const { process: jvmProcess, kill: killProcess } = await startTestGateway();
|
|
23
|
+
|
|
24
|
+
const cs = new ClientServer(
|
|
25
|
+
new GatewayParameters({ port: 25333 }),
|
|
26
|
+
new CallbackServerParameters({ port: 25334 })
|
|
27
|
+
);
|
|
28
|
+
await cs.connect();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const jvm = cs.jvm;
|
|
32
|
+
|
|
33
|
+
// -----------------------------------------------------------------------
|
|
34
|
+
// Runnable — Java calls run() on the JS object
|
|
35
|
+
// -----------------------------------------------------------------------
|
|
36
|
+
console.log('--- Runnable callback ---');
|
|
37
|
+
|
|
38
|
+
let runCount = 0;
|
|
39
|
+
const runnable = createJavaProxy(['java.lang.Runnable'], {
|
|
40
|
+
run() {
|
|
41
|
+
runCount++;
|
|
42
|
+
console.log(` run() called! (invocation #${runCount})`);
|
|
43
|
+
return null;
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const thread = await jvm.java.lang.Thread(runnable);
|
|
48
|
+
await thread.start();
|
|
49
|
+
await thread.join();
|
|
50
|
+
|
|
51
|
+
console.log(`Runnable was invoked ${runCount} time(s)`);
|
|
52
|
+
|
|
53
|
+
// -----------------------------------------------------------------------
|
|
54
|
+
// Comparator — Java calls compare(a, b) to sort a list
|
|
55
|
+
// -----------------------------------------------------------------------
|
|
56
|
+
console.log('\n--- Comparator callback (sort by string length) ---');
|
|
57
|
+
|
|
58
|
+
const byLength = createJavaProxy(['java.util.Comparator'], {
|
|
59
|
+
compare(a, b) {
|
|
60
|
+
return String(a).length - String(b).length;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const words = await jvm.java.util.ArrayList();
|
|
65
|
+
await words.add('banana'); await words.add('fig'); await words.add('apple');
|
|
66
|
+
await words.add('kiwi'); await words.add('date');
|
|
67
|
+
await jvm.java.util.Collections.sort(words, byLength);
|
|
68
|
+
|
|
69
|
+
const sorted = await words.toArray();
|
|
70
|
+
console.log('Sorted by length:', sorted);
|
|
71
|
+
|
|
72
|
+
// -----------------------------------------------------------------------
|
|
73
|
+
// Callable — returns a value back to Java
|
|
74
|
+
// -----------------------------------------------------------------------
|
|
75
|
+
console.log('\n--- Callable callback (returns a value) ---');
|
|
76
|
+
|
|
77
|
+
const callable = createJavaProxy(['java.util.concurrent.Callable'], {
|
|
78
|
+
call() {
|
|
79
|
+
const value = 'computed by JavaScript at ' + new Date().toISOString();
|
|
80
|
+
console.log(' call() invoked, returning:', value);
|
|
81
|
+
return value;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const future = await jvm.java.util.concurrent.FutureTask(callable);
|
|
86
|
+
await future.run();
|
|
87
|
+
const result = await future.get();
|
|
88
|
+
console.log('FutureTask result:', result);
|
|
89
|
+
|
|
90
|
+
} finally {
|
|
91
|
+
await cs.shutdown();
|
|
92
|
+
killProcess();
|
|
93
|
+
console.log('\nGateway shut down.');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
main().catch((err) => { console.error(err.message); process.exit(1); });
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example 05 — Java standard library
|
|
6
|
+
*
|
|
7
|
+
* Demonstrates direct access to Java standard-library classes via the
|
|
8
|
+
* gateway.jvm namespace — no custom Java code required.
|
|
9
|
+
*
|
|
10
|
+
* Topics covered:
|
|
11
|
+
* - java.lang (String, Math, System, Integer, StringBuilder)
|
|
12
|
+
* - java.util (ArrayList, HashMap, TreeMap, Collections, UUID, Date)
|
|
13
|
+
* - java.time (LocalDate, LocalDateTime, Duration) [Java 8+]
|
|
14
|
+
* - javaImport shortcut
|
|
15
|
+
*
|
|
16
|
+
* Run:
|
|
17
|
+
* node examples/05-stdlib.js
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { startTestGateway } = require('./_gateway');
|
|
21
|
+
|
|
22
|
+
async function main() {
|
|
23
|
+
console.log('Connecting to Java gateway...\n');
|
|
24
|
+
const { gateway, kill } = await startTestGateway();
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const jvm = gateway.jvm;
|
|
28
|
+
|
|
29
|
+
// -----------------------------------------------------------------------
|
|
30
|
+
// java.lang
|
|
31
|
+
// -----------------------------------------------------------------------
|
|
32
|
+
console.log('--- java.lang ---');
|
|
33
|
+
|
|
34
|
+
const sb = await jvm.java.lang.StringBuilder();
|
|
35
|
+
await sb.append('js4j');
|
|
36
|
+
await sb.append(' + ');
|
|
37
|
+
await sb.append('Java');
|
|
38
|
+
console.log('StringBuilder:', await sb.toString());
|
|
39
|
+
|
|
40
|
+
const strVal = await jvm.java.lang.String.valueOf(42);
|
|
41
|
+
console.log('String.valueOf(42): ', strVal);
|
|
42
|
+
|
|
43
|
+
console.log('Math.PI: ', await gateway.getField(jvm.java.lang.Math, 'PI'));
|
|
44
|
+
console.log('Math.exp(1.5):', await jvm.java.lang.Math.exp(1.5));
|
|
45
|
+
console.log('Math.floor(3.9):', await jvm.java.lang.Math.floor(3.9));
|
|
46
|
+
console.log('Math.log(Math.E):', await jvm.java.lang.Math.log(
|
|
47
|
+
await gateway.getField(jvm.java.lang.Math, 'E')
|
|
48
|
+
));
|
|
49
|
+
|
|
50
|
+
const ms = await jvm.java.lang.System.currentTimeMillis();
|
|
51
|
+
console.log('System.currentTimeMillis:', ms);
|
|
52
|
+
|
|
53
|
+
console.log('Integer.MAX_VALUE:', await gateway.getField(jvm.java.lang.Integer, 'MAX_VALUE'));
|
|
54
|
+
console.log('Integer.toBinaryString(255):', await jvm.java.lang.Integer.toBinaryString(255));
|
|
55
|
+
console.log('Integer.toHexString(255):', await jvm.java.lang.Integer.toHexString(255));
|
|
56
|
+
|
|
57
|
+
// -----------------------------------------------------------------------
|
|
58
|
+
// java.util
|
|
59
|
+
// -----------------------------------------------------------------------
|
|
60
|
+
console.log('\n--- java.util ---');
|
|
61
|
+
|
|
62
|
+
const list = await jvm.java.util.ArrayList();
|
|
63
|
+
await list.add('cherry');
|
|
64
|
+
await list.add('apple');
|
|
65
|
+
await list.add('banana');
|
|
66
|
+
await jvm.java.util.Collections.sort(list);
|
|
67
|
+
console.log('Sorted ArrayList:', await list.toArray());
|
|
68
|
+
|
|
69
|
+
const map = await jvm.java.util.HashMap();
|
|
70
|
+
await map.put('x', 10);
|
|
71
|
+
await map.put('y', 20);
|
|
72
|
+
await map.put('z', 30);
|
|
73
|
+
console.log('HashMap size: ', await map.size());
|
|
74
|
+
console.log('HashMap get x: ', await map.get('x'));
|
|
75
|
+
|
|
76
|
+
const tree = await jvm.java.util.TreeMap(map);
|
|
77
|
+
const keys = await tree.keySet();
|
|
78
|
+
console.log('TreeMap keys: ', await keys.toArray());
|
|
79
|
+
|
|
80
|
+
const uuid = await jvm.java.util.UUID.randomUUID();
|
|
81
|
+
const uuidStr = await uuid.toString();
|
|
82
|
+
console.log('UUID: ', uuidStr);
|
|
83
|
+
console.log('UUID version: ', await uuid.version());
|
|
84
|
+
|
|
85
|
+
const nums = await jvm.java.util.ArrayList();
|
|
86
|
+
await nums.add(5); await nums.add(3); await nums.add(9); await nums.add(1); await nums.add(7);
|
|
87
|
+
console.log('max of [5,3,9,1,7]:', await jvm.java.util.Collections.max(nums));
|
|
88
|
+
console.log('min of [5,3,9,1,7]:', await jvm.java.util.Collections.min(nums));
|
|
89
|
+
|
|
90
|
+
// -----------------------------------------------------------------------
|
|
91
|
+
// java.time (Java 8+)
|
|
92
|
+
// -----------------------------------------------------------------------
|
|
93
|
+
console.log('\n--- java.time ---');
|
|
94
|
+
|
|
95
|
+
const today = await jvm.java.time.LocalDate.now();
|
|
96
|
+
console.log('LocalDate.now():', await today.toString());
|
|
97
|
+
|
|
98
|
+
const fixed = await jvm.java.time.LocalDate.of(2000, 1, 1);
|
|
99
|
+
console.log('Year 2000: ', await fixed.toString());
|
|
100
|
+
|
|
101
|
+
const duration = await jvm.java.time.Duration.ofHours(3);
|
|
102
|
+
console.log('Duration (3h): ', await duration.toString());
|
|
103
|
+
console.log('In minutes: ', await duration.toMinutes());
|
|
104
|
+
|
|
105
|
+
// -----------------------------------------------------------------------
|
|
106
|
+
// javaImport — shortcut access
|
|
107
|
+
// -----------------------------------------------------------------------
|
|
108
|
+
console.log('\n--- javaImport shortcut ---');
|
|
109
|
+
|
|
110
|
+
await gateway.javaImport('java.util.LinkedList');
|
|
111
|
+
const linked = await jvm.LinkedList();
|
|
112
|
+
await linked.add('first');
|
|
113
|
+
await linked.add('second');
|
|
114
|
+
await linked.addFirst('zeroth');
|
|
115
|
+
console.log('LinkedList:', await linked.toArray());
|
|
116
|
+
|
|
117
|
+
} finally {
|
|
118
|
+
await kill();
|
|
119
|
+
console.log('\nGateway shut down.');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
main().catch((err) => { console.error(err.message); process.exit(1); });
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared helper used by all examples.
|
|
5
|
+
*
|
|
6
|
+
* Locates the py4j JAR, compiles TestEntryPoint.java if needed,
|
|
7
|
+
* then launches the gateway and returns { gateway, kill }.
|
|
8
|
+
*
|
|
9
|
+
* Set PY4J_JAR=/path/to/py4j.jar if auto-detection fails.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { execSync } = require('child_process');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { launchGateway } = require('../src/launcher');
|
|
16
|
+
|
|
17
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
18
|
+
const JAVA_DIR = path.join(ROOT, 'java');
|
|
19
|
+
const BUILD_DIR = path.join(JAVA_DIR, 'build');
|
|
20
|
+
|
|
21
|
+
function findPy4jJar() {
|
|
22
|
+
if (process.env.PY4J_JAR) return process.env.PY4J_JAR;
|
|
23
|
+
|
|
24
|
+
// Common system install locations
|
|
25
|
+
const fixed = [
|
|
26
|
+
'/usr/share/py4j/py4j.jar',
|
|
27
|
+
'/usr/local/share/py4j/py4j.jar',
|
|
28
|
+
];
|
|
29
|
+
for (const p of fixed) {
|
|
30
|
+
if (fs.existsSync(p)) return p;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// pip install py4j puts the JAR next to the Python package
|
|
34
|
+
try {
|
|
35
|
+
const site = execSync(
|
|
36
|
+
'python3 -c "import py4j, os; print(os.path.dirname(py4j.__file__))"',
|
|
37
|
+
{ encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
38
|
+
).trim();
|
|
39
|
+
const libDir = path.join(site, 'java', 'lib');
|
|
40
|
+
if (fs.existsSync(libDir)) {
|
|
41
|
+
const jar = fs.readdirSync(libDir).find(f => f.endsWith('.jar'));
|
|
42
|
+
if (jar) return path.join(libDir, jar);
|
|
43
|
+
}
|
|
44
|
+
} catch (_) {}
|
|
45
|
+
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function buildIfNeeded(jar) {
|
|
50
|
+
const cls = path.join(BUILD_DIR, 'TestEntryPoint.class');
|
|
51
|
+
if (fs.existsSync(cls)) return; // already built
|
|
52
|
+
|
|
53
|
+
console.log('Compiling TestEntryPoint.java...');
|
|
54
|
+
fs.mkdirSync(BUILD_DIR, { recursive: true });
|
|
55
|
+
execSync(
|
|
56
|
+
`javac -cp "${jar}" -d "${BUILD_DIR}" "${path.join(JAVA_DIR, 'TestEntryPoint.java')}"`,
|
|
57
|
+
{ stdio: 'inherit' }
|
|
58
|
+
);
|
|
59
|
+
console.log('Compiled.\n');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function startTestGateway() {
|
|
63
|
+
const jar = findPy4jJar();
|
|
64
|
+
if (!jar) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
'py4j JAR not found. Install py4j (pip install py4j) or set PY4J_JAR=/path/to/py4j.jar'
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
buildIfNeeded(jar);
|
|
71
|
+
|
|
72
|
+
return launchGateway({
|
|
73
|
+
classpath: `${BUILD_DIR}${path.delimiter}${jar}`,
|
|
74
|
+
mainClass: 'TestEntryPoint',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = { startTestGateway };
|