/*
* JBoss, Home of Professional Open Source
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.jboss.as.cli.gui.metacommand;
import java.awt.event.ActionEvent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import org.jboss.as.cli.gui.CliGuiContext;
import org.jboss.as.cli.gui.component.CLIOutput;
import org.jboss.as.cli.gui.component.ScriptMenu;
/**
* Abstract action that runs scripts.
*
* @author ssilvert
*/
public abstract class ScriptAction extends AbstractAction {
protected CliGuiContext cliGuiCtx;
private CLIOutput output;
private ScriptMenu menu;
public ScriptAction(ScriptMenu menu, String name, CliGuiContext cliGuiCtx) {
super(name);
this.cliGuiCtx = cliGuiCtx;
this.menu = menu;
output = cliGuiCtx.getOutput();
}
/**
* Subclasses should override this method and then call runScript() when a script File
* is determined.
*/
public abstract void actionPerformed(ActionEvent e);
/**
* Run a CLI script from a File.
*
* @param script The script file.
*/
protected void runScript(File script) {
if (!script.exists()) {
JOptionPane.showMessageDialog(cliGuiCtx.getMainPanel(), script.getAbsolutePath() + " does not exist.",
"Unable to run script.", JOptionPane.ERROR_MESSAGE);
return;
}
int choice = JOptionPane.showConfirmDialog(cliGuiCtx.getMainPanel(), "Run CLI script " + script.getName() + "?",
"Confirm run script", JOptionPane.YES_NO_OPTION);
if (choice != JOptionPane.YES_OPTION) return;
menu.addScript(script);
cliGuiCtx.getTabs().setSelectedIndex(1); // set to Output tab to view the output
output.post("\n");
SwingWorker scriptRunner = new ScriptRunner(script);
scriptRunner.execute();
}
// read the file as a list of text lines
private List<String> getCommandLines(File file) {
try {
return Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new IllegalStateException("Failed to process file " + file.getAbsolutePath(), e);
}
}
// We need this class because we have to pass on whether or not a
// message should be displayed in bold or not.
private class OutMessage {
private boolean isBold;
private String message;
OutMessage(String message, boolean isBold) {
this.message = message;
this.isBold = isBold;
}
}
/**
* Use a SwingWorker to run the script in the background. Some commands such as deploy can take a long time,
* so they can tie up the event dispatch thread and freeze the UI.
*/
protected class ScriptRunner extends SwingWorker<Object, OutMessage> {
private File file;
private int caretPosition = 0;
private ScriptRunner(File file) {
this.file = file;
}
@Override
protected Object doInBackground() throws Exception {
ByteArrayOutputStream scriptOut = new ByteArrayOutputStream();
PrintStream printOut = new PrintStream(scriptOut);
// We capture the output stream from System.out so we can give the user feedback
// that comes from core CLI. The publish() method allows us to send messages
// to the event dispatch thread safely and in order.
try {
cliGuiCtx.getCommmandContext().captureOutput(printOut);
cliGuiCtx.getCommandLine().setEnabled(false);
publish(new OutMessage(">>> Execute CLI script " + file, true));
boolean failure = false;
for (String command : getCommandLines(file)) {
publish(new OutMessage(command, true));
try {
cliGuiCtx.getCommmandContext().handle(command.trim());
} catch (Throwable t) {
t.printStackTrace(printOut);
failure = true;
}
if (scriptOut.size() > 0) {
publish(new OutMessage(scriptOut.toString(), false));
scriptOut.reset();
}
if (failure) {
publish(new OutMessage(">> Command Failed: " + command, true));
break;
}
}
publish(new OutMessage(">>> Script complete.", true));
} finally {
cliGuiCtx.getCommmandContext().releaseOutput();
cliGuiCtx.getCommandLine().setEnabled(true);
cliGuiCtx.getCommmandContext().handle("cd /"); // reset to root directory
}
return null;
}
@Override
protected void process(List<OutMessage> messages) {
// output messages on the event dispatch thread
for (OutMessage msg : messages) {
if (msg.isBold) {
caretPosition = output.postBoldAt(msg.message + "\n", caretPosition);
} else {
caretPosition = output.postAt(msg.message + "\n", caretPosition);
}
}
}
}
}