From e9f3de10cbff3a0ec78254cc7eaf546147d612f9 Mon Sep 17 00:00:00 2001 From: mpollack Date: Thu, 25 Jul 2013 19:11:46 -0400 Subject: [PATCH] SHL92 - Decoupling the script command from AbstractShell Thanks to trumpetx https://github.com/trumpetx/spring-shell/commit/c0abfa045477a259c290a77cfc1ba14649c534c9 --- .../shell/commands/ScriptCommands.java | 135 ++++++++++++++++++ .../shell/core/AbstractShell.java | 116 +-------------- .../shell/core/JLineShell.java | 2 +- .../shell/core/JLineShellComponent.java | 24 ---- 4 files changed, 137 insertions(+), 140 deletions(-) create mode 100644 src/main/java/org/springframework/shell/commands/ScriptCommands.java diff --git a/src/main/java/org/springframework/shell/commands/ScriptCommands.java b/src/main/java/org/springframework/shell/commands/ScriptCommands.java new file mode 100644 index 00000000..439ae4ac --- /dev/null +++ b/src/main/java/org/springframework/shell/commands/ScriptCommands.java @@ -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-null 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 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 findResources(final String path) { + try { + Resource[] resources = applicationContext.getResources(path); + Collection list = new ArrayList(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); + } + } + +} diff --git a/src/main/java/org/springframework/shell/core/AbstractShell.java b/src/main/java/org/springframework/shell/core/AbstractShell.java index 12463c8f..c99f0cbc 100644 --- a/src/main/java/org/springframework/shell/core/AbstractShell.java +++ b/src/main/java/org/springframework/shell/core/AbstractShell.java @@ -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 null if the search can't be performed - * @since 1.2.0 - */ - protected abstract Collection 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-null 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 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. *

* 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(); } diff --git a/src/main/java/org/springframework/shell/core/JLineShell.java b/src/main/java/org/springframework/shell/core/JLineShell.java index e0ac9974..709f914d 100644 --- a/src/main/java/org/springframework/shell/core/JLineShell.java +++ b/src/main/java/org/springframework/shell/core/JLineShell.java @@ -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"; diff --git a/src/main/java/org/springframework/shell/core/JLineShellComponent.java b/src/main/java/org/springframework/shell/core/JLineShellComponent.java index 7296a720..d2e5a544 100644 --- a/src/main/java/org/springframework/shell/core/JLineShellComponent.java +++ b/src/main/java/org/springframework/shell/core/JLineShellComponent.java @@ -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 findResources(final String path) { - try { - Resource[] resources = applicationContext.getResources(path); - Collection list = new ArrayList(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;