package com.revolsys.swing.scripting; import java.awt.Window; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import java.util.function.Consumer; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject.Kind; import javax.tools.ToolProvider; import com.revolsys.io.FileUtil; import com.revolsys.io.file.FileNameExtensionFilter; import com.revolsys.process.JavaProcess; import com.revolsys.swing.SwingUtil; import com.revolsys.swing.logging.LoggingEventPanel; import com.revolsys.util.PreferencesUtil; import groovy.lang.Binding; import groovy.lang.GroovyShell; public class ScriptRunner { private static final String[] NULL_MAIN_ARGS = new String[0]; public static void main(final String[] args) { if (args.length > 0) { final String fileName = args[0]; final File scriptFile = FileUtil.getFile(fileName); runScript(scriptFile); } } public static void runScript(final File scriptFile) { final ScriptRunner scriptRunner = new ScriptRunner(scriptFile); scriptRunner.run(); } public static void runScript(final Window window) { runScript(window, ScriptRunner::runScript); } public static void runScript(final Window window, final Consumer<File> action) { final JFileChooser fileChooser = SwingUtil.newFileChooser("Select Script", "com.revolsys.swing.tools.script", "directory"); final FileNameExtensionFilter groovyFilter = new FileNameExtensionFilter("Groovy Script", "groovy"); fileChooser.addChoosableFileFilter(groovyFilter); final FileNameExtensionFilter javaFilter = new FileNameExtensionFilter("Java", "java"); fileChooser.addChoosableFileFilter(javaFilter); fileChooser.setMultiSelectionEnabled(false); final int returnVal = fileChooser.showOpenDialog(window); if (returnVal == JFileChooser.APPROVE_OPTION) { final File selectedFile = fileChooser.getSelectedFile(); final File scriptFile = FileUtil.getFile(selectedFile); PreferencesUtil.setUserString("com.revolsys.swing.tools.script", "directory", scriptFile.getParent()); action.accept(scriptFile); } } public static void runScriptProcess(final Window window, final File logDirectory, final JavaProcess process) { runScript(window, (scriptFile) -> { process.setProgramClass(ScriptRunner.class); process.addProgramArgument(0, scriptFile.getAbsolutePath()); if (logDirectory != null) { final String logFileName = FileUtil.getBaseName(scriptFile) + ".log"; final File logFile = FileUtil.getFile(logDirectory, logFileName); logDirectory.mkdirs(); process.setLogFile(logFile); } process.startThread(); }); } public static void runScriptProcess(final Window window, final JavaProcess process) { runScript(window, (scriptFile) -> { process.setProgramClass(ScriptRunner.class); process.addProgramArgument(0, scriptFile.getAbsolutePath()); process.startThread(); }); } private final File scriptFile; public ScriptRunner(final File scriptFile) { this.scriptFile = FileUtil.getFile(scriptFile); } public void run() { if (this.scriptFile == null) { } else if (this.scriptFile.exists() && this.scriptFile.isFile()) { final String fileExtension = FileUtil.getFileNameExtension(this.scriptFile); try { if ("java".equals(fileExtension)) { final String scriptClassName = FileUtil.getBaseName(this.scriptFile); final URIJavaFileObject scriptJavaFile = new URIJavaFileObject(this.scriptFile, Kind.SOURCE); final JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); final JavaFileManager fileManager = new InMemoryJavaFileManager(scriptJavaFile); final CompilationTask compilationTask = javaCompiler.getTask(null, fileManager, null, null, null, Collections.singleton(scriptJavaFile)); compilationTask.call(); final ClassLoader classLoader = fileManager.getClassLoader(null); final Class<?> scriptClass; try { scriptClass = classLoader.loadClass(scriptClassName); } catch (final ClassNotFoundException e) { showErrorDialog("must contain the class:<br />"// + "<code>public class " + scriptClassName + "</code><br />" // + "in the default package."); return; } final Method mainMethod; try { mainMethod = scriptClass.getDeclaredMethod("main", String[].class); } catch (final NoSuchMethodException e) { showErrorDialog("must contain the method:<br />" + "<code>public static void main(String[] args)</code><br />" // + " in the class:<br />" // + "<code>" + scriptClassName + "</code>"); return; } try { mainMethod.invoke(null, (Object)NULL_MAIN_ARGS); } catch (final InvocationTargetException e) { final Throwable targetException = e.getTargetException(); showErrorDialog(scriptClass, targetException); } catch (final Throwable e) { showErrorDialog(scriptClass, e); return; } } else { final Binding binding = new Binding(); final GroovyShell shell = new GroovyShell(binding); shell.run(this.scriptFile, NULL_MAIN_ARGS); } } catch (final Throwable e) { showErrorDialog(getClass(), e); } } else { showErrorDialog("Does not exist"); } } private void showErrorDialog(final Class<?> scriptClass, final Throwable e) { LoggingEventPanel.showDialog(SwingUtil.getActiveWindow(), "Error running script file:<br /> " // + "<code>" + this.scriptFile + "</code><br />"// + e.getMessage(), e); } private void showErrorDialog(final String message) { JOptionPane.showMessageDialog(SwingUtil.getActiveWindow(), "<html>Script file:<br /> " + "<code>" + this.scriptFile + "</code><br />" + message + "</html>", "Script Error", JOptionPane.ERROR_MESSAGE); } }