diff --git a/docs/src/reference/docbook/images/shell-arch-overview.png b/docs/src/reference/docbook/images/shell-arch-overview.png new file mode 100644 index 00000000..5b7f791e Binary files /dev/null and b/docs/src/reference/docbook/images/shell-arch-overview.png differ diff --git a/docs/src/reference/docbook/reference/dev-guide/dev-spring-shell.xml b/docs/src/reference/docbook/reference/dev-guide/dev-spring-shell.xml index 34e6922e..1ac18fde 100644 --- a/docs/src/reference/docbook/reference/dev-guide/dev-spring-shell.xml +++ b/docs/src/reference/docbook/reference/dev-guide/dev-spring-shell.xml @@ -9,18 +9,19 @@ xmlns:ns="http://docbook.org/ns/docbook"> Developing Spring Shell Applications - The commands are - - - - - - + Contributing commands to the shell is very easy. There are only a few + annotations you need to learn. The implementation style of the command is in + the style of developing an application that uses dependency injection as you + can leverage all the features of the Spring container.
Marker Interface - The marker interface.... + The first step to creating a command is to implement the market + interface CommandMarker and to annotate your class with Spring's + @Component annotation. (Note there is an open JIRA issue to provide a + @CliCommand meta-annotation to avoid having to use a market interface) + Taking the
diff --git a/docs/src/reference/docbook/reference/introduction.xml b/docs/src/reference/docbook/reference/introduction.xml index 825f2b95..b9552d18 100644 --- a/docs/src/reference/docbook/reference/introduction.xml +++ b/docs/src/reference/docbook/reference/introduction.xml @@ -2,6 +2,6 @@ Document structure - This part of the reference documentation explains the core componets + This part of the reference documentation explains the core components of the Spring Shell. diff --git a/docs/src/reference/docbook/reference/shell.xml b/docs/src/reference/docbook/reference/shell.xml index 81558b7a..bbae8319 100644 --- a/docs/src/reference/docbook/reference/shell.xml +++ b/docs/src/reference/docbook/reference/shell.xml @@ -22,15 +22,30 @@ started. The essential boostrapping code that looks for your contributions looks like thisnew ClassPathXmlApplicationContext("classpath*:/META-INF/spring/spring-shell-plugin.xml"); - In the spring-shell-plugin.xml file you should - declare the commands and any collaboration objects that support the - commands actions. An easy way to declare the commands is to use Spring's - component scanning functionality. + In the spring-shell-plugin.xml file you should + define the command classes and any other collaboration objects that + support the commands actions. The plugin model is depicted in the + following diagram - Here is an example spring-shell-plugin.xml that - from the sample application. + + + + + - <beans xmlns="http://www.springframework.org/schema/beans" + Note that the current plugin model loads all plugins under the same + class loader. An open JIRA issus is to provide a classloader per plugin to + provide isolation. + +
+ Commands + + An easy way to declare the commands is to use Spring's component + scanning functionality.Here is an example + spring-shell-plugin.xml that from the sample + application. + + <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd @@ -40,25 +55,26 @@ </beans> - The commands are Spring components, demarcated as such using the - @Component annotation. For example, the - HelloWorldCommands class from the sample - application looks like this + The commands are Spring components, demarcated as such using the + @Component annotation. For example, the + HelloWorldCommands class from the sample + application looks like this - @Component + @Component public class HelloWorldCommands implements CommandMarker { - // methods with @Cli annotations go here - // use any Spring annotations for Dependency Injection or other Spring interfaces as required. + // methods with @Cli annotations go here + } - One the commands are registered and instantiated by the Spring - container, they are registered with the core shell parser so that the - @Cli annotationscan be processed. The way the commands - are identified is through the use of the - CommandMarker interface. + One the commands are registered and instantiated by the Spring + container, they are registered with the core shell parser so that the + @Cli annotations can be processed. The way the + commands are identified is through the use of the + CommandMarker interface. +
Converters @@ -67,7 +83,7 @@ public class HelloWorldCommands implements CommandMarker { org.springframework.shell.core.Converter interface provides the contract to convert the strings that are entered in the command to rich Java types passed into the arguments of - @Cli-annotated methods. + @Cli-annotated methods. By default converters for common types are registered. These cover primitive types (boolean, int, float...) as well as Date, Character, and @@ -106,7 +122,94 @@ public class HelloWorldCommands implements CommandMarker { executed. +
- +
+ Customizing the shell + + There are a few extension points that allow you to customize the + shell. The extension points are the interfaces + + + + BannerProvider - Specifies the + banner text , welcome message, and version number that will be + displayed when the shell is started + + + + PromptProvider - Specifies the + command prompt text + + + + HistoryFileNameProvider - + Specifies the name of the command history file + + + + There is a default implementation for these interfaces but you + should create your own implementations for your own shell application. Use + Spring's @Ordered annotation to set the priority of the + provider. This allows your provider implementations to take precidence + over any other implementations that maybe present on the classpath from + other plugins. + + To make cool "ASCII art" + banners the website http://patorjk.com/software/taag + is quite neat! +
+ +
+ Communicating between plugins + + As this is a standard Spring application you can use Spring's + ApplicationContext event infrastructure to communicate across + plugins. +
+ +
+ Command method interception + + It has shown to be useful to provide a simple form of interception + around the invocation of a command method. This enables the command class + to check for updates to state, such as configuration information modified + by other plugins, before the command is executed. The interface + ExecutionProcess should be implemented + instead of CommandMarker to access this + functionlatiy. The ExecutionProcess + interface is shown below + + public interface ExecutionProcessor extends CommandMarker { + + /** + * Method called before invoking the target command (described by {@link ParseResult}). + * Additionally, for advanced cases, the parse result itself effectively changing the invocation + * calling site. + * + * @param invocationContext target command context + * @return the invocation target + */ + ParseResult beforeInvocation(ParseResult invocationContext); + + /** + * Method called after successfully invoking the target command (described by {@link ParseResult}). + * + * @param invocationContext target command context + * @param result the invocation result + */ + void afterReturningInvocation(ParseResult invocationContext, Object result); + + /** + * Method called after invoking the target command (described by {@link ParseResult}) had thrown an exception . + * + * @param invocationContext target command context + * @param thrown the thrown object + */ + void afterThrowingInvocation(ParseResult invocationContext, Throwable thrown); + +}
diff --git a/src/main/java/org/springframework/shell/plugin/BannerProvider.java b/src/main/java/org/springframework/shell/plugin/BannerProvider.java index a1c3c400..39d17248 100644 --- a/src/main/java/org/springframework/shell/plugin/BannerProvider.java +++ b/src/main/java/org/springframework/shell/plugin/BannerProvider.java @@ -16,9 +16,11 @@ package org.springframework.shell.plugin; + /** - * Banner provider. Plugin should implement this interface to replace the version banner. - * getOrder indicate the priority, higher values can be interpreted as lower priority + * Banner provider. Plugins should implement this interface to replace the version banner. + * Use the @Order annotation to specify the priority of the banner to be display, higher + * values can be interpreted as lower priority * * @author Jarred Li * @since 1.0