Skip to content

Commit ce52547

Browse files
committed
cleanup
1 parent 749ddb9 commit ce52547

9 files changed

+120
-139
lines changed

how-to-implement-a-js-web-api.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# How to implement a JavaScript Web-API
22

3-
1. Simply copy the `JS_API_Console` class from the `com.osiris.headlessbrowser.javascript` package
4-
and paste it with another name into the same package.
5-
2. Register your new class in the `JSContext` class, so it gets loaded into it.
6-
3. The `JS_API_Console` is the Java-Implementation of the JavaScript console api and
3+
1. Simply copy the [JS_API_Console](https://github.com/Osiris-Team/Headless-Browser/blob/main/src/main/java/com/osiris/headlessbrowser/JS_API_Console.java)
4+
class and paste it with another name into the same package.
5+
2. Register your new class in the [JSContext](https://github.com/Osiris-Team/Headless-Browser/blob/main/src/main/java/com/osiris/headlessbrowser/JSContext.java)
6+
class, so it gets loaded into it.
7+
3. The [JS_API_Console](https://github.com/Osiris-Team/Headless-Browser/blob/main/src/main/java/com/osiris/headlessbrowser/JS_API_Console.java) is the Java-Implementation of the JavaScript console api and
78
thus provides all the information you need to start implementing a new web-api.

pom.xml

-11
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,6 @@
2323
<artifactId>citeproc-java</artifactId>
2424
<version>2.0.0</version>
2525
</dependency>
26-
<dependency>
27-
<groupId>com.eclipsesource.j2v8</groupId>
28-
<artifactId>j2v8</artifactId>
29-
<version>6.2.1</version>
30-
<type>aar.asc</type>
31-
</dependency>
32-
<dependency>
33-
<groupId>com.eclipsesource.j2v8</groupId>
34-
<artifactId>j2v8_win32_x86_64</artifactId>
35-
<version>4.6.0</version>
36-
</dependency>
3726
<dependency>
3827
<groupId>org.jsoup</groupId>
3928
<artifactId>jsoup</artifactId>

src/main/java/com/osiris/headlessbrowser/HeadlessBrowser.java

-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
package com.osiris.headlessbrowser;
22

3-
import com.eclipsesource.v8.NodeJS;
4-
5-
import java.util.ArrayList;
6-
import java.util.List;
7-
83
public class HeadlessBrowser {
94

105
public HeadlessBrowser() {

src/main/java/com/osiris/headlessbrowser/HeadlessWindow.java

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
package com.osiris.headlessbrowser;
22

3-
import com.eclipsesource.v8.NodeJS;
43

5-
public class HeadlessWindow implements AutoCloseable{
6-
public static NodeJS NODE_JS = NodeJS.createNodeJS();
4+
public class HeadlessWindow implements AutoCloseable {
75
private final JSContext jsContext = new JSContext(this);
86

97

10-
public static NodeJS getNodeJs() {
11-
return NODE_JS;
12-
}
13-
148
public JSContext getJsContext() {
159
return jsContext;
1610
}

src/main/java/com/osiris/headlessbrowser/JSContext.java

+106-103
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,24 @@
88
import de.undercouch.citeproc.helper.json.JsonBuilder;
99
import de.undercouch.citeproc.helper.json.JsonObject;
1010
import de.undercouch.citeproc.helper.json.StringJsonBuilder;
11-
import de.undercouch.citeproc.script.*;
11+
import de.undercouch.citeproc.script.AbstractScriptRunner;
12+
import de.undercouch.citeproc.script.GraalScriptRunner;
13+
import de.undercouch.citeproc.script.ScriptRunnerException;
1214
import org.graalvm.polyglot.Context;
1315
import org.graalvm.polyglot.PolyglotException;
1416
import org.graalvm.polyglot.Source;
1517
import org.graalvm.polyglot.Value;
1618

17-
import java.io.*;
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.io.InputStreamReader;
22+
import java.io.Reader;
1823
import java.util.*;
1924

2025
public class JSContext extends AbstractScriptRunner {
21-
private HeadlessWindow window;
22-
private Context rawContext = Context.newBuilder("js").allowAllAccess(true).build();
23-
private Map<JavaScriptAPI, Boolean> loadedJSWebAPIs = new HashMap<>();
26+
private final HeadlessWindow window;
27+
private final Context rawContext = Context.newBuilder("js").allowAllAccess(true).build();
28+
private final Map<JavaScriptAPI, Boolean> loadedJSWebAPIs = new HashMap<>();
2429

2530
public JSContext(HeadlessWindow window) {
2631
this.window = window;
@@ -32,7 +37,7 @@ public JSContext(HeadlessWindow window) {
3237

3338
// Register all JavaScript Web-APIs:
3439
loadedJSWebAPIs.forEach((api, override) -> {
35-
try{
40+
try {
3641
registerAndLoad(api.getJSVarName(), api.getObject(), override);
3742
} catch (Exception exception) {
3843
System.err.println("Failed to load one/multiple JavaScript Web-API(s) into the current JavaScript-Context! Details:");
@@ -42,20 +47,102 @@ public JSContext(HeadlessWindow window) {
4247

4348
}
4449

50+
/**
51+
* Recursively convert a JavaScript value to a Java object
52+
*
53+
* @param v the value to convert
54+
* @return the object
55+
*/
56+
private static Object convert(Value v) {
57+
Object o = v;
58+
if (v.isNull()) {
59+
o = null;
60+
} else if (v.isBoolean()) {
61+
o = v.asBoolean();
62+
} else if (v.isDate()) {
63+
o = v.asDate();
64+
} else if (v.isDuration()) {
65+
o = v.asDuration();
66+
} else if (v.isHostObject()) {
67+
o = v.asHostObject();
68+
} else if (v.isInstant()) {
69+
o = v.asInstant();
70+
} else if (v.isNativePointer()) {
71+
o = v.asNativePointer();
72+
} else if (v.isNumber()) {
73+
if (v.fitsInInt()) {
74+
o = v.asInt();
75+
} else if (v.fitsInLong()) {
76+
o = v.asLong();
77+
} else if (v.fitsInDouble()) {
78+
o = v.asDouble();
79+
} else {
80+
throw new IllegalStateException("Unknown type of number");
81+
}
82+
} else if (v.isProxyObject()) {
83+
o = v.asProxyObject();
84+
} else if (v.isString()) {
85+
o = v.asString();
86+
} else if (v.isTime()) {
87+
o = v.asTime();
88+
} else if (v.isTimeZone()) {
89+
o = v.asTimeZone();
90+
} else if (v.hasArrayElements()) {
91+
o = convertArray(v);
92+
} else if (v.hasMembers()) {
93+
o = convertObject(v);
94+
}
95+
return o;
96+
}
97+
98+
/**
99+
* Recursively convert a JavaScript array to a list
100+
*
101+
* @param arr the array to convert
102+
* @return the list
103+
*/
104+
private static List<Object> convertArray(Value arr) {
105+
List<Object> l = new ArrayList<>();
106+
for (int i = 0; i < arr.getArraySize(); ++i) {
107+
Value v = arr.getArrayElement(i);
108+
Object o = convert(v);
109+
l.add(o);
110+
}
111+
return l;
112+
}
113+
114+
/**
115+
* Recursively convert a JavaScript object to a map
116+
*
117+
* @param obj the object to convert
118+
* @return the map
119+
*/
120+
private static Map<String, Object> convertObject(Value obj) {
121+
Map<String, Object> r = new LinkedHashMap<>();
122+
for (String k : obj.getMemberKeys()) {
123+
Value v = obj.getMember(k);
124+
Object o = convert(v);
125+
r.put(k, o);
126+
}
127+
return r;
128+
}
129+
45130
/**
46131
* Registers and loads this API into the provided {@link JSContext}. <br>
132+
*
47133
* @param id
48134
*/
49135
public void registerAndLoad(String id, Object object, boolean override) throws DuplicateRegisteredId, IOException {
50-
if(!override && rawContext.getBindings("js").getMember(id) != null)
51-
throw new DuplicateRegisteredId("Failed to register because of already existing/registered id '"+id+"'.");
136+
if (!override && rawContext.getBindings("js").getMember(id) != null)
137+
throw new DuplicateRegisteredId("Failed to register because of already existing/registered id '" + id + "'.");
52138
rawContext.getBindings("js").putMember(id, object);
53139
}
54140

55141
/**
56142
* Executes the given jsCode in the current context. <br>
57143
* This means that all the jsCode that has been ran before in this {@link JSContext} is accessible
58144
* for the given jsCode.
145+
*
59146
* @param jsCode JavaScript code to run in the current {@link JSContext}.
60147
* @throws ScriptRunnerException
61148
* @throws IOException
@@ -76,14 +163,12 @@ public Context getRawContext() {
76163
return rawContext;
77164
}
78165

79-
80166
/**
81167
* ALL METHODS BELOW ARE TAKEN FROM {@link GraalScriptRunner}. <br>
82168
* Some methods were added to provide extra functionality.
83169
*/
84170

85171

86-
87172
@Override
88173
public String getName() {
89174
return rawContext.getEngine().getImplementationName();
@@ -96,14 +181,6 @@ public String getVersion() {
96181

97182
@Override
98183
public void eval(Reader reader) throws IOException {
99-
String jsCode = null;
100-
try (BufferedReader bufferedReader = new BufferedReader(reader)) {
101-
while ((jsCode = bufferedReader.readLine()) != null) {
102-
jsCode = jsCode+jsCode;
103-
}
104-
} catch (IOException e) {
105-
throw e;
106-
}
107184
rawContext.eval(Source.newBuilder("js", reader, null).cached(false).build());
108185
}
109186

@@ -131,7 +208,7 @@ public void callMethod(String name, Object... args) throws ScriptRunnerException
131208
public <T> T callMethod(Object obj, String name, Class<T> resultType, Object... args)
132209
throws ScriptRunnerException {
133210
try {
134-
return convert(((Value)obj).getMember(name)
211+
return convert(((Value) obj).getMember(name)
135212
.execute(convertArguments(args)), resultType);
136213
} catch (IOException | PolyglotException e) {
137214
throw new ScriptRunnerException("Could not call method", e);
@@ -142,100 +219,24 @@ public <T> T callMethod(Object obj, String name, Class<T> resultType, Object...
142219
public void callMethod(Object obj, String name, Object... args)
143220
throws ScriptRunnerException {
144221
try {
145-
((Value)obj).getMember(name).executeVoid(convertArguments(args));
222+
((Value) obj).getMember(name).executeVoid(convertArguments(args));
146223
} catch (IOException | PolyglotException e) {
147224
throw new ScriptRunnerException("Could not call method", e);
148225
}
149226
}
150227

151-
/**
152-
* Recursively convert a JavaScript value to a Java object
153-
* @param v the value to convert
154-
* @return the object
155-
*/
156-
private static Object convert(Value v) {
157-
Object o = v;
158-
if (v.isNull()) {
159-
o = null;
160-
} else if (v.isBoolean()) {
161-
o = v.asBoolean();
162-
} else if (v.isDate()) {
163-
o = v.asDate();
164-
} else if (v.isDuration()) {
165-
o = v.asDuration();
166-
} else if (v.isHostObject()) {
167-
o = v.asHostObject();
168-
} else if (v.isInstant()) {
169-
o = v.asInstant();
170-
} else if (v.isNativePointer()) {
171-
o = v.asNativePointer();
172-
} else if (v.isNumber()) {
173-
if (v.fitsInInt()) {
174-
o = v.asInt();
175-
} else if (v.fitsInLong()) {
176-
o = v.asLong();
177-
} else if (v.fitsInDouble()) {
178-
o = v.asDouble();
179-
} else {
180-
throw new IllegalStateException("Unknown type of number");
181-
}
182-
} else if (v.isProxyObject()) {
183-
o = v.asProxyObject();
184-
} else if (v.isString()) {
185-
o = v.asString();
186-
} else if (v.isTime()) {
187-
o = v.asTime();
188-
} else if (v.isTimeZone()) {
189-
o = v.asTimeZone();
190-
} else if (v.hasArrayElements()) {
191-
o = convertArray(v);
192-
} else if (v.hasMembers()) {
193-
o = convertObject(v);
194-
}
195-
return o;
196-
}
197-
198228
@Override
199229
@SuppressWarnings("unchecked")
200230
public <T> T convert(Object o, Class<T> type) {
201231
if (type != Object.class && o instanceof Value) {
202-
o = convert((Value)o);
232+
o = convert((Value) o);
203233
}
204-
return (T)o;
205-
}
206-
207-
/**
208-
* Recursively convert a JavaScript array to a list
209-
* @param arr the array to convert
210-
* @return the list
211-
*/
212-
private static List<Object> convertArray(Value arr) {
213-
List<Object> l = new ArrayList<>();
214-
for (int i = 0; i < arr.getArraySize(); ++i) {
215-
Value v = arr.getArrayElement(i);
216-
Object o = convert(v);
217-
l.add(o);
218-
}
219-
return l;
220-
}
221-
222-
/**
223-
* Recursively convert a JavaScript object to a map
224-
* @param obj the object to convert
225-
* @return the map
226-
*/
227-
private static Map<String, Object> convertObject(Value obj) {
228-
Map<String, Object> r = new LinkedHashMap<>();
229-
for (String k : obj.getMemberKeys()) {
230-
Value v = obj.getMember(k);
231-
Object o = convert(v);
232-
r.put(k, o);
233-
}
234-
return r;
234+
return (T) o;
235235
}
236236

237237
/**
238238
* Convert arguments that should be passed to a JavaScript function
239+
*
239240
* @param args the arguments
240241
* @return the converted arguments or `args` if conversion was not necessary
241242
* @throws IOException if an argument could not be converted
@@ -253,7 +254,7 @@ private Object[] convertArguments(Object[] args) throws IOException {
253254
.build();
254255
o = rawContext.eval(src);
255256
} else if (v instanceof VariableWrapper) {
256-
o = new VariableWrapperWrapper((VariableWrapper)o);
257+
o = new VariableWrapperWrapper((VariableWrapper) o);
257258
}
258259
if (o != v) {
259260
if (copy == args) {
@@ -284,6 +285,7 @@ public void close() {
284285
* Wraps around {@link VariableWrapper} and converts
285286
* {@link VariableWrapperParams} objects to JSON objects. This class is
286287
* public because Graal JavaScript needs to be able to access it.
288+
*
287289
* @author Michel Kraemer
288290
*/
289291
public static class VariableWrapperWrapper {
@@ -295,9 +297,10 @@ private VariableWrapperWrapper(VariableWrapper wrapper) {
295297

296298
/**
297299
* Call the {@link VariableWrapper} with the given parameters
298-
* @param params the context in which an item should be rendered
299-
* @param prePunct the text that precedes the item to render
300-
* @param str the item to render
300+
*
301+
* @param params the context in which an item should be rendered
302+
* @param prePunct the text that precedes the item to render
303+
* @param str the item to render
301304
* @param postPunct the text that follows the item to render
302305
* @return the string to be rendered
303306
*/

0 commit comments

Comments
 (0)