| /* |
| * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package com.sun.demo.scripting.jconsole; |
| |
| import com.sun.tools.jconsole.*; |
| import java.awt.*; |
| import java.awt.event.*; |
| import java.io.*; |
| import java.lang.reflect.*; |
| import java.util.concurrent.CountDownLatch; |
| import javax.script.*; |
| import javax.swing.*; |
| import javax.swing.event.*; |
| import java.util.*; |
| |
| /** |
| * This is script console plugin. This class uses javax.script API to create |
| * interactive read-eval-print script shell within the jconsole GUI. |
| */ |
| public class ScriptJConsolePlugin extends JConsolePlugin |
| implements ScriptShellPanel.CommandProcessor { |
| // Panel for our tab |
| private volatile ScriptShellPanel window; |
| // Tabs that we add to jconsole GUI |
| private Map<String, JPanel> tabs; |
| |
| // Script engine that evaluates scripts |
| private volatile ScriptEngine engine; |
| |
| // script engine initialization occurs in background. |
| // This latch is used to coorrdinate engine init and eval. |
| private CountDownLatch engineReady = new CountDownLatch(1); |
| |
| // File extension used for scripts of chosen language. |
| // For eg. ".js" for JavaScript, ".bsh" for BeanShell. |
| private String extension; |
| |
| // Prompt to print in the read-eval-print loop. This is |
| // derived from the script file extension. |
| private volatile String prompt; |
| |
| /** |
| * Constructor to create this plugin |
| */ |
| public ScriptJConsolePlugin() { |
| } |
| |
| @Override public Map<String, JPanel> getTabs() { |
| // create ScriptEngine |
| createScriptEngine(); |
| |
| // create panel for tab |
| window = new ScriptShellPanel(this); |
| |
| // add tab to tabs map |
| tabs = new HashMap<String, JPanel>(); |
| tabs.put("Script Shell", window); |
| |
| new Thread(new Runnable() { |
| public void run() { |
| // initialize the script engine |
| initScriptEngine(); |
| engineReady.countDown(); |
| } |
| }).start(); |
| return tabs; |
| } |
| |
| @Override public SwingWorker<?,?> newSwingWorker() { |
| return null; |
| } |
| |
| @Override public void dispose() { |
| window.dispose(); |
| } |
| |
| public String getPrompt() { |
| return prompt; |
| } |
| |
| public String executeCommand(String cmd) { |
| String res; |
| try { |
| engineReady.await(); |
| Object tmp = engine.eval(cmd); |
| res = (tmp == null)? null : tmp.toString(); |
| } catch (InterruptedException ie) { |
| res = ie.getMessage(); |
| } catch (ScriptException se) { |
| res = se.getMessage(); |
| } |
| return res; |
| } |
| |
| //-- Internals only below this point |
| private void createScriptEngine() { |
| ScriptEngineManager manager = new ScriptEngineManager(); |
| String language = getScriptLanguage(); |
| engine = manager.getEngineByName(language); |
| if (engine == null) { |
| throw new RuntimeException("cannot load " + language + " engine"); |
| } |
| extension = engine.getFactory().getExtensions().get(0); |
| prompt = extension + ">"; |
| engine.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE); |
| } |
| |
| // Name of the System property used to select scripting language |
| private static final String LANGUAGE_KEY = "com.sun.demo.jconsole.console.language"; |
| |
| private String getScriptLanguage() { |
| // check whether explicit System property is set |
| String lang = System.getProperty(LANGUAGE_KEY); |
| if (lang == null) { |
| // default is JavaScript |
| lang = "JavaScript"; |
| } |
| return lang; |
| } |
| |
| // create Bindings that is backed by a synchronized HashMap |
| private Bindings createBindings() { |
| Map<String, Object> map = |
| Collections.synchronizedMap(new HashMap<String, Object>()); |
| return new SimpleBindings(map); |
| } |
| |
| // create and initialize script engine |
| private void initScriptEngine() { |
| // set pre-defined global variables |
| setGlobals(); |
| // load pre-defined initialization file |
| loadInitFile(); |
| // load current user's initialization file |
| loadUserInitFile(); |
| } |
| |
| // set pre-defined global variables for script |
| private void setGlobals() { |
| engine.put("engine", engine); |
| engine.put("window", window); |
| engine.put("plugin", this); |
| } |
| |
| // load initial script file (jconsole.<extension>) |
| private void loadInitFile() { |
| String oldFilename = (String) engine.get(ScriptEngine.FILENAME); |
| engine.put(ScriptEngine.FILENAME, "<built-in jconsole." + extension + ">"); |
| try { |
| Class myClass = this.getClass(); |
| InputStream stream = myClass.getResourceAsStream("/resources/jconsole." + |
| extension); |
| if (stream != null) { |
| engine.eval(new InputStreamReader(new BufferedInputStream(stream))); |
| } |
| } catch (Exception exp) { |
| exp.printStackTrace(); |
| // FIXME: What else I can do here?? |
| } finally { |
| engine.put(ScriptEngine.FILENAME, oldFilename); |
| } |
| } |
| |
| // load user's initial script file (~/jconsole.<extension>) |
| private void loadUserInitFile() { |
| String oldFilename = (String) engine.get(ScriptEngine.FILENAME); |
| String home = System.getProperty("user.home"); |
| if (home == null) { |
| // no user.home?? should not happen?? |
| return; |
| } |
| String fileName = home + File.separator + "jconsole." + extension; |
| if (! (new File(fileName).exists())) { |
| // user does not have ~/jconsole.<extension> |
| return; |
| } |
| engine.put(ScriptEngine.FILENAME, fileName); |
| try { |
| engine.eval(new FileReader(fileName)); |
| } catch (Exception exp) { |
| exp.printStackTrace(); |
| // FIXME: What else I can do here?? |
| } finally { |
| engine.put(ScriptEngine.FILENAME, oldFilename); |
| } |
| } |
| } |