Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/apple/applescript/AppleScriptEngine.java
38829 views
1
/*
2
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package apple.applescript;
27
28
import java.io.*;
29
import java.nio.file.Files;
30
import java.util.*;
31
import java.util.Map.Entry;
32
33
import javax.script.*;
34
35
/**
36
* AppleScriptEngine implements JSR 223 for AppleScript on Mac OS X
37
*/
38
public class AppleScriptEngine implements ScriptEngine {
39
private static native void initNative();
40
41
private static native long createContextFrom(final Object object);
42
private static native Object createObjectFrom(final long context);
43
private static native void disposeContext(final long context);
44
45
private static native long evalScript(final String script, long contextptr);
46
private static native long evalScriptFromURL(final String filename, long contextptr);
47
48
static {
49
System.loadLibrary("AppleScriptEngine");
50
initNative();
51
TRACE("<static-init>");
52
}
53
54
static void checkSecurity() {
55
final SecurityManager securityManager = System.getSecurityManager();
56
if (securityManager != null) securityManager.checkExec("/usr/bin/osascript");
57
}
58
59
static void TRACE(final String str) {
60
// System.out.println(AppleScriptEngine.class.getName() + "." + str);
61
}
62
63
/**
64
* Accessor for the ScriptEngine's long name variable
65
* @return the long name of the ScriptEngine
66
*/
67
protected static String getEngine() {
68
TRACE("getEngine()");
69
return AppleScriptEngineFactory.ENGINE_NAME;
70
}
71
72
/**
73
* Accessor for the ScriptEngine's version
74
* @return the version of the ScriptEngine
75
*/
76
protected static String getEngineVersion() {
77
TRACE("getEngineVersion()");
78
return AppleScriptEngineFactory.ENGINE_VERSION;
79
}
80
81
/**
82
* Accessor for the ScriptEngine's short name
83
* @return the short name of the ScriptEngine
84
*/
85
protected static String getName() {
86
TRACE("getName()");
87
return AppleScriptEngineFactory.ENGINE_SHORT_NAME;
88
}
89
90
/**
91
* Accessor for the ScriptEngine's supported language name
92
* @return the language the ScriptEngine supports
93
*/
94
protected static String getLanguage() {
95
TRACE("getLanguage()");
96
return AppleScriptEngineFactory.LANGUAGE;
97
}
98
99
/**
100
* The no argument constructor sets up the object with default members,
101
* a factory for the engine and a fresh context.
102
* @see com.apple.applescript.AppleScriptEngine#init()
103
*/
104
public AppleScriptEngine() {
105
TRACE("<ctor>()");
106
// set our parent factory to be a new factory
107
factory = AppleScriptEngineFactory.getFactory();
108
109
// set up our noarg bindings
110
setContext(new SimpleScriptContext());
111
put(ARGV, "");
112
113
init();
114
}
115
116
/**
117
* All AppleScriptEngines share the same ScriptEngineFactory
118
*/
119
private final ScriptEngineFactory factory;
120
121
/**
122
* The local context for the AppleScriptEngine
123
*/
124
private ScriptContext context;
125
126
/**
127
* The constructor taking a factory as an argument sets the parent factory for
128
* this engine to be the passed factory, and sets up the engine with a fresh context
129
* @param factory
130
* @see com.apple.applescript.AppleScriptEngine#init()
131
*/
132
public AppleScriptEngine(final ScriptEngineFactory factory) {
133
// inherit the factory passed to us
134
this.factory = factory;
135
136
// set up our noarg bindings
137
setContext(new SimpleScriptContext());
138
put(ARGV, "");
139
140
init();
141
}
142
143
/**
144
* The initializer populates the local context with some useful predefined variables:
145
* <ul><li><code>javax_script_language_version</code> - the version of AppleScript that the AppleScriptEngine supports.</li>
146
* <li><code>javax_script_language</code> - "AppleScript" -- the language supported by the AppleScriptEngine.</li>
147
* <li><code>javax_script_engine</code> - "AppleScriptEngine" -- the name of the ScriptEngine.</li>
148
* <li><code>javax_script_engine_version</code> - the version of the AppleScriptEngine</li>
149
* <li><code>javax_script_argv</code> - "" -- AppleScript does not take arguments from the command line</li>
150
* <li><code>javax_script_filename</code> - "" -- the currently executing filename</li>
151
* <li><code>javax_script_name</code> - "AppleScriptEngine" -- the short name of the AppleScriptEngine</li>
152
* <li><code>THREADING</code> - null -- the AppleScriptEngine does not support concurrency, you will have to implement thread-safeness yourself.</li></ul>
153
*/
154
private void init() {
155
TRACE("init()");
156
// set up our context
157
/* TODO -- name of current executable? bad java documentation at:
158
* https://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#FILENAME */
159
put(ScriptEngine.FILENAME, "");
160
put(ScriptEngine.ENGINE, getEngine());
161
put(ScriptEngine.ENGINE_VERSION, getEngineVersion());
162
put(ScriptEngine.NAME, getName());
163
put(ScriptEngine.LANGUAGE, getLanguage());
164
put(ScriptEngine.LANGUAGE_VERSION, getLanguageVersion());
165
166
// TODO -- for now, err on the side of caution and say that we are NOT thread-safe
167
put("THREADING", null);
168
}
169
170
/**
171
* Uses the AppleScriptEngine to get the local AppleScript version
172
* @return the version of AppleScript running on the system
173
*/
174
protected String getLanguageVersion() {
175
TRACE("AppleScriptEngine.getLanguageVersion()");
176
try {
177
final Object result = eval("get the version of AppleScript");
178
if (result instanceof String) return (String)result;
179
} catch (final ScriptException e) { e.printStackTrace(); }
180
return "unknown";
181
}
182
183
/**
184
* Implementation required by ScriptEngine parent<br />
185
* Returns the factory parent of this AppleScriptEngine
186
*/
187
public ScriptEngineFactory getFactory() {
188
return factory;
189
}
190
191
/**
192
* Implementation required by ScriptEngine parent<br />
193
* Return the engine's context
194
* @return this ScriptEngine's context
195
*/
196
public ScriptContext getContext() {
197
return context;
198
}
199
200
/**
201
* Implementation required by ScriptEngine parent<br />
202
* Set a new context for the engine
203
* @param context the new context to install in the engine
204
*/
205
public void setContext(final ScriptContext context) {
206
this.context = context;
207
}
208
209
/**
210
* Implementation required by ScriptEngine parent<br />
211
* Create and return a new set of simple bindings.
212
* @return a new and empty set of bindings
213
*/
214
public Bindings createBindings() {
215
return new SimpleBindings();
216
}
217
218
/**
219
* Implementation required by ScriptEngine parent<br />
220
* Return the engines bindings for the context indicated by the argument.
221
* @param scope contextual scope to return.
222
* @return the bindings in the engine for the scope indicated by the parameter
223
*/
224
public Bindings getBindings(final int scope) {
225
return context.getBindings(scope);
226
}
227
228
/**
229
* Implementation required by ScriptEngine parent<br />
230
* Sets the bindings for the indicated scope
231
* @param bindings a set of bindings to assign to the engine
232
* @param scope the scope that the passed bindings should be assigned to
233
*/
234
public void setBindings(final Bindings bindings, final int scope) {
235
context.setBindings(bindings, scope);
236
}
237
238
/**
239
* Implementation required by ScriptEngine parent<br />
240
* Insert a key and value into the engine's bindings (scope: engine)
241
* @param key the key of the pair
242
* @param value the value of the pair
243
*/
244
public void put(final String key, final Object value) {
245
getBindings(ScriptContext.ENGINE_SCOPE).put(key, value);
246
}
247
248
/**
249
* Implementation required by ScriptEngine parent<br />
250
* Get a value from the engine's bindings using a key (scope: engine)
251
* @param key the key of the pair
252
* @return the value of the pair
253
*/
254
public Object get(final String key) {
255
return getBindings(ScriptContext.ENGINE_SCOPE).get(key);
256
}
257
258
/**
259
* Implementation required by ScriptEngine parent<br />
260
* Passes the Reader argument, as well as the engine's context to a lower evaluation function.<br />
261
* Prefers FileReader or BufferedReader wrapping FileReader as argument.
262
* @param reader a Reader to AppleScript source or compiled AppleScript
263
* @return an Object corresponding to the return value of the script
264
* @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
265
*/
266
public Object eval(final Reader reader) throws ScriptException {
267
return eval(reader, getContext());
268
}
269
270
/**
271
* Implementation required by ScriptEngine parent<br />
272
* Uses the passed bindings as the context for executing the passed script.
273
* @param reader a stream to AppleScript source or compiled AppleScript
274
* @param bindings a Bindings object representing the contexts to execute inside
275
* @return the return value of the script
276
* @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
277
*/
278
public Object eval(final Reader reader, final Bindings bindings) throws ScriptException {
279
final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
280
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
281
final Object retval = eval(reader);
282
getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);
283
return retval;
284
}
285
286
/**
287
* Implementation required by ScriptEngine parent<br />
288
* This function can execute either AppleScript source or compiled AppleScript and functions by writing the
289
* contents of the Reader to a temporary file and then executing it with the engine's context.
290
* @param reader
291
* @param scriptContext
292
* @return an Object corresponding to the return value of the script
293
*/
294
public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
295
checkSecurity();
296
297
// write our passed reader to a temporary file
298
File tmpfile;
299
FileWriter tmpwrite;
300
try {
301
tmpfile = Files.createTempFile("AppleScriptEngine.", ".scpt").toFile();
302
tmpwrite = new FileWriter(tmpfile);
303
304
// read in our input and write directly to tmpfile
305
/* TODO -- this may or may not be avoidable for certain Readers,
306
* if a filename can be grabbed, it would be faster to get that and
307
* use the underlying file than writing a temp file.
308
*/
309
int data;
310
while ((data = reader.read()) != -1) {
311
tmpwrite.write(data);
312
}
313
tmpwrite.close();
314
315
// set up our context business
316
final long contextptr = scriptContextToNSDictionary(context);
317
try {
318
final long retCtx = evalScriptFromURL("file://" + tmpfile.getCanonicalPath(), contextptr);
319
Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
320
disposeContext(retCtx);
321
return retVal;
322
} finally {
323
disposeContext(contextptr);
324
tmpfile.delete();
325
}
326
} catch (final IOException e) {
327
throw new ScriptException(e);
328
}
329
}
330
331
/**
332
* Implementation required by ScriptEngine parent<br />
333
* Evaluate an AppleScript script passed as a source string. Using the engine's built in context.
334
* @param script the string to execute.
335
* @return an Object representing the return value of the script
336
* @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
337
*/
338
public Object eval(final String script) throws ScriptException {
339
return eval(script, getContext());
340
}
341
342
/**
343
* Implementation required by ScriptEngine parent<br />
344
* Evaluate an AppleScript script passed as a source string with a custom ScriptContext.
345
* @param script the AppleScript source to compile and execute.
346
* @param scriptContext the context to execute the script under
347
* @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
348
*/
349
public Object eval(final String script, final Bindings bindings) throws ScriptException {
350
final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
351
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
352
353
final Object retval = eval(script);
354
getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);
355
356
return retval;
357
}
358
359
/**
360
* Implementation required by ScriptEngine parent
361
* @param script
362
* @param scriptContext
363
*/
364
public Object eval(final String script, final ScriptContext context) throws ScriptException {
365
checkSecurity();
366
final long ctxPtr = scriptContextToNSDictionary(context);
367
try {
368
final long retCtx = evalScript(script, ctxPtr);
369
Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
370
disposeContext(retCtx);
371
return retVal;
372
} finally {
373
disposeContext(ctxPtr);
374
}
375
}
376
377
/**
378
* Converts a ScriptContext into an NSDictionary
379
* @param context ScriptContext for the engine
380
* @return a pointer to an NSDictionary
381
*/
382
private long scriptContextToNSDictionary(final ScriptContext context) throws ScriptException {
383
final Map<String, Object> contextAsMap = new HashMap<String, Object>();
384
for (final Entry<String, Object> e : context.getBindings(ScriptContext.ENGINE_SCOPE).entrySet()) {
385
contextAsMap.put(e.getKey().replaceAll("\\.", "_"), e.getValue());
386
}
387
return createContextFrom(contextAsMap);
388
}
389
}
390
391