提交 77c21248 编写于 作者: S sundar

8190698: jjs tool of jdk.scripting.nashorn.shell module should not statically...

8190698: jjs tool of jdk.scripting.nashorn.shell module should not statically depend on java.desktop
Reviewed-by: jlaskey, hannesw
上级 5f964487
......@@ -25,7 +25,6 @@
package jdk.nashorn.tools.jjs;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
......@@ -69,7 +68,7 @@ class Console implements AutoCloseable {
});
in.addCompleter(completer);
Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
bind(DOCUMENTATION_SHORTCUT, (ActionListener)evt -> showDocumentation(docHelper));
bind(DOCUMENTATION_SHORTCUT, (Runnable) ()->showDocumentation(docHelper));
try {
Signal.handle(new Signal("CONT"), new Handler() {
@Override public void handle(Signal sig) {
......
......@@ -117,7 +117,7 @@ final class EditObject extends AbstractJSObject {
final SaveHandler saveHandler = new SaveHandler(initText);
if (editor != null && !editor.isEmpty()) {
ExternalEditor.edit(editor, errorHandler, initText, saveHandler, console);
} else if (! Main.HEADLESS) {
} else {
try {
ServiceLoader<BuildInEditorProvider> sl
= ServiceLoader.load(BuildInEditorProvider.class);
......@@ -136,8 +136,6 @@ final class EditObject extends AbstractJSObject {
} catch (RuntimeException ex) {
errorHandler.accept(Main.getMessage("jjs.err.cant.launch.editor"));
}
} else {
errorHandler.accept(Main.getMessage("no.editor"));
}
return UNDEFINED;
}
......
......@@ -27,8 +27,6 @@ package jdk.nashorn.tools.jjs;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.awt.Desktop;
import java.awt.GraphicsEnvironment;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
......@@ -65,7 +63,6 @@ public final class Main extends Shell {
private static final String DOC_PROPERTY_NAME = "__doc__";
static final boolean DEBUG = Boolean.getBoolean("nashorn.jjs.debug");
static final boolean HEADLESS = GraphicsEnvironment.isHeadless();
// file where history is persisted.
private static final File HIST_FILE = new File(new File(System.getProperty("user.home")), ".jjs.history");
......@@ -120,7 +117,49 @@ public final class Main extends Shell {
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
final PropertiesHelper propsHelper = new PropertiesHelper(context);
final NashornCompleter completer = new NashornCompleter(context, global, this, propsHelper);
if (globalChanged) {
Context.setGlobal(global);
}
// Check if java.desktop module is available and we're running in non-headless mode.
// We access AWT via script to avoid direct dependency on java.desktop module.
final boolean isHeadless = (boolean) context.eval(global,
"(function() { \n" +
" var env = java.awt.GraphicsEnvironment; \n" +
" return env && typeof env.isHeadless == 'function'? \n" +
" env.isHeadless() : true; \n" +
"})()",
global, "<headless-check>");
// Function that shows a JFileChooser dialog and returns the file name chosen (if chosen).
// We access swing from script to avoid direct dependency on java.desktop module.
final ScriptFunction fileChooserFunc = isHeadless? null : (ScriptFunction) context.eval(global,
"(function() { \n" +
" var ExtensionFilter = javax.swing.filechooser.FileNameExtensionFilter; \n" +
" var JFileChooser = javax.swing.JFileChooser; \n" +
" function run() { \n" +
" var chooser = new JFileChooser(); \n" +
" chooser.fileFilter = new ExtensionFilter('JavaScript Files', 'js'); \n" +
" var retVal = chooser.showOpenDialog(null); \n" +
" return retVal == JFileChooser.APPROVE_OPTION ? \n" +
" chooser.selectedFile.absolutePath : null; \n" +
" }; \n" +
" var fileChooserTask = new java.util.concurrent.FutureTask(run); \n" +
" javax.swing.SwingUtilities.invokeLater(fileChooserTask); \n" +
" return fileChooserTask.get(); \n" +
"})",
global, "<file-chooser>");
final NashornCompleter completer = new NashornCompleter(context, global, this, propsHelper, fileChooserFunc);
// Function that opens up the desktop browser application with the given URI.
// We access AWT from script to avoid direct dependency on java.desktop module.
final ScriptFunction browseFunc = isHeadless? null : (ScriptFunction) context.eval(global,
"(function(uri) { \n" +
" java.awt.Desktop.desktop.browse(uri); \n" +
"})",
global, "<browse>");
try (final Console in = new Console(System.in, System.out, HIST_FILE, completer,
str -> {
......@@ -128,14 +167,14 @@ public final class Main extends Shell {
final Object res = context.eval(global, str, global, "<shell>");
if (res != null && res != UNDEFINED) {
// Special case Java types: show the javadoc for the class.
if (NativeJava.isType(UNDEFINED, res)) {
if (!isHeadless && NativeJava.isType(UNDEFINED, res)) {
final String typeName = NativeJava.typeName(UNDEFINED, res).toString();
final String url = typeName.replace('.', '/').replace('$', '.') + ".html";
openBrowserForJavadoc(url);
} else if (res instanceof NativeJavaPackage) {
openBrowserForJavadoc(browseFunc, url);
} else if (!isHeadless && res instanceof NativeJavaPackage) {
final String pkgName = ((NativeJavaPackage)res).getName();
final String url = pkgName.replace('.', '/') + "/package-summary.html";
openBrowserForJavadoc(url);
openBrowserForJavadoc(browseFunc, url);
} else if (res instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)res;
if (sobj.has(DOC_PROPERTY_NAME)) {
......@@ -153,10 +192,6 @@ public final class Main extends Shell {
return null;
})) {
if (globalChanged) {
Context.setGlobal(global);
}
global.addShellBuiltins();
// redefine readLine to use jline Console's readLine!
......@@ -282,11 +317,10 @@ public final class Main extends Shell {
}
private static String JAVADOC_BASE = "https://docs.oracle.com/javase/9/docs/api/";
private static void openBrowserForJavadoc(String relativeUrl) {
private static void openBrowserForJavadoc(ScriptFunction browse, String relativeUrl) {
try {
final URI uri = new URI(JAVADOC_BASE + relativeUrl);
Desktop.getDesktop().browse(uri);
ScriptRuntime.apply(browse, null, uri);
} catch (Exception ignored) {
}
}
......
......@@ -29,12 +29,8 @@ import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.Objects;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.SwingUtilities;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.UserInterruptException;
import jdk.nashorn.api.tree.AssignmentTree;
......@@ -60,6 +56,7 @@ import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
......@@ -72,16 +69,19 @@ final class NashornCompleter implements Completer {
private final ScriptEnvironment env;
private final PartialParser partialParser;
private final PropertiesHelper propsHelper;
private final ScriptFunction fileChooserFunc;
private final Parser parser;
private static final boolean BACKSLASH_FILE_SEPARATOR = File.separatorChar == '\\';
NashornCompleter(final Context context, final Global global,
final PartialParser partialParser, final PropertiesHelper propsHelper) {
final PartialParser partialParser, final PropertiesHelper propsHelper,
final ScriptFunction fileChooserFunc) {
this.context = context;
this.global = global;
this.env = context.getEnv();
this.partialParser = partialParser;
this.propsHelper = propsHelper;
this.fileChooserFunc = fileChooserFunc;
this.parser = createParser(env);
}
......@@ -236,8 +236,9 @@ final class NashornCompleter implements Completer {
final ExpressionTree topExpr = getTopLevelExpression(parser, completeExpr);
if (topExpr == null) {
// special case for load call that looks like "load(" with optional whitespaces
if (LOAD_CALL.matcher(test).matches()) {
// Special case for load call that looks like "load(" with optional whitespaces.
// If we have a fileChooserFunc then call it, so that the user can select a file.
if (fileChooserFunc != null && LOAD_CALL.matcher(test).matches()) {
String name = readFileName(context.getErr());
if (name != null) {
// handle '\' file separator
......@@ -269,26 +270,11 @@ final class NashornCompleter implements Completer {
// Internals only below this point
// read file name from the user using by showing a swing file chooser diablog
private static String readFileName(final PrintWriter err) {
// if running on AWT Headless mode, don't attempt swing dialog box!
if (Main.HEADLESS) {
return null;
}
final FutureTask<String> fileChooserTask = new FutureTask<String>(() -> {
// show a file chooser dialog box
final JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new FileNameExtensionFilter("JavaScript Files", "js"));
final int retVal = chooser.showOpenDialog(null);
return retVal == JFileChooser.APPROVE_OPTION ?
chooser.getSelectedFile().getAbsolutePath() : null;
});
SwingUtilities.invokeLater(fileChooserTask);
private String readFileName(final PrintWriter err) {
try {
return fileChooserTask.get();
} catch (final ExecutionException | InterruptedException e) {
final Object res = ScriptRuntime.apply(fileChooserFunc, null);
return res instanceof String? (String)res : null;
} catch (final Exception e) {
err.println(e);
if (Main.DEBUG) {
e.printStackTrace();
......
......@@ -39,7 +39,6 @@
*/
module jdk.scripting.nashorn.shell {
requires java.compiler;
requires java.desktop;
requires jdk.internal.le;
requires jdk.scripting.nashorn;
requires jdk.internal.ed;
......
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8190698: jjs tool of jdk.scripting.nashorn.shell module should not statically depend on java.desktop
*
* @test
* @run
*/
var optJjsMod = java.lang.ModuleLayer.boot().findModule("jdk.scripting.nashorn.shell");
// make sure that the module exists!
Assert.assertTrue(optJjsMod.isPresent());
// jdk.scripting.nashorn.shell should not have java.desktop dependency
var javaDesktopDependency = optJjsMod.get().
descriptor.requires().
stream().
filter(function(mod) { return mod.name() == "java.desktop" }).
findFirst();
Assert.assertTrue(!javaDesktopDependency.isPresent());
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册