SHL92 - Decoupling the script command from AbstractShell

Thanks to trumpetx
c0abfa0454
This commit is contained in:
mpollack
2013-07-25 19:11:46 -04:00
parent 612da3bda1
commit e9f3de10cb
4 changed files with 137 additions and 140 deletions

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.shell.commands;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.JLineShellComponent;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.shell.support.logging.HandlerUtils;
import org.springframework.shell.support.util.IOUtils;
import org.springframework.shell.support.util.MathUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
@Component
public class ScriptCommands implements CommandMarker {
protected final Logger logger = HandlerUtils.getLogger(getClass());
@Autowired
private ApplicationContext applicationContext;
@Autowired
private JLineShellComponent shell;
@CliCommand(value = { "script" }, help = "Parses the specified resource file and executes its commands")
public void script(
@CliOption(key = { "", "file" }, help = "The file to locate and execute", mandatory = true) final File script,
@CliOption(key = "lineNumbers", mandatory = false, specifiedDefaultValue = "true", unspecifiedDefaultValue = "false", help = "Display line numbers when executing the script") final boolean lineNumbers) {
Assert.notNull(script, "Script file to parse is required");
double startedNanoseconds = System.nanoTime();
final InputStream inputStream = openScript(script);
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(inputStream));
String line;
int i = 0;
while ((line = in.readLine()) != null) {
i++;
if (lineNumbers) {
logger.fine("Line " + i + ": " + line);
} else {
logger.fine(line);
}
if (!"".equals(line.trim())) {
boolean success = shell.executeScriptLine(line);
if (success && ((line.trim().startsWith("q") || line.trim().startsWith("ex")))) {
break;
} else if (!success) {
// Abort script processing, given something went wrong
throw new IllegalStateException("Script execution aborted");
}
}
}
} catch (IOException e) {
throw new IllegalStateException(e);
} finally {
IOUtils.closeQuietly(inputStream, in);
double executionDurationInSeconds = (System.nanoTime() - startedNanoseconds) / 1000000000D;
logger.fine("Script required " + MathUtils.round(executionDurationInSeconds, 3) + " seconds to execute");
}
}
/**
* Opens the given script for reading
*
* @param script the script to read (required)
* @return a non-<code>null</code> input stream
*/
private InputStream openScript(final File script) {
try {
return new BufferedInputStream(new FileInputStream(script));
} catch (final FileNotFoundException fnfe) {
// Try to find the script via the classloader
final Collection<URL> urls = findResources(script.getName());
// Handle search failure
Assert.notNull(urls, "Unexpected error looking for '" + script.getName() + "'");
// Handle the search being OK but the file simply not being present
Assert.notEmpty(urls, "Script '" + script + "' not found on disk or in classpath");
Assert.isTrue(urls.size() == 1, "More than one '" + script + "' was found in the classpath; unable to continue");
try {
return urls.iterator().next().openStream();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
protected Collection<URL> findResources(final String path) {
try {
Resource[] resources = applicationContext.getResources(path);
Collection<URL> list = new ArrayList<URL>(resources.length);
for (Resource resource : resources) {
list.add(resource.getURL());
}
return list;
} catch (IOException ex) {
logger.fine("Cannot find path " + path);
// return Collections.emptyList();
throw new RuntimeException(ex);
}
}
}

View File

@@ -15,28 +15,16 @@
*/
package org.springframework.shell.core;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.shell.event.AbstractShellStatusPublisher;
import org.springframework.shell.event.ParseResult;
import org.springframework.shell.event.ShellStatus;
import org.springframework.shell.event.ShellStatus.Status;
import org.springframework.shell.support.logging.HandlerUtils;
import org.springframework.shell.support.util.IOUtils;
import org.springframework.shell.support.util.MathUtils;
import org.springframework.shell.support.util.VersionUtils;
import org.springframework.util.Assert;
@@ -63,94 +51,19 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
protected boolean inBlockComment;
protected ExitShellRequest exitShellRequest;
/**
* Returns any classpath resources with the given path
*
* @param path the path for which to search (never null)
* @return <code>null</code> if the search can't be performed
* @since 1.2.0
*/
protected abstract Collection<URL> findResources(String path);
protected abstract String getHomeAsString();
protected abstract ExecutionStrategy getExecutionStrategy();
protected abstract Parser getParser();
@CliCommand(value = { "script" }, help = "Parses the specified resource file and executes its commands")
public void script(
@CliOption(key = { "", "file" }, help = "The file to locate and execute", mandatory = true) final File script,
@CliOption(key = "lineNumbers", mandatory = false, specifiedDefaultValue = "true", unspecifiedDefaultValue = "false", help = "Display line numbers when executing the script") final boolean lineNumbers) {
Assert.notNull(script, "Script file to parse is required");
double startedNanoseconds = System.nanoTime();
final InputStream inputStream = openScript(script);
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(inputStream));
String line;
int i = 0;
while ((line = in.readLine()) != null) {
i++;
if (lineNumbers) {
logger.fine("Line " + i + ": " + line);
} else {
logger.fine(line);
}
if (!"".equals(line.trim())) {
boolean success = executeScriptLine(line);
if (success && ((line.trim().startsWith("q") || line.trim().startsWith("ex")))) {
break;
} else if (!success) {
// Abort script processing, given something went wrong
throw new IllegalStateException("Script execution aborted");
}
}
}
} catch (IOException e) {
throw new IllegalStateException(e);
} finally {
IOUtils.closeQuietly(inputStream, in);
double executionDurationInSeconds = (System.nanoTime() - startedNanoseconds) / 1000000000D;
logger.fine("Script required " + MathUtils.round(executionDurationInSeconds, 3) + " seconds to execute");
}
}
/**
* Opens the given script for reading
*
* @param script the script to read (required)
* @return a non-<code>null</code> input stream
*/
private InputStream openScript(final File script) {
try {
return new BufferedInputStream(new FileInputStream(script));
} catch (final FileNotFoundException fnfe) {
// Try to find the script via the classloader
final Collection<URL> urls = findResources(script.getName());
// Handle search failure
Assert.notNull(urls, "Unexpected error looking for '" + script.getName() + "'");
// Handle the search being OK but the file simply not being present
Assert.notEmpty(urls, "Script '" + script + "' not found on disk or in classpath");
Assert.isTrue(urls.size() == 1, "More than one '" + script + "' was found in the classpath; unable to continue");
try {
return urls.iterator().next().openStream();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
/**
* Execute the single line from a script.
* <p>
* This method can be overridden by sub-classes to pre-process script lines.
*/
protected boolean executeScriptLine(final String line) {
public boolean executeScriptLine(final String line) {
return executeCommand(line).isSuccess();
}
@@ -304,8 +217,6 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
return exitShellRequest;
}
@CliCommand(value = { "/*" }, help = "Start of block comment")
public void blockCommentBegin() {
Assert.isTrue(!inBlockComment, "Cannot open a new block comment when one already active");
@@ -318,31 +229,6 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
inBlockComment = false;
}
//@CliCommand(value = { "flash test" }, help = "Tests message flashing")
public void flashCustom() throws Exception {
flash(Level.FINE, "Hello world", "a");
Thread.sleep(150);
flash(Level.FINE, "Short world", "a");
Thread.sleep(150);
flash(Level.FINE, "Small", "a");
Thread.sleep(150);
flash(Level.FINE, "Downloading xyz", "b");
Thread.sleep(150);
flash(Level.FINE, "", "a");
Thread.sleep(150);
flash(Level.FINE, "Downloaded xyz", "b");
Thread.sleep(150);
flash(Level.FINE, "System online", "c");
Thread.sleep(150);
flash(Level.FINE, "System ready", "c");
Thread.sleep(150);
flash(Level.FINE, "System farewell", "c");
Thread.sleep(150);
flash(Level.FINE, "", "c");
Thread.sleep(150);
flash(Level.FINE, "", "b");
}
public String versionInfo(){
return VersionUtils.versionInfo();
}

View File

@@ -68,7 +68,7 @@ import org.springframework.util.StringUtils;
* @author Jarred Li
* @since 1.0
*/
public abstract class JLineShell extends AbstractShell implements CommandMarker, Shell, Runnable {
public abstract class JLineShell extends AbstractShell implements Shell, Runnable {
// Constants
private static final String ANSI_CONSOLE_CLASSNAME = "org.fusesource.jansi.AnsiConsole";

View File

@@ -15,15 +15,10 @@
*/
package org.springframework.shell.core;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
@@ -31,16 +26,13 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.Resource;
import org.springframework.shell.CommandLine;
import org.springframework.shell.plugin.BannerProvider;
import org.springframework.shell.plugin.HistoryFileNameProvider;
import org.springframework.shell.plugin.NamedProvider;
import org.springframework.shell.plugin.PromptProvider;
import org.springframework.shell.support.logging.HandlerUtils;
/**
* Launcher for {@link JLineShell}.
@@ -138,22 +130,6 @@ public class JLineShellComponent extends JLineShell implements SmartLifecycle, A
}
}
@Override
protected Collection<URL> findResources(final String path) {
try {
Resource[] resources = applicationContext.getResources(path);
Collection<URL> list = new ArrayList<URL>(resources.length);
for (Resource resource : resources) {
list.add(resource.getURL());
}
return list;
} catch (IOException ex) {
logger.fine("Cannot find path " + path);
// return Collections.emptyList();
throw new RuntimeException(ex);
}
}
@Override
protected ExecutionStrategy getExecutionStrategy() {
return executionStrategy;