/**
* Copyright 2011 Intuit Inc. All Rights Reserved
*/
package com.intuit.tank.tools.script;
/*
* #%L
* script-filter
* %%
* Copyright (C) 2011 - 2015 Intuit Inc.
* %%
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* #L%
*/
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.script.ScriptException;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rtextarea.RTextScrollPane;
import com.intuit.tank.api.model.v1.script.ExternalScriptTO;
import com.intuit.tank.api.model.v1.script.ScriptTO;
import com.intuit.tank.client.v1.script.ScriptServiceClient;
import com.intuit.tank.tools.script.ScriptRunner;
/**
* ScrioptFilterRunner
*
* @author dangleton
*
*/
public class ScriptFilterRunner extends JFrame {
private static final long serialVersionUID = 1L;
private static final String INITIAL_OUTPUT_CONTENT = "Output:\n";
private ScriptRunner runner = new ScriptRunner();
private JComboBox languageSelector;
private JLabel currentFileLabel;
private RSyntaxTextArea scriptEditorTA;
private XMlViewDialog xmlViewDialog;
private ScriptTO tankScript;
private TextAreaOutputLogger output;
private File xmlFile;
private JButton runBT;
private JButton showXmlBT;
private JButton saveBT;
private JLabel localLB;
private ScriptServiceClient scriptServiceClient;
private ExternalScriptTO currentExternalScript;
private JFileChooser loadChooser;
private boolean local = true;
/**
* @throws HeadlessException
*/
public ScriptFilterRunner(final boolean terminate, String serviceUrl) throws HeadlessException {
super("Intuit Tank Script Filter Editor");
setSize(new Dimension(1024, 800));
setBounds(new Rectangle(getSize()));
setPreferredSize(getSize());
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
if (terminate) {
System.exit(0);
}
}
});
scriptServiceClient = new ScriptServiceClient(serviceUrl);
Component topPanel = createTopPanel();
Component bottomPanel = createBottomPanel();
Component contentPanel = createContentPanel();
add(topPanel, BorderLayout.NORTH);
add(contentPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.SOUTH);
WindowUtil.centerOnScreen(this);
pack();
}
/**
* @return
*/
private Component createContentPanel() {
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
scriptEditorTA = new RSyntaxTextArea();
setSyntaxStyle();
RTextScrollPane sp = new RTextScrollPane(scriptEditorTA);
pane.setTopComponent(sp);
JScrollPane scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
output = new TextAreaOutputLogger(scrollPane, INITIAL_OUTPUT_CONTENT);
output.setEditable(false);
output.setAutoscrolls(true);
output.setScrollContent(true);
output.setWrapStyleWord(true);
scrollPane.setViewportView(output);
JToolBar toolBar = new JToolBar();
JButton clearBT = new JButton("Clear");
clearBT.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
output.setText(INITIAL_OUTPUT_CONTENT);
}
});
final JCheckBox scrollCB = new JCheckBox("Auto Scroll Content");
scrollCB.setSelected(true);
scrollCB.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
output.setScrollContent(scrollCB.isSelected());
}
});
toolBar.add(clearBT);
toolBar.add(scrollCB);
panel.add(toolBar, BorderLayout.NORTH);
panel.add(scrollPane, BorderLayout.CENTER);
pane.setBottomComponent(panel);
pane.setDividerLocation(300);
return pane;
}
/**
* @return
*/
private Component createTopPanel() {
JPanel topPanel = new JPanel(new GridBagLayout());
List<ConfiguredLanguage> configuredLanguages = ConfiguredLanguage.getConfiguredLanguages();
languageSelector = new JComboBox(configuredLanguages.toArray());
languageSelector.setSelectedIndex(0);
languageSelector.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
setSyntaxStyle();
}
});
currentFileLabel = new JLabel();
final JFileChooser jFileChooser = new JFileChooser();
jFileChooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return "Tank XML Files";
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith("_ts.xml");
}
});
JButton button = new JButton("Select File...");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int showOpenDialog = jFileChooser.showOpenDialog(ScriptFilterRunner.this);
if (showOpenDialog == JFileChooser.APPROVE_OPTION) {
loadTSXml(jFileChooser.getSelectedFile());
}
}
});
xmlViewDialog = new XMlViewDialog(this);
xmlViewDialog.setSize(new Dimension(800, 500));
showXmlBT = new JButton("Show XML");
showXmlBT.setEnabled(false);
showXmlBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
displayXml();
}
});
saveBT = new JButton("Save XML");
saveBT.setEnabled(false);
saveBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveXml();
}
});
JPanel xmlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 20));
xmlPanel.add(button);
xmlPanel.add(showXmlBT);
xmlPanel.add(saveBT);
int y = 0;
topPanel.add(new JLabel("Current Tank XML: "), getConstraints(0, y, GridBagConstraints.NONE));
topPanel.add(currentFileLabel, getConstraints(1, y++, GridBagConstraints.HORIZONTAL));
topPanel.add(new JLabel("Select Script Language: "), getConstraints(0, y, GridBagConstraints.NONE));
topPanel.add(languageSelector, getConstraints(1, y++, GridBagConstraints.HORIZONTAL));
topPanel.add(new JLabel("Select Tank XML: "), getConstraints(0, y, GridBagConstraints.NONE));
topPanel.add(xmlPanel, getConstraints(1, y++, GridBagConstraints.HORIZONTAL));
return topPanel;
}
/**
*
*/
protected void toggleStorageMode() {
local = !local;
setLocalLable();
}
private void setLocalLable() {
localLB.setText(local ? "Current Storage Mode: Local" : "Current Storage Mode: Remote");
}
/**
* @param loadChooser
* @return
*/
public Component createBottomPanel() {
loadChooser = new JFileChooser();
loadChooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return "Script Files";
}
@Override
public boolean accept(File f) {
return f.isDirectory()
|| ConfiguredLanguage.getConfiguredExtensions().contains(
FilenameUtils.getExtension(f.getName()));
}
});
runBT = new JButton("Run Script");
runBT.setEnabled(false);
runBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
runScript();
}
});
JButton chooseBT = new JButton("Open Script...");
chooseBT.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
loadScript();
}
});
JButton saveScriptBT = new JButton("Save Script...");
saveScriptBT.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
saveScript(false);
}
});
JButton saveAsScriptBT = new JButton("Save Script As...");
saveAsScriptBT.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
saveScript(true);
}
});
JButton localBT = new JButton("Toggle Storage Mode");
localBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
toggleStorageMode();
}
});
localLB = new JLabel();
setLocalLable();
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
bottomPanel.add(runBT);
bottomPanel.add(chooseBT);
bottomPanel.add(saveScriptBT);
bottomPanel.add(saveAsScriptBT);
bottomPanel.add(localLB);
bottomPanel.add(localBT);
return bottomPanel;
}
/**
*
*/
protected void saveScript(boolean saveAs) {
if (local) {
int showOpenDialog = loadChooser.showSaveDialog(ScriptFilterRunner.this);
if (showOpenDialog == JFileChooser.APPROVE_OPTION) {
saveScript(loadChooser.getSelectedFile());
}
} else {
storeScript(saveAs);
}
}
/**
*
*/
protected void loadScript() {
if (local) {
// open script from file system
int showOpenDialog = loadChooser.showOpenDialog(ScriptFilterRunner.this);
if (showOpenDialog == JFileChooser.APPROVE_OPTION) {
File file = loadChooser.getSelectedFile();
ConfiguredLanguage languagebyExtension = ConfiguredLanguage.getLanguagebyExtension(file
.getName());
if (languagebyExtension != null) {
try {
scriptEditorTA.setText(FileUtils.readFileToString(file));
currentExternalScript = null;
languageSelector.setSelectedItem(languagebyExtension);
} catch (IOException e) {
JOptionPane.showMessageDialog(ScriptFilterRunner.this, e.getMessage(),
"Error loading script", JOptionPane.ERROR_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(ScriptFilterRunner.this,
"Script language extension not configured. valid extensions are: "
+ ConfiguredLanguage.getConfiguredExtensions(), "Error loading script",
JOptionPane.ERROR_MESSAGE);
}
}
} else {
selectScript(new SelectDialog<ExternalScriptTO>(ScriptFilterRunner.this, scriptServiceClient
.getExternalScripts()));
}
}
/**
*
*/
protected void storeScript(boolean saveAs) {
ConfiguredLanguage language = (ConfiguredLanguage) languageSelector.getSelectedItem();
if (saveAs || currentExternalScript == null) {
String retVal = JOptionPane.showInputDialog("Script Name: ", "<Script Name>");
if (retVal != null) {
retVal = retVal + "." + language.getDefaultExtension();
currentExternalScript = new ExternalScriptTO();
currentExternalScript.setName(retVal);
currentExternalScript.setCreator("");
} else {
return;
}
} else {
currentExternalScript.setName(FilenameUtils.getBaseName(currentExternalScript.getName()) + "."
+ language.getDefaultExtension());
}
currentExternalScript.setScript(scriptEditorTA.getText());
currentExternalScript = scriptServiceClient.saveOrUpdateExternalScript(currentExternalScript);
}
/**
*
*/
protected void selectScript(SelectDialog<ExternalScriptTO> scriptSelectDialog) {
scriptSelectDialog.setVisible(true);
if (scriptSelectDialog.getSelectedObject() != null) {
ExternalScriptTO selectedScript = scriptSelectDialog.getSelectedObject();
ConfiguredLanguage languagebyExtension = ConfiguredLanguage.getLanguagebyExtension(selectedScript
.getName());
if (languagebyExtension != null) {
languageSelector.setSelectedItem(languagebyExtension);
scriptEditorTA.setText(selectedScript.getScript());
currentExternalScript = selectedScript;
} else {
JOptionPane.showMessageDialog(this, "Script language extension not configured. valid extensions are: "
+ ConfiguredLanguage.getConfiguredExtensions(), "Error loading script",
JOptionPane.ERROR_MESSAGE);
}
}
}
/**
* @param selectedFile
*/
protected void saveScript(File selectedFile) {
try {
FileUtils.writeStringToFile(selectedFile, this.scriptEditorTA.getText());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage(), "Error writing script", JOptionPane.ERROR_MESSAGE);
}
}
/**
*
*/
protected void saveXml() {
Writer fw = null;
try {
fw = new OutputStreamWriter(new FileOutputStream(xmlFile), "UTF-8");
// fw = new FileWriter(xmlFile);
JAXBContext ctx = JAXBContext.newInstance(ScriptTO.class.getPackage().getName());
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty("jaxb.formatted.output", true);
marshaller.marshal(tankScript, fw);
} catch (Exception e) {
JOptionPane.showMessageDialog(this, e.getMessage(), "Error writing file", JOptionPane.ERROR_MESSAGE);
} finally {
IOUtils.closeQuietly(fw);
}
}
/**
*
*/
protected void setSyntaxStyle() {
ConfiguredLanguage item = (ConfiguredLanguage) languageSelector.getSelectedItem();
scriptEditorTA.setSyntaxEditingStyle(item.getSyntaxStyle());
}
/**
*
*/
protected void displayXml() {
if (tankScript != null) {
xmlViewDialog.setTitle(tankScript.getName());
String xml = toXml(tankScript);
xmlViewDialog.setText(xml, !xmlViewDialog.isVisible());
if (!xmlViewDialog.isVisible()) {
WindowUtil.centerOnParent(xmlViewDialog);
xmlViewDialog.setVisible(true);
}
} else {
JOptionPane.showMessageDialog(this, "You must select a Tank XML file.", "Data Needed",
JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* @param x
* @param y
* @return
*/
private GridBagConstraints getConstraints(int x, int y, int fill) {
GridBagConstraints ret = new GridBagConstraints(x, y, 1, 1, x, .5D, GridBagConstraints.WEST, fill, new Insets(
5, 5, 5, 5), 5, 5);
return ret;
}
private void loadTSXml(File selectedFile) {
try {
JAXBContext ctx = JAXBContext.newInstance(ScriptTO.class.getPackage().getName());
Unmarshaller unmarshaller = ctx.createUnmarshaller();
tankScript = (ScriptTO) unmarshaller.unmarshal(selectedFile);
currentFileLabel.setText(selectedFile.getName());
xmlFile = selectedFile;
showXmlBT.setEnabled(true);
runBT.setEnabled(true);
saveBT.setEnabled(true);
} catch (JAXBException e) {
JOptionPane.showMessageDialog(this, e.getMessage(), "Error reading file", JOptionPane.ERROR_MESSAGE);
}
}
private String toXml(ScriptTO turboScriptTO) {
String ret = null;
try {
JAXBContext ctx = JAXBContext.newInstance(ScriptTO.class.getPackage().getName());
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty("jaxb.formatted.output", true);
StringWriter sw = new StringWriter();
marshaller.marshal(turboScriptTO, sw);
ret = sw.toString();
} catch (JAXBException e) {
JOptionPane.showMessageDialog(this, e.getMessage(), "Error reading file", JOptionPane.ERROR_MESSAGE);
}
return ret;
}
private void runScript() {
String text = scriptEditorTA.getText();
if (tankScript == null) {
JOptionPane.showMessageDialog(this, "You must select a Tank XML file.", "Data Needed",
JOptionPane.INFORMATION_MESSAGE);
} else if (StringUtils.isEmpty(text)) {
JOptionPane.showMessageDialog(this, "You need to enter your script.", "Data Needed",
JOptionPane.INFORMATION_MESSAGE);
} else {
try {
Map<String, Object> inputs = new HashMap<String, Object>();
inputs.put("script", tankScript);
runner.runScript(text,
((ConfiguredLanguage) languageSelector.getSelectedItem()).getEngine(), inputs, output);
} catch (ScriptException e) {
output.append("Error executing script:\n");
output.append(e.getMessage() + "\n");
JOptionPane
.showMessageDialog(this, e.getMessage(), "Error executing Script", JOptionPane.ERROR_MESSAGE);
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
try {
System.setProperty("jsse.enableSNIExtension", "false");
} catch (Throwable e1) {
System.err.println("Error setting property " + e1);
e1.printStackTrace();
}
String url = "http://localhost:8080/";
if (args.length > 0) {
url = args[0];
}
new ScriptFilterRunner(true, url).setVisible(true);
}
}