Remove everything prior to Shell 2 migration
This commit is contained in:
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,17 +0,0 @@
|
||||
/.classpath
|
||||
/.project
|
||||
.settings/
|
||||
.gradle
|
||||
build
|
||||
target/
|
||||
/log.roo
|
||||
|
||||
/bin/
|
||||
/*.log
|
||||
|
||||
/.idea
|
||||
/*.iml
|
||||
/*.ipr
|
||||
/*.iws
|
||||
out
|
||||
.gradletasknamecache
|
||||
14
.springBeans
14
.springBeans
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.8.1.201111220115-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
<enableImports><![CDATA[false]]></enableImports>
|
||||
<configs>
|
||||
<config>src/test/resources/META-INF/spring/spring-shell-plugin.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
</configSets>
|
||||
</beansProjectDescription>
|
||||
@@ -1,88 +0,0 @@
|
||||
:currentReleaseVersion: 1.1.0.RELEASE
|
||||
:currentSnapshotVersion: 1.2.0.BUILD-SNAPSHOT
|
||||
|
||||
Spring Shell is an shell skeleton that can be easily extended with commands using a Spring based programming model. Spring Shell eases the creation of interactive console applications, featuring ANSI coloring, TAB completion, history browsing, _etc._
|
||||
|
||||
To witness possibilities of Spring Shell, have a look at the http://docs.spring.io/spring-xd/docs/current-SNAPSHOT/reference/html/#interactive-shell[Spring XD Shell].
|
||||
|
||||
The latest release version is {currentReleaseVersion}, while the development version is {currentSnapshotVersion}.
|
||||
|
||||
# Useful links
|
||||
|
||||
* http://static.springsource.org/spring-shell/docs/current/reference/[User documentation]
|
||||
* https://jira.spring.io/browse/SHL[Issue Tracker]
|
||||
|
||||
# Artifacts
|
||||
|
||||
[filter=source,language=xml,subs="attributes,specialcharacters"]
|
||||
----
|
||||
<!-- used for Spring GA Releases releases, artifacts are also in maven central -->
|
||||
<repository>
|
||||
<!-- Release -->
|
||||
<id>spring-release</id>
|
||||
<name>Spring Maven RELEASE Repository</name>
|
||||
<url>http://repo.springframework.org/release</url>
|
||||
</repository>
|
||||
|
||||
<!-- libs-release artifacts that may not be in maven central -->
|
||||
<repository>
|
||||
<id>libs-release</id>
|
||||
<name>Spring Maven libs-release Repository</name>
|
||||
<url>http://repo.springframework.org/libs-release</url>
|
||||
</repository>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell</artifactId>
|
||||
<version>{currentReleaseVersion}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- used for nightly builds -->
|
||||
<repository>
|
||||
<!-- Snapshots -->
|
||||
<id>spring-snapshot</id>
|
||||
<name>Spring Maven SNAPSHOT Repository</name>
|
||||
<url>http://repo.springframework.org/libs-snapshot</url>
|
||||
</repository>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell</artifactId>
|
||||
<version>{currentSnapshotVersion}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
|
||||
* Gradle:
|
||||
|
||||
[subs="attributes,specialcharacters"]
|
||||
----
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/lib-release" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.springframework.shell:spring-shell:{currentReleaseVersion}"
|
||||
}
|
||||
----
|
||||
|
||||
# Building
|
||||
Spring Shell is built with Gradle. To build Spring Shell, run
|
||||
|
||||
./gradlew
|
||||
|
||||
# Running Example
|
||||
|
||||
cd samples/helloworld
|
||||
./gradlew installApp
|
||||
cd build/install/helloworld/bin
|
||||
helloworld
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
Here are some ways for you to get involved in the community:
|
||||
|
||||
* Get involved with the Spring community on Stack Overflow. Please help out on the http://stackoverflow.com/questions/tagged/spring-shell[dedicated SO tag] by responding to questions and joining the debate.
|
||||
* Create https://jira.spring.io/browse/SHL[JIRA] tickets for bugs and new features and comment and vote on the ones that you are interested in.
|
||||
Github is for social coding: if you want to write code, we encourage contributions through pull requests from http://help.github.com/forking/[forks of this repository]. If you want to contribute code this way, please reference a JIRA tracker ticket covering the specific issue you are addressing. Before we accept a non-trivial patch or pull request we will need you to sign the https://support.springsource.com/spring_committer_signup[contributor's agreement]. Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.
|
||||
220
build.gradle
220
build.gradle
@@ -1,220 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url 'http://repo.springsource.org/plugins-release' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'io.spring.gradle:docbook-reference-plugin:0.3.1'
|
||||
classpath 'org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE'
|
||||
}
|
||||
}
|
||||
|
||||
description = 'Spring Shell'
|
||||
group = 'org.springframework.shell'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "http://repo.springsource.org/libs-snapshot" }
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
}
|
||||
|
||||
apply plugin: "java"
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
apply from: "$rootDir/maven.gradle"
|
||||
apply plugin: 'docbook-reference'
|
||||
apply plugin: 'application'
|
||||
|
||||
if (project.hasProperty('platformVersion')) {
|
||||
apply plugin: 'spring-io'
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-snapshot" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
springIoVersions "io.spring.platform:platform-versions:${platformVersion}@properties"
|
||||
}
|
||||
}
|
||||
|
||||
[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial", "-Xlint:unchecked", "-Xlint:rawtypes"]
|
||||
|
||||
[compileJava, compileTestJava]*.options*.encoding = "UTF-8"
|
||||
|
||||
dependencies {
|
||||
compile "org.springframework:spring-core:$springVersion"
|
||||
compile "org.springframework:spring-context-support:$springVersion"
|
||||
compile "commons-io:commons-io:$commonsioVersion"
|
||||
compile "jline:jline:$jlineVersion"
|
||||
|
||||
|
||||
// Testing
|
||||
testCompile "junit:junit:$junitVersion"
|
||||
testCompile "org.mockito:mockito-core:$mockitoVersion"
|
||||
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
|
||||
javadoc {
|
||||
ext.srcDir = file("${projectDir}/docs/src/api")
|
||||
destinationDir = file("${buildDir}/api")
|
||||
ext.tmpDir = file("${buildDir}/api-work")
|
||||
|
||||
configure(options) {
|
||||
encoding = "UTF-8"
|
||||
stylesheetFile = file("${srcDir}/spring-javadoc.css")
|
||||
overview = "${srcDir}/overview.html"
|
||||
docFilesSubDirs = true
|
||||
outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
|
||||
breakIterator = true
|
||||
showFromProtected()
|
||||
groups = [
|
||||
'Spring Shell' : ['org.springframework.shell*'],
|
||||
]
|
||||
|
||||
links = [
|
||||
"http://static.springframework.org/spring/docs/3.1.x/javadoc-api",
|
||||
"http://download.oracle.com/javase/6/docs/api",
|
||||
]
|
||||
|
||||
//exclude "org/springframework/data/redis/config/**"
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
}
|
||||
|
||||
title = "${rootProject.description} ${version} API"
|
||||
}
|
||||
|
||||
|
||||
jar {
|
||||
manifest.attributes['Implementation-Title'] = 'spring-shell'
|
||||
manifest.attributes['Implementation-Version'] = project.version
|
||||
|
||||
from("$rootDir/docs/src/info") {
|
||||
include "license.txt"
|
||||
include "notice.txt"
|
||||
into "META-INF"
|
||||
expand(copyright: new Date().format('yyyy'), version: project.version)
|
||||
}
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn:classes) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allJava
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc
|
||||
}
|
||||
|
||||
reference {
|
||||
sourceDir = file('docs/src/reference/docbook')
|
||||
}
|
||||
|
||||
|
||||
task docsZip(type: Zip) {
|
||||
group = 'Distribution'
|
||||
classifier = 'docs'
|
||||
description = "Builds -${classifier} archive containing api and reference for deployment"
|
||||
|
||||
from('docs/src/info') {
|
||||
include 'changelog.txt'
|
||||
}
|
||||
|
||||
from (javadoc) {
|
||||
into 'api'
|
||||
}
|
||||
|
||||
from (reference) {
|
||||
into 'reference'
|
||||
}
|
||||
}
|
||||
|
||||
task schemaZip(type: Zip) {
|
||||
group = 'Distribution'
|
||||
classifier = 'schema'
|
||||
description = "Builds -${classifier} archive containing all XSDs for deployment"
|
||||
|
||||
def Properties schemas = new Properties();
|
||||
|
||||
sourceSets.main.resources.find {
|
||||
it.path.endsWith('META-INF' + File.separator + 'spring.schemas')
|
||||
}?.withInputStream { schemas.load(it) }
|
||||
|
||||
ext.paths = [] as Set
|
||||
|
||||
for (def key : schemas.keySet()) {
|
||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||
assert shortName != key
|
||||
File xsdFile = sourceSets.main.resources.find {
|
||||
it.path.replace('\\', '/').endsWith(schemas.get(key))
|
||||
}
|
||||
assert xsdFile != null
|
||||
def input = xsdFile.path
|
||||
|
||||
if (!paths.contains(input)) {
|
||||
paths.add(input)
|
||||
into (shortName) {
|
||||
from input
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task distroZip(type: Zip, dependsOn: [jar, docsZip, sourcesJar, javadocJar]) {
|
||||
group = 'Distribution'
|
||||
classifier = 'dist'
|
||||
description = "Builds -${classifier} archive, containing all jars and docs, " +
|
||||
"suitable for community download page."
|
||||
|
||||
ext.zipRootDir = "${project.name}-${project.version}"
|
||||
|
||||
into (zipRootDir) {
|
||||
from('docs/src/info') {
|
||||
include 'readme.txt'
|
||||
include 'license.txt'
|
||||
include 'notice.txt'
|
||||
expand(copyright: new Date().format('yyyy'), version: project.version)
|
||||
}
|
||||
|
||||
from('samples/') {
|
||||
into 'samples'
|
||||
exclude '.gradle/'
|
||||
exclude 'build/'
|
||||
}
|
||||
|
||||
from(zipTree(docsZip.archivePath)) {
|
||||
into "docs"
|
||||
}
|
||||
|
||||
// from(zipTree(schemaZip.archivePath)) {
|
||||
// into "schema"
|
||||
// }
|
||||
into ("dist") {
|
||||
from rootProject.collect { project -> project.libsDir }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar
|
||||
archives javadocJar
|
||||
|
||||
archives docsZip
|
||||
// archives schemaZip
|
||||
archives distroZip
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = 'Generates gradlew[.bat] scripts'
|
||||
gradleVersion = '2.10'
|
||||
}
|
||||
|
||||
|
||||
mainClassName = "org.springframework.shell.Bootstrap"
|
||||
|
||||
assemble.dependsOn = ['jar', 'sourcesJar']
|
||||
defaultTasks 'build'
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,24 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This document is the API specification for the Spring Shell project.
|
||||
<hr/>
|
||||
|
||||
<div id="overviewBody">
|
||||
<!--
|
||||
<p>
|
||||
For further API reference and developer documentation, see the
|
||||
<a href="http://static.springframework.org/spring/docs/2.0.x/reference/index.html" target="_top">Spring Framework reference documentation</a>.
|
||||
That documentation contains more detailed, developer-targeted
|
||||
descriptions, with conceptual overviews, definitions of terms,
|
||||
workarounds, and working code examples.
|
||||
</p>
|
||||
-->
|
||||
<p>
|
||||
If you are interested in commercial training, consultancy and
|
||||
support for the Spring Shell project,
|
||||
<a href="http://www.SpringSource.com/" target="_top">SpringSource</a> provides
|
||||
such commercial support.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
/* Spring-specific Javadoc style sheet rules */
|
||||
|
||||
#overviewBody {
|
||||
|
||||
}
|
||||
|
||||
.code {
|
||||
border: 1px solid black;
|
||||
background-color: #F4F4F4;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* Vanilla Javadoc style sheet rules */
|
||||
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
background-color: white;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
td { font-size: 10pt; font-family: Helvetica, Arial, sans-serif }/* Javadoc style sheet */
|
||||
|
||||
/* Define colors, fonts and other style attributes here to override the defaults */
|
||||
|
||||
/* Page background color */
|
||||
body { background-color: #FFFFFF }
|
||||
|
||||
/* Headings */
|
||||
h1 { font-size: 145% }
|
||||
|
||||
/* Table colors */
|
||||
.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
|
||||
.TableSubHeadingColor { background: #EEEEFF } /* Light mauve */
|
||||
.TableRowColor { background: #FFFFFF } /* White */
|
||||
|
||||
/* Font used in left-hand frame lists */
|
||||
.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif }
|
||||
.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif }
|
||||
.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif }
|
||||
|
||||
/* Navigation bar fonts and colors */
|
||||
.NavBarCell1 { background-color:#EEEEFF;} /* Light mauve */
|
||||
.NavBarCell1Rev { background-color:#00008B;} /* Dark Blue */
|
||||
.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}
|
||||
.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}
|
||||
|
||||
.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
|
||||
.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
|
||||
@@ -1,175 +0,0 @@
|
||||
SPRING SHELL CHANGELOG
|
||||
======================
|
||||
http://www.springsource.org/spring-shell
|
||||
|
||||
Commit changelog: http://github.com/SpringSource/spring-shell/tree/[version]
|
||||
Issues changelog: http://jira.springsource.org/secure/ReleaseNote.jspa?projectId=10361
|
||||
|
||||
Changes in version 1.1.0 RELEASE (2014-7-25)
|
||||
-------------------------------------
|
||||
|
||||
No changes
|
||||
|
||||
Changes in version 1.1 RC4 (2014-7-8)
|
||||
-------------------------------------
|
||||
** Bug
|
||||
* [SHL-138] - Support unquoted doublequotes inside singles, and vice versa
|
||||
* [SHL-140] - Fix completions for the "help" builtin command
|
||||
* [SHL-153] - Date command should assume user localization.
|
||||
|
||||
** Improvement
|
||||
* [SHL-136] - Shell should indicate error location with a caret when possible
|
||||
* [SHL-155] - Expose number of times the TAB key has been hit in completion
|
||||
|
||||
** Task
|
||||
* [SHL-154] - Update DateCommand test
|
||||
|
||||
|
||||
Changes in version 1.1 RC3 (2014-5-16)
|
||||
--------------------------------------
|
||||
** Bug
|
||||
* [SHL-140] - Fix completions for the "help" builtin command
|
||||
|
||||
** Improvement
|
||||
* [SHL-134] - Grab the entire input line as parameter to CliCommand
|
||||
* [SHL-139] - Add support for common escapes
|
||||
* [SHL-143] - Upgrade to gradle 1.11
|
||||
* [SHL-149] - Upgrad to Spring Framework 4
|
||||
|
||||
Changes in version 1.1 RC2 (2014-4-15)
|
||||
--------------------------------------
|
||||
** Bug
|
||||
* [SHL-133] - Shell command "! ls /tmp" fails
|
||||
* [SHL-135] - Key-less option corner case
|
||||
|
||||
Changes in version 1.1 RC1 (2014-4-2)
|
||||
-------------------------------------
|
||||
|
||||
** Bug
|
||||
* [SHL-84] - Shell cannot deal with "-" in CliOption keys
|
||||
* [SHL-85] - Argument completion broken when default value present
|
||||
* [SHL-107] - Prompt not re-evaluated if the user input is just an "enter" command.
|
||||
* [SHL-116] - Support quotes escaping
|
||||
* [SHL-119] - Remove unused bright color constants
|
||||
* [SHL-120] - Add @Inherited and @Documented to the annotations
|
||||
* [SHL-122] - --key --foo thinks "--foo" is a value, even if --key has a default
|
||||
|
||||
** Improvement
|
||||
* [SHL-74] - Switch JLine dependency to an official JLine version
|
||||
* [SHL-80] - ability to disable built-in commands
|
||||
* [SHL-91] - Applications built with spring-shell are required to inherit comment commands
|
||||
* [SHL-125] - Some documentation fixes
|
||||
|
||||
** New Feature
|
||||
* [SHL-126] - Add utility classes for rendering ascii based tables
|
||||
|
||||
** Task
|
||||
* [SHL-118] - Rename JLineCompletorAdapter to ParserCompleter
|
||||
* [SHL-128] - Change version of spring shell in hello world application to 1.1 RC1
|
||||
* [SHL-130] - Release 1.1 RC1
|
||||
|
||||
Release Notes - Spring Shell - Version 1.1 M1
|
||||
|
||||
|
||||
Changes in version 1.1 M1 (2013-7-26)
|
||||
-------------------------------------
|
||||
|
||||
** Bug
|
||||
* [SHL-47] - Invesitgate if SimpleFileConverter should be used or incorporated in FileConverter
|
||||
* [SHL-72] - DefaultBannerProvider welcome message mentions non-existent 'hint' command
|
||||
* [SHL-87] - sample app not working anymore
|
||||
* [SHL-114] - After initial creation, the plugin's ApplicationContext is refreshed one time too often
|
||||
|
||||
|
||||
|
||||
** Improvement
|
||||
* [SHL-68] - Make help for built-in commands consistent
|
||||
* [SHL-69] - Extract "version" command from AbstractShell
|
||||
* [SHL-70] - Add a command to clear the console
|
||||
* [SHL-71] - Reference docs do not mention PluginProvider interface
|
||||
* [SHL-73] - Typo in reference docs: CliOptions iso CliOption
|
||||
* [SHL-75] - Change repository used to pull in custom jline dependency in sample application
|
||||
* [SHL-77] - Update the build to use later versions of JUnit and SLF4J
|
||||
* [SHL-78] - Add an if check in JLineShellComponent's stop method.
|
||||
* [SHL-79] - Update gradle wrapper to 1.2
|
||||
* [SHL-82] - Improve detection of apple terminal
|
||||
* [SHL-86] - Change bootstrapping procedure so JLineShellComponent can resolve its own dependencies.
|
||||
* [SHL-92] - Decoupled commands 'date' and 'system properties' from AbstractShell
|
||||
* [SHL-93] - Decouple script command from AbstractShell
|
||||
* [SHL-100] - Rename PluginProvider to NamedProvider and name() method to getProviderName()
|
||||
* [SHL-101] - Add top level ShellException
|
||||
* [SHL-102] - Remove parent/child context hierarchy
|
||||
* [SHL-104] - Remove compiler warnings
|
||||
* [SHL-105] - Add option to run helloworld example as a gradle run task
|
||||
|
||||
** New Feature
|
||||
* [SHL-66] - Plugins should have access to command line options
|
||||
* [SHL-103] - Create simple way to test the execution of shell commands
|
||||
|
||||
|
||||
Changes in version 1.0 RELEASE (2012-10-02)
|
||||
-------------------------------------------
|
||||
|
||||
** Bug
|
||||
* [SHL-62] - customized prompt doesn't works
|
||||
|
||||
|
||||
|
||||
** Improvement
|
||||
* [SHL-63] - sample moved from Maven to Gradle
|
||||
* [SHL-111] - Change prompt during running application
|
||||
|
||||
|
||||
Changes in version 1.0 RC1 (2012-09-20)
|
||||
---------------------------------------
|
||||
|
||||
** Bug
|
||||
* [SHL-14] - History from previous session is not loaded into JLine history buffer
|
||||
* [SHL-48] - Remove duplicated classes from Spring Framework and old Roo code base in util package
|
||||
* [SHL-52] - Missing Maven dependency JLine
|
||||
* [SHL-60] - Jansi terminal support not working under cygwin
|
||||
* [SHL-61] - Remove unused Hint classes
|
||||
|
||||
** Improvement
|
||||
* [SHL-53] - Documentation Corrections
|
||||
* [SHL-54] - Dynamic prompt
|
||||
* [SHL-57] - Miscellaneous documentation cleanup
|
||||
|
||||
** New Feature
|
||||
* [SHL-55] - ascii art/text should be loaded from a file
|
||||
* [SHL-56] - SHL contains a lot of duplicated classes from Spring
|
||||
|
||||
** Task
|
||||
* [SHL-51] - Correct Maven groupId
|
||||
|
||||
|
||||
Changes in version 1.0 M1 (2012-07-18)
|
||||
--------------------------------------
|
||||
|
||||
* Moved Spring Roo code into Spring Shell, removing OSGi dependency
|
||||
|
||||
** New Feature
|
||||
* [SHL-12] - Allow shell comnand prompt text to be customized by plugins
|
||||
* [SHL-13] - Allow name of history file to be customized by plugins
|
||||
* [SHL-40] - Provide an interception mechanism for the command class to intercept invocation of command methods
|
||||
|
||||
** Improvement
|
||||
* [SHL-24] - Should not ignore the optional parameter if no parameter value is set in the command
|
||||
* [SHL-31] - Move providers & ApplicationContext to JLineShellComponent from JLineShell.
|
||||
* [SHL-32] - Sub-classes of AbstractShell should be able to handle results of execution as required.
|
||||
* [SHL-39] - Remove NAPA specific environment option, replace with Spring 3.1 profile support
|
||||
* [SHL-41] - Improve error handling for command line options when staring shell
|
||||
|
||||
** Bug
|
||||
* [SHL-6] - Spring Shell does not support "help"
|
||||
* [SHL-19] - When running spring shell in the script mode, the output shout not include the Spring Shell interative information
|
||||
* [SHL-35] - Improve the parsing command line options to gracefully handle invalid values.
|
||||
|
||||
** Task
|
||||
* [SHL-1] - Change build system to use gradle
|
||||
* [SHL-4] - Adding a constructor in JlineShell to provide ConsoleReader.
|
||||
* [SHL-9] - Create Bamboo build project on CI farm
|
||||
* [SHL-10] - Publish CI builds to springsource maven snapshot repository
|
||||
* [SHL-23] - Create docbook based reference guide
|
||||
* [SHL-25] - Enable unit test on CI build
|
||||
* [SHL-50] - Add sample application
|
||||
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
@@ -1,22 +0,0 @@
|
||||
======================================================================
|
||||
== NOTICE file corresponding to section 4 d of the Apache License, ==
|
||||
== Version 2.0, for the Spring Framework distribution. ==
|
||||
======================================================================
|
||||
|
||||
This product includes software developed by
|
||||
the Apache Software Foundation (http://www.apache.org).
|
||||
|
||||
The end-user documentation included with a redistribution, if any,
|
||||
must include the following acknowledgement:
|
||||
|
||||
"This product includes software developed by the Spring Framework
|
||||
Project (http://www.springframework.org)."
|
||||
|
||||
Alternately, this acknowledgement may appear in the software itself,
|
||||
if and wherever such third-party acknowledgements normally appear.
|
||||
|
||||
The names "Spring", "Spring Framework", and "Spring Shell" must
|
||||
not be used to endorse or promote products derived from this
|
||||
software without prior written permission. For written permission,
|
||||
please contact enquiries@springsource.com.
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
SPRING SHELL
|
||||
------------
|
||||
https://github.com/spring-projects/spring-shell
|
||||
|
||||
1. INTRODUCTION
|
||||
|
||||
Spring Shell is an interactive shell that can be easily extended with commands using a Spring based programming model.
|
||||
|
||||
2. RELEASE NOTES
|
||||
|
||||
This release comes with complete reference documentation. For further
|
||||
details, consult the provided javadoc for specific packages and classes.
|
||||
|
||||
3. DISTRIBUTION JAR FILES
|
||||
|
||||
The Spring Shell jar files can be found in the 'dist' directory.
|
||||
|
||||
4. GETTING STARTED
|
||||
|
||||
Please see the reference documentation.
|
||||
Additionally, consult the blog at https://spring.io/blog as well
|
||||
as sections of interest in the reference documentation.
|
||||
|
||||
5. ADDITIONAL RESOURCES
|
||||
|
||||
Spring Shell homepage: http://www.springsource.org/spring-shell
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB |
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<book xmlns="http://docbook.org/ns/docbook" version="5.0"
|
||||
xml:id="spring-shell-reference"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<bookinfo>
|
||||
<title>Spring Shell Documentation</title>
|
||||
<titleabbrev>Spring Shell ${version}</titleabbrev>
|
||||
<releaseinfo>${version}</releaseinfo>
|
||||
<productname>Spring Shell</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Mark</firstname>
|
||||
<surname>Pollack</surname>
|
||||
<affiliation>SpringSource</affiliation>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Costin</firstname>
|
||||
<surname>Leau</surname>
|
||||
<affiliation>SpringSource</affiliation>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Jarred</firstname>
|
||||
<surname>Li</surname>
|
||||
<affiliation>VMware</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Copies of this document may be made for your own use and for distribution
|
||||
to others, provided that you do not charge any fee for such copies and
|
||||
further provided that each copy contains this Copyright Notice, whether
|
||||
distributed in print or electronically.
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc/>
|
||||
|
||||
<xi:include href="preface.xml"/>
|
||||
|
||||
<part id="introduction">
|
||||
<title>Introduction</title>
|
||||
<xi:include href="introduction/introduction.xml"/>
|
||||
<xi:include href="introduction/requirements.xml"/>
|
||||
</part>
|
||||
|
||||
<part id="reference">
|
||||
<title>Reference Documentation</title>
|
||||
<xi:include href="reference/introduction.xml"/>
|
||||
<xi:include href="reference/shell.xml"/>
|
||||
</part>
|
||||
|
||||
<part id="dev">
|
||||
<title>Developing Spring Shell Applications</title>
|
||||
<xi:include href="reference/dev-guide/introduction.xml"/>
|
||||
<xi:include href="reference/dev-guide/dev-spring-shell.xml"/>
|
||||
</part>
|
||||
|
||||
<part id="samples">
|
||||
<title>Spring Shell Sample application</title>
|
||||
<xi:include href="samples/introduction.xml"/>
|
||||
<xi:include href="samples/simple-application.xml"/>
|
||||
</part>
|
||||
|
||||
</book>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<partintro version="5.0" xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:ns5="http://www.w3.org/2000/svg"
|
||||
xmlns:ns4="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns2="http://www.w3.org/1999/xlink"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<para>The Spring Shell provides an interactive shell that lets you
|
||||
contribute commands using a simple Spring based programming model.</para>
|
||||
|
||||
<para>This document is the reference guide for the Spring Shell and covers
|
||||
the key classes that are part of the Shell infrastructure, the plugin model,
|
||||
how to create commands for the shell as well as discussion of the sample
|
||||
application.</para>
|
||||
</partintro>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="requirements"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:ns6="http://www.w3.org/1999/xlink"
|
||||
xmlns:ns5="http://www.w3.org/2000/svg"
|
||||
xmlns:ns4="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Requirements</title>
|
||||
|
||||
<para>The Spring Shell requires JDK level 6.0 and above as well as the
|
||||
<ulink url="http://www.springsource.org/about">Spring Framework</ulink> 3.0
|
||||
(3.1 recommended) and above.</para>
|
||||
</chapter>
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<preface version="5.0" xml:id="preface" xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:ns5="http://www.w3.org/2000/svg"
|
||||
xmlns:ns4="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns2="http://www.w3.org/1999/xlink"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Preface</title>
|
||||
|
||||
<para>The Spring Shell provides an interactive shell that allows you to
|
||||
plugin your own custom commands using a Spring based programming
|
||||
model.</para>
|
||||
|
||||
<para>The shell has been extracted from the <link
|
||||
ns2:href="http://www.springsource.org/spring-roo/">Spring Roo
|
||||
project</link>, giving it a strong foundation and rich feature set. One
|
||||
significant change from Spring Roo is that the plugin model is no longer
|
||||
based on OSGi but instead uses the Spring IoC container to discover commands
|
||||
through classpath scanning. There is currently no classloader isolation
|
||||
between plugins, however that maybe added in future versions.</para>
|
||||
|
||||
<para>Spring Shell's features include</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>A simple, annotation driven, programming model to contribute
|
||||
custom commands</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Use of Spring's classpath scanning functionality as the basis for
|
||||
a command plugin strategy and command development</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Inheritance of the <link
|
||||
ns2:href="http://static.springsource.org/spring-roo/reference/html-single/index.html#usage-shell">Roo
|
||||
Shell features</link>, most notably tab completion, colorization, and
|
||||
script execution.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Customization of command prompt, banner, shell history file
|
||||
name.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>This document assumes that the reader already has a basic familiarity
|
||||
with the Spring Framework.</para>
|
||||
|
||||
<para>While every effort has been made to ensure that this documentation is
|
||||
comprehensive and there are no errors, nevertheless some topics might
|
||||
require more explanation and some typos might have crept in. If you do spot
|
||||
any mistakes or even more serious errors and you can spare a few cycles
|
||||
during lunch, please do bring the error to the attention of the Spring Shell
|
||||
team by <link ns2:href="https://jira.springsource.org/browse/SHL">raising an
|
||||
issue</link>.</para>
|
||||
</preface>
|
||||
@@ -1,225 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="dev-shell"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:ns5="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns4="http://www.w3.org/2000/svg"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Developing Spring Shell Applications</title>
|
||||
|
||||
<para>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
|
||||
the same as developing classes for an application that uses dependency
|
||||
injection. You can leverage all the features of the Spring container to
|
||||
implement your command classes.</para>
|
||||
|
||||
<section>
|
||||
<title>Marker Interface</title>
|
||||
|
||||
<para>The first step to creating a command is to implement the marker
|
||||
interface <interfacename>CommandMarker</interfacename> and to annotate
|
||||
your class with Spring's <classname>@Component </classname>annotation.
|
||||
(Note there is an open JIRA issue to provide a
|
||||
<classname>@CliCommand</classname> meta-annotation to avoid having to use
|
||||
a marker interface). Using the code from the helloworld sample
|
||||
application, the code of a <classname>HelloWorldCommands</classname> class
|
||||
is shown below:</para>
|
||||
|
||||
<programlisting language="java">@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
// use any Spring annotations for Dependency Injection or other Spring interfaces
|
||||
// as required.
|
||||
|
||||
// methods with @Cli annotations go here
|
||||
|
||||
}</programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Logging</title>
|
||||
|
||||
<para>Logging is currently done using JDK logging. Due to the intricacies
|
||||
of console, JLine and Ansi handling, it is generally advised to display
|
||||
messages as return values to the method commands. However, when logging is
|
||||
required, the typical JDK logger declaration should suffice.</para>
|
||||
|
||||
<programlisting language="java">@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
protected final Logger LOG = Logger.getLogger(getClass().getName());
|
||||
|
||||
// methods with @Cli annotations go here
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<warning>
|
||||
Note: it is the responsibility of the packager/developer to handle logging for third-party libraries. Typically one wants to reduce the logging level so the console/shell does not get affected by logging messages.
|
||||
</warning>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>CLI Annotations</title>
|
||||
|
||||
<para>There are three annotations used on methods and method arguments
|
||||
that define the main contract for interacting with the shell. These
|
||||
are:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><classname>CliAvailabilityIndicator</classname> - Placed on a
|
||||
method that returns a boolean value and indicates if a particular
|
||||
command can be presented in the shell. This decision is usually based
|
||||
on the history of commands that have been executed previously. It
|
||||
prevents extraneous commands being presented until some preconditions
|
||||
are met, for example the execution of a 'configuration'
|
||||
command.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>CliCommand</classname> - Placed on a method that
|
||||
provides a command to the shell. Its value provides one or more
|
||||
strings that serve as the start of a particular command name. These
|
||||
must be unique within the entire application, across all
|
||||
plugins.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>CliOption</classname> - Placed on the arguments of a
|
||||
command method, allowing it to declare the argument value as mandatory
|
||||
or optional with a default value.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Here is a simple use of these annotations in a command class</para>
|
||||
|
||||
<programlisting language="java">@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
@CliAvailabilityIndicator({"hw simple"})
|
||||
public boolean isCommandAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw simple", help = "Print a simple hello world message")
|
||||
public String simple(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message")
|
||||
final String message,
|
||||
|
||||
@CliOption(key = { "location" }, mandatory = false,
|
||||
help = "Where you are saying hello", specifiedDefaultValue="At work")
|
||||
final String location) {
|
||||
|
||||
return "Message = [" + message + "] Location = [" + location + "]";
|
||||
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>The method annotated with <classname>@CliAvailabilityIndicator
|
||||
</classname>is returning true so that the one and only command in this
|
||||
class is exposed to the shell to be invoked. If there were more commands
|
||||
in the class, you would list them as comma separated value.</para>
|
||||
|
||||
<para>The <classname>@CliCommand</classname> annotation is creating the
|
||||
command '<literal>hw simple</literal>' in the shell. The help message is
|
||||
what will be printed if you use the build in <literal>help</literal>
|
||||
command. The method name is '<methodname>simple</methodname>' but it could
|
||||
just have been any other name.</para>
|
||||
|
||||
<para>The <classname>@CliOption</classname> annotation on each of the
|
||||
command arguments is where you will spend most of your time authoring
|
||||
commands. You need to decide which arguments are required, which are
|
||||
optional, and if they are optional is there a default value. In this case
|
||||
there are two arguments or options to the command: message and location.
|
||||
The message option is required and a help message is provided to give
|
||||
guidance to the user when tabbing to get completion for the
|
||||
command.</para>
|
||||
|
||||
<para>The implementation of the '<methodname>simple</methodname>' method
|
||||
is trivial, just a log statement, but this is where you would typically
|
||||
call other collaborating objects that were injected into the class via
|
||||
Spring.</para>
|
||||
|
||||
<para>The method argument types in this example are
|
||||
<classname>String</classname>, which doesn't present any issue with type
|
||||
conversion. You can specify methods with any rich object type as well as
|
||||
basic primitive types such as int, float etc. For all types other than
|
||||
those handled by the shell by default (basic types,
|
||||
<classname>Date</classname>, <classname>File</classname>) you will need to
|
||||
register your own implementation of the
|
||||
<interfacename>org.springframework.shell.core.Converter</interfacename>
|
||||
interface with the container in your plugin.</para>
|
||||
|
||||
<para>Note that the method return argument can be non-void - in our
|
||||
example, it is the actual message we want to display. Whenever an object
|
||||
is returned, the shell will display its <literal>toString()</literal>
|
||||
representation.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Testing shell commands</title>
|
||||
|
||||
<para>To perform a test of the shell commands you can instantiate the shell inside a test case,
|
||||
execute the command and then perform assertions on the return value CommandResult.
|
||||
A simple base class to set this up is shown below.</para>
|
||||
<programlisting language="java">public abstract class AbstractShellIntegrationTest {
|
||||
|
||||
private static JLineShellComponent shell;
|
||||
|
||||
@BeforeClass
|
||||
public static void startUp() throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
shell = bootstrap.getJLineShellComponent();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdown() {
|
||||
shell.stop();
|
||||
}
|
||||
|
||||
public static JLineShellComponent getShell() {
|
||||
return shell;
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
<para>Here is an example testing the Date command</para>
|
||||
<programlisting language="java">public class BuiltInCommandTests extends AbstractShellIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void dateTest() throws ParseException {
|
||||
|
||||
//Execute command
|
||||
CommandResult cr = getShell().executeCommand("date");
|
||||
|
||||
//Get result
|
||||
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,Locale.US);
|
||||
Date result = df.parse(cr.getResult().toString());
|
||||
|
||||
//Make assertions - DateMaters is an external dependency not shown here.
|
||||
Date now = new Date();
|
||||
MatcherAssert.assertThat(now, DateMatchers.within(5, TimeUnit.SECONDS, result));
|
||||
}
|
||||
}</programlisting>
|
||||
<para>The java.lang.Class of CommandResult's getResult method will match that of the return value of
|
||||
the method annotated with @CliCommand. You should cast to the appropriate type to help perform your assertions.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Building and running the shell</title>
|
||||
|
||||
<para>In our opinion, the easiest way to build and execute the shell is to
|
||||
cut-n-paste the gradle script in the example application. This uses the
|
||||
application plugin from gradle to create a bin directory with a startup
|
||||
script for windows and Unix and places all dependent jars in a lib
|
||||
directory. Maven has a similar plugin - the <link
|
||||
xlink:href="http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/">AppAssembler</link>
|
||||
plugin.</para>
|
||||
|
||||
<para>The main class of the shell is
|
||||
<classname>org.springframework.shell.Bootstrap</classname>. As long as you
|
||||
place other plugins, perhaps developed independently, on the classpath,
|
||||
the Bootstrap class will incorporate them into the shell.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<partintro>
|
||||
<para>This section provides some guidance on how one can create commands for
|
||||
the Spring Shell.</para>
|
||||
</partintro>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<partintro>
|
||||
<para>This part of the reference documentation explains the core components
|
||||
of the Spring Shell.</para>
|
||||
</partintro>
|
||||
@@ -1,312 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="shell" xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:ns5="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns4="http://www.w3.org/2000/svg"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Spring Shell</title>
|
||||
|
||||
<para>The core components of the shell are its plugin model, built-in
|
||||
commands, and converters.</para>
|
||||
|
||||
<section>
|
||||
<title>Plugin Model</title>
|
||||
|
||||
<para>The plugin model is based on Spring. Each plugin jar is required to
|
||||
contain the file
|
||||
<literal>META-INF/spring/spring-shell-plugin.xml</literal>. These files
|
||||
will be loaded to bootstrap a Spring
|
||||
<interfacename>ApplicationContext</interfacename> when the shell is
|
||||
started. The essential boostrapping code that looks for your contributions
|
||||
looks like this: <programlisting>new ClassPathXmlApplicationContext("classpath*:/META-INF/spring/spring-shell-plugin.xml");</programlisting></para>
|
||||
|
||||
<para>In the <literal>spring-shell-plugin.xml</literal> file you should
|
||||
define the command classes and any other collaborating objects that
|
||||
support the command's actions. The plugin model is depicted in the
|
||||
following diagram</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="pdf">
|
||||
<imagedata fileref="../images/shell-arch-overview.png"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/shell-arch-overview.png"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para>Note that the current plugin model loads all plugins under the same
|
||||
class loader. An open <link
|
||||
xlink:href="https://jira.springsource.org/browse/SHL-37">JIRA issue</link>
|
||||
suggests providing a classloader per plugin to provide isolation.</para>
|
||||
|
||||
<section>
|
||||
<title>Commands</title>
|
||||
|
||||
<para>An easy way to declare the commands is to use Spring's component
|
||||
scanning functionality. Here is an example
|
||||
<literal>spring-shell-plugin.xml </literal> from the sample
|
||||
application:</para>
|
||||
|
||||
<programlisting language="xml"><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
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
|
||||
|
||||
<context:component-scan
|
||||
base-package="org.springframework.shell.samples.helloworld.commands" />
|
||||
|
||||
</beans></programlisting>
|
||||
|
||||
<para>The commands are Spring components, demarcated as such using the
|
||||
<literal>@Component</literal> annotation. For example, the shell of the
|
||||
<classname>HelloWorldCommands</classname> class from the sample
|
||||
application looks like this</para>
|
||||
|
||||
<programlisting language="java">@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
// use any Spring annotations for Dependency Injection or other Spring
|
||||
// interfaces as required.
|
||||
|
||||
// methods with @Cli annotations go here
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>Once the commands are registered and instantiated by the Spring
|
||||
container, they are registered with the core shell parser so that the
|
||||
<literal>@Cli</literal> annotations can be processed. The way the
|
||||
commands are identified is through the use of the
|
||||
<interfacename>CommandMarker</interfacename> interface.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Converters</title>
|
||||
|
||||
<para>The
|
||||
<interfacename>org.springframework.shell.core.Converter</interfacename>
|
||||
interface provides the contract to convert the strings that are entered
|
||||
on the command line to rich Java types passed into the arguments of
|
||||
<classname>@Cli</classname>-annotated methods.</para>
|
||||
|
||||
<para>By default converters for common types are registered. These cover
|
||||
primitive types (boolean, int, float...) as well as Date, Character, and
|
||||
File.</para>
|
||||
|
||||
<para>If you need to register any additional
|
||||
<interfacename>Converter</interfacename> instances, register them with
|
||||
the Spring container in the
|
||||
<classname>spring-shell-plugin.xml</classname> file and they will be
|
||||
picked up automatically.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Built in commands</title>
|
||||
|
||||
<para>There are a few built in commands. Here is a listing of their class
|
||||
name and functionality</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><classname>ConsoleCommands</classname> -
|
||||
<literal>clr</literal> and <literal>clear</literal> - to clear the console.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>DateCommands</classname> -
|
||||
<literal>date</literal> - show the current date and time.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>ExitCommands</classname> -
|
||||
<literal>exit</literal> and <literal>quit</literal> - to exit the
|
||||
shell.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>HelpCommands</classname> - <literal>help</literal> -
|
||||
list all commands and their usage</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>InlineCommentCommands</classname> - <literal>//</literal> and <literal>;</literal> shows the valid characters to use for inline comments</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>OsCommands</classname> - the keyword for this command
|
||||
is the exclamation point, <literal>!</literal>. After the exclamation
|
||||
point you can pass in a unix/windows command string to be
|
||||
executed.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>SystemPropertyCommands</classname> - <literal>system properties</literal>- shows the shell's system properties</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>VersionCommands</classname> - <literal>version</literal>- shows the shell's version</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>There are two commands in provided by the
|
||||
<classname>AbstractShell</classname> class related to useage of block comments</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para><literal>/*</literal> and <literal>*/</literal>- The begin and end characters for block comments</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Customizing the shell</title>
|
||||
|
||||
<para>There are a few extension points that allow you to customize the
|
||||
shell. The extension points are the interfaces</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><interfacename>BannerProvider</interfacename> - Specifies the
|
||||
banner text, welcome message, and version number that will be
|
||||
displayed when the shell is started</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><interfacename>PromptProvider</interfacename> - Specifies the
|
||||
command prompt text, eg. "<literal>shell></literal>" or
|
||||
"<literal>#</literal>" or "<literal>$</literal>". This will be called
|
||||
after every command execution so it does not need to be a static
|
||||
string.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><interfacename>HistoryFileNameProvider</interfacename> -
|
||||
Specifies the name of the command history file</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>There is a default implementation for these interfaces but you
|
||||
should create your own implementations for your own shell application.
|
||||
All of these interfaces extend from
|
||||
<interfacename>NamedProvider</interfacename>. Use
|
||||
Spring's <literal>@Order</literal> annotation to set the priority of the
|
||||
provider. This allows your provider implementations to take precedence
|
||||
over any other implementations that maybe present on the classpath from
|
||||
other plugins.</para>
|
||||
|
||||
<para>To make cool "<link
|
||||
xlink:href="http://en.wikipedia.org/wiki/ASCII_art">ASCII art</link>"
|
||||
banners the website <link
|
||||
xlink:href="http://patorjk.com/software/taag">http://patorjk.com/software/taag</link>
|
||||
is quite neat!</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Communicating between plugins</title>
|
||||
|
||||
<para>As this is a standard Spring application you can use Spring's
|
||||
<classname>ApplicationContext</classname> event infrastructure to
|
||||
communicate across plugins.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Command method interception</title>
|
||||
|
||||
<para>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 method is executed. The interface
|
||||
<interfacename>ExecutionProcessor</interfacename> should be implemented
|
||||
instead of <interfacename>CommandMarker</interfacename> to access this
|
||||
functionality. The <interfacename>ExecutionProcessor</interfacename>
|
||||
interface is shown below</para>
|
||||
|
||||
<programlisting language="java">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);
|
||||
|
||||
}</programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Command line options</title>
|
||||
|
||||
<para>There are a few command line options that can be specified when
|
||||
starting the shell. They are</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>--profiles</literal> - Specifies values for the system
|
||||
property spring.profiles.active so that Spring 3.1 and greater <link
|
||||
xlink:href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/">profile
|
||||
support </link>is enabled.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>--cmdfile</literal> - Specifies a file to read that
|
||||
contains shell commands</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>--histsize</literal> - Specifies the maximum number of
|
||||
lines to store in the command history file. Default value is
|
||||
3000.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>--disableInternalCommands</literal> - Flag that disables all commands that would
|
||||
be pre-registered with the shell. There is no argument to this option. You can selectively add
|
||||
back any internal commands by referencing them in your shell plugin file. Look at the
|
||||
Spring Shell javadocs for specific commands located in the
|
||||
<literal>org.springframework.shell.commands</literal> package as well as the section in this documentation
|
||||
of Built in commands.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Scripts and comments</title>
|
||||
|
||||
<para>Scripts can be executed either by passing in the
|
||||
<literal>--cmdfile</literal> argument at startup or by executing the
|
||||
<literal>script</literal> command inside the shell. When using scripts it
|
||||
helps to add comments and this can be done using block comments that start
|
||||
and end with <literal>/*</literal> and <literal>*/</literal> or an inline
|
||||
one line comment using the <literal>//</literal> or <literal>;</literal>
|
||||
characters.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<partintro>
|
||||
<para>This part of the reference documentation covers the sample
|
||||
applications included with Spring Shell that demonstrate the features in a
|
||||
code centric manner.</para>
|
||||
|
||||
<para><xref linkend="simple-application"/>Describes a simple Spring Shell
|
||||
application that echo's the command parameters to the console.</para>
|
||||
</partintro>
|
||||
@@ -1,137 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="simple-application"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:ns5="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns4="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns3="http://www.w3.org/2000/svg"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Simple sample application using the Spring Shell</title>
|
||||
|
||||
<section>
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>The sample application named 'helloworld' contains three
|
||||
'<literal>hw</literal>' commands, they are '<literal>hw simple</literal>',
|
||||
'<literal>hw complex</literal>' and '<literal>hw enum</literal>' and
|
||||
demonstrate simple to intermediate level usage of the
|
||||
<literal>@Cli</literal> annotation classes for creating commands.</para>
|
||||
|
||||
<para>The example code is located in the distribution directory
|
||||
<literal><spring-shell-install-dir>/samples/helloworld</literal>.</para>
|
||||
|
||||
<para>To build the example cd to the helloworld directory and execute
|
||||
<literal>gradlew installApp</literal> (you first need to add the <literal>gradlew</literal>
|
||||
gradle wrapper to your path). To run the application cd to
|
||||
<literal>build\install\helloworld\bin</literal> and execute the helloworld
|
||||
script.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>HelloWorldCommands</title>
|
||||
|
||||
<para>The <classname>HelloWorldCommands</classname> class is show
|
||||
below</para>
|
||||
|
||||
<programlisting language="java">package org.springframework.shell.samples.helloworld.commands;
|
||||
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
private boolean simpleCommandExecuted = false;
|
||||
|
||||
@CliAvailabilityIndicator({"hw simple"})
|
||||
public boolean isSimpleAvailable() {
|
||||
//always available
|
||||
return true;
|
||||
}
|
||||
|
||||
@CliAvailabilityIndicator({"hw complex", "hw enum"})
|
||||
public boolean isComplexAvailable() {
|
||||
if (simpleCommandExecuted) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw simple", help = "Print a simple hello world message")
|
||||
public String simple(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
|
||||
@CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello", specifiedDefaultValue="At work") final String location) {
|
||||
simpleCommandExecuted = true;
|
||||
return "Message = [" + message + "] Location = [" + location + "]";
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw complex", help = "Print a complex hello world message")
|
||||
public String hello(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
|
||||
@CliOption(key = { "name1"}, mandatory = true, help = "Say hello to the first name") final String name1,
|
||||
@CliOption(key = { "name2" }, mandatory = true, help = "Say hello to a second name") final String name2,
|
||||
@CliOption(key = { "time" }, mandatory = false, specifiedDefaultValue="now", help = "When you are saying hello") final String time,
|
||||
@CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello") final String location) {
|
||||
return "Hello " + name1 + " and " + name2 + ". Your special message is " + message + ". time=[" + time + "] location=[" + location + "]";
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw enum", help = "Print a simple hello world message from an enumerated value")
|
||||
public String eenum(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final MessageType message){
|
||||
return "Hello. Your special enumerated message is " + message;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
Type1("type1"),
|
||||
Type2("type2"),
|
||||
Type3("type3");
|
||||
|
||||
private String type;
|
||||
|
||||
private MessageType(String type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType(){
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>The use of the <classname>@CliAvailabilityIndicator</classname>
|
||||
annotation on two methods, <methodname>isSimpleAvailable</methodname> and
|
||||
<methodname>isComplexAvailable</methodname> shows how you can enable the
|
||||
presence of the '<literal>hw complex</literal>' and '<literal>hw
|
||||
enum</literal>' commands only if the '<literal>hw simple</literal>'
|
||||
command was executed.</para>
|
||||
|
||||
<para>Here is an example session showing the behavior.</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="../images/shell-example.jpg"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/shell-example.jpg"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para>The '<literal>hw enum</literal>' command shows how the shell
|
||||
supports the use of an enumeration as command method arguments.</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="../images/shell-example-enum.jpg"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/shell-example-enum.jpg"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,8 +0,0 @@
|
||||
slf4jVersion=1.7.13
|
||||
jlineVersion=2.12
|
||||
junitVersion=4.12
|
||||
springVersion=4.2.4.RELEASE
|
||||
commonsioVersion=2.4
|
||||
hamcrestVersion=1.3
|
||||
version=1.2.1.BUILD-SNAPSHOT
|
||||
mockitoVersion=1.10.19
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +0,0 @@
|
||||
#Thu Jun 29 11:35:25 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
|
||||
164
gradlew
vendored
164
gradlew
vendored
@@ -1,164 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
gradlew.bat
vendored
90
gradlew.bat
vendored
@@ -1,90 +0,0 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
60
maven.gradle
60
maven.gradle
@@ -1,60 +0,0 @@
|
||||
apply plugin: 'maven'
|
||||
|
||||
ext.optionalDeps = []
|
||||
ext.providedDeps = []
|
||||
|
||||
ext.optional = { optionalDeps << it }
|
||||
ext.provided = { providedDeps << it }
|
||||
|
||||
install {
|
||||
repositories.mavenInstaller {
|
||||
customizePom(pom, project)
|
||||
}
|
||||
}
|
||||
|
||||
def customizePom(pom, gradleProject) {
|
||||
pom.whenConfigured { generatedPom ->
|
||||
// respect 'optional' and 'provided' dependencies
|
||||
gradleProject.optionalDeps.each { dep ->
|
||||
generatedPom.dependencies.find { it.artifactId == dep.name }?.optional = true
|
||||
}
|
||||
gradleProject.providedDeps.each { dep ->
|
||||
generatedPom.dependencies.find { it.artifactId == dep.name }?.scope = 'provided'
|
||||
}
|
||||
|
||||
// eliminate test-scoped dependencies (no need in maven central poms)
|
||||
generatedPom.dependencies.removeAll { dep ->
|
||||
dep.scope == 'test'
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
description = gradleProject.description
|
||||
url = 'http://github.com/SpringSource/spring-shell'
|
||||
organization {
|
||||
name = 'SpringSource'
|
||||
url = 'http://www.springsource.org/spring-shell'
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name 'The Apache Software License, Version 2.0'
|
||||
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url = 'http://github.com/SpringSource/spring-shell'
|
||||
connection = 'scm:git:git://github.com/SpringSource/spring-shell'
|
||||
developerConnection = 'scm:git:git://github.com/SpringSource/spring-shell'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'markpollack'
|
||||
name = 'Mark Pollack'
|
||||
email = 'mpollack@vmware.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
readme.dev
32
readme.dev
@@ -1,32 +0,0 @@
|
||||
======================================================================
|
||||
DEBUGGING VIA ECLIPSE
|
||||
======================================================================
|
||||
|
||||
Most of the time we just use the spring-shell line tool directly
|
||||
from the command line. This we have found is the fastest approach and
|
||||
also lets us see exactly what a user would see, including the TAB
|
||||
completion features. Still, sometimes you have a tricky issue you'd
|
||||
prefer to work through via the STS/Eclipse debugger. When you do this
|
||||
you need to be aware that you lose the full capabilities of the shell,
|
||||
as the JLine library (used for command line parsing) is unable to
|
||||
fully hook into your operating system's keyboard and ANSI services.
|
||||
Anyhow, for some issues a debugger is worth the minor price of losing
|
||||
your full keyboard and colour services! :-)
|
||||
|
||||
To setup debugging, open org.springframework.shell.Bootstrap.
|
||||
Note it has a Java "main" method. Execute the class using Run As >
|
||||
Java Application. Note the "Console" tab in Eclipse/STS will open.
|
||||
Type "quit" then hit enter. Now select Run > Debug Configurations.
|
||||
Select the Java Application > Bootstrap entry. Click on Arguments
|
||||
and then add the following VM Arguments:
|
||||
|
||||
*nix machines:
|
||||
-Djline.terminal=org.springframework.shell.core.IdeTerminal
|
||||
|
||||
Windows machines:
|
||||
-Djline.WindowsTerminal.directConsole=false
|
||||
-Djline.terminal=jline.UnsupportedTerminal
|
||||
|
||||
Finally, set the working directory to "Other" and a location on your
|
||||
disk where you'd like the spring-shell to be loaded. This is usually a
|
||||
project you're intending to test with.
|
||||
8
samples/helloworld/.gitignore
vendored
8
samples/helloworld/.gitignore
vendored
@@ -1,8 +0,0 @@
|
||||
/.classpath
|
||||
/.project
|
||||
.settings/
|
||||
target/
|
||||
/log.roo
|
||||
*.log
|
||||
|
||||
/bin/
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>helloworld</name>
|
||||
<comment>Spring Shell Example</comment>
|
||||
<projects/>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments/>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<linkedResources/>
|
||||
</projectDescription>
|
||||
@@ -1,32 +0,0 @@
|
||||
description = 'Spring Shell Example'
|
||||
apply plugin: 'base'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'application'
|
||||
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/libs-milestone" }
|
||||
maven { url "http://repo.springsource.org/libs-release" }
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.springframework.shell:spring-shell:$springShellVersion"
|
||||
testCompile "junit:junit:$junitVersion"
|
||||
runtime "log4j:log4j:$log4jVersion"
|
||||
}
|
||||
|
||||
mainClassName = "org.springframework.shell.Bootstrap"
|
||||
|
||||
defaultTasks 'installApp'
|
||||
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = 'Generates gradlew[.bat] scripts'
|
||||
gradleVersion = '1.2'
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
springShellVersion = 1.2.0.RELEASE
|
||||
junitVersion = 4.10
|
||||
log4jVersion = 1.2.17
|
||||
version = 1.0.0.RELEASE
|
||||
|
||||
|
||||
|
||||
BIN
samples/helloworld/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
samples/helloworld/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@@ -1,6 +0,0 @@
|
||||
#Thu Jul 25 19:49:28 EDT 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.2-bin.zip
|
||||
164
samples/helloworld/gradlew
vendored
164
samples/helloworld/gradlew
vendored
@@ -1,164 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
samples/helloworld/gradlew.bat
vendored
90
samples/helloworld/gradlew.bat
vendored
@@ -1,90 +0,0 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,101 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.shell.samples</groupId>
|
||||
<artifactId>helloworld</artifactId>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>helloworld</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<spring.shell.version>1.2.0.RELEASE</spring.shell.version>
|
||||
<jar.mainclass>org.springframework.shell.Bootstrap</jar.mainclass>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<junit.version>4.10</junit.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell</artifactId>
|
||||
<version>${spring.shell.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||
<overWriteReleases>true</overWriteReleases>
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
<overWriteIfNewer>true</overWriteIfNewer>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
<mainClass>${jar.mainclass}</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<version>${project.version}</version>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>libs-milestone</id>
|
||||
<url>http://repo.spring.io/libs-milestone/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>libs-release</id>
|
||||
<url>http://repo.spring.io/libs-release/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
@@ -1,21 +0,0 @@
|
||||
Maven 3:
|
||||
|
||||
1.Build the project
|
||||
$>mvn package
|
||||
|
||||
2.run spring shell
|
||||
$>java -jar target/helloworld-1.1.0.RELEASE.jar
|
||||
|
||||
|
||||
|
||||
Gradle:
|
||||
|
||||
1.Build and install the project
|
||||
$>./gradlew installApp
|
||||
|
||||
2.run spring shell
|
||||
$>./build/install/helloworld/bin/helloworld
|
||||
|
||||
or
|
||||
$>./gradlew -q run
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.samples.helloworld;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.shell.Bootstrap;
|
||||
|
||||
/**
|
||||
* Driver class to run the helloworld example.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* Main class that delegates to Spring Shell's Bootstrap class in order to simplify debugging inside an IDE
|
||||
* @param args
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
Bootstrap.main(args);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package org.springframework.shell.samples.helloworld.commands;
|
||||
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class HelloWorldCommands implements CommandMarker {
|
||||
|
||||
private boolean simpleCommandExecuted = false;
|
||||
|
||||
@CliAvailabilityIndicator({"hw simple"})
|
||||
public boolean isSimpleAvailable() {
|
||||
//always available
|
||||
return true;
|
||||
}
|
||||
|
||||
@CliAvailabilityIndicator({"hw complex", "hw enum"})
|
||||
public boolean isComplexAvailable() {
|
||||
if (simpleCommandExecuted) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw simple", help = "Print a simple hello world message")
|
||||
public String simple(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
|
||||
@CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello", specifiedDefaultValue="At work") final String location) {
|
||||
simpleCommandExecuted = true;
|
||||
return "Message = [" + message + "] Location = [" + location + "]";
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw complex", help = "Print a complex hello world message (run 'hw simple' once first)")
|
||||
public String hello(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
|
||||
@CliOption(key = { "name1"}, mandatory = true, help = "Say hello to the first name") final String name1,
|
||||
@CliOption(key = { "name2" }, mandatory = true, help = "Say hello to a second name") final String name2,
|
||||
@CliOption(key = { "time" }, mandatory = false, specifiedDefaultValue="now", help = "When you are saying hello") final String time,
|
||||
@CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello") final String location) {
|
||||
return "Hello " + name1 + " and " + name2 + ". Your special message is " + message + ". time=[" + time + "] location=[" + location + "]";
|
||||
}
|
||||
|
||||
@CliCommand(value = "hw enum", help = "Print a simple hello world message from an enumerated value (run 'hw simple' once first)")
|
||||
public String eenum(
|
||||
@CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final MessageType message){
|
||||
return "Hello. Your special enumerated message is " + message;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
Type1("type1"),
|
||||
Type2("type2"),
|
||||
Type3("type3");
|
||||
|
||||
private String type;
|
||||
|
||||
private MessageType(String type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType(){
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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.samples.helloworld.commands;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.shell.plugin.support.DefaultBannerProvider;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Jarred Li
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class MyBannerProvider extends DefaultBannerProvider {
|
||||
|
||||
public String getBanner() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("=======================================" + OsUtils.LINE_SEPARATOR);
|
||||
buf.append("* *"+ OsUtils.LINE_SEPARATOR);
|
||||
buf.append("* HelloWorld *" +OsUtils.LINE_SEPARATOR);
|
||||
buf.append("* *"+ OsUtils.LINE_SEPARATOR);
|
||||
buf.append("=======================================" + OsUtils.LINE_SEPARATOR);
|
||||
buf.append("Version:" + this.getVersion());
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return "1.2.3";
|
||||
}
|
||||
|
||||
public String getWelcomeMessage() {
|
||||
return "Welcome to HelloWorld CLI";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return "Hello World Banner";
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.samples.helloworld.commands;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.shell.plugin.support.DefaultHistoryFileNameProvider;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jarred Li
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class MyHistoryFileNameProvider extends DefaultHistoryFileNameProvider {
|
||||
|
||||
public String getHistoryFileName() {
|
||||
return "my.log";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return "My history file name provider";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.samples.helloworld.commands;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.shell.plugin.support.DefaultPromptProvider;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Jarred Li
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class MyPromptProvider extends DefaultPromptProvider {
|
||||
|
||||
@Override
|
||||
public String getPrompt() {
|
||||
return "hw-shell>";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return "My prompt provider";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:component-scan base-package="org.springframework.shell.samples.helloworld.commands" />
|
||||
|
||||
</beans>
|
||||
@@ -1 +0,0 @@
|
||||
log4j.rootCategory=OFF
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 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.samples.hellworld.commands;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.Bootstrap;
|
||||
import org.springframework.shell.core.CommandResult;
|
||||
import org.springframework.shell.core.JLineShellComponent;
|
||||
|
||||
public class HelloWorldCommandTests {
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
|
||||
JLineShellComponent shell = bootstrap.getJLineShellComponent();
|
||||
|
||||
CommandResult cr = shell.executeCommand("hw simple --message hello");
|
||||
assertEquals(true, cr.isSuccess());
|
||||
assertEquals("Message = [hello] Location = [null]", cr.getResult());
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = 'spring-shell'
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.shell.core.ExitShellRequest;
|
||||
import org.springframework.shell.core.JLineShellComponent;
|
||||
import org.springframework.shell.core.Shell;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* Loads a {@link Shell} using Spring IoC container.
|
||||
*
|
||||
* @author Ben Alex (original Roo code)
|
||||
* @author Mark Pollack
|
||||
* @author David Winterfeldt
|
||||
*
|
||||
*/
|
||||
public class Bootstrap {
|
||||
|
||||
private final static String[] CONTEXT_PATH = { "classpath*:/META-INF/spring/spring-shell-plugin.xml" };
|
||||
|
||||
private CommandLine commandLine;
|
||||
|
||||
private GenericApplicationContext ctx;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
ExitShellRequest exitShellRequest;
|
||||
try {
|
||||
Bootstrap bootstrap = new Bootstrap(args);
|
||||
exitShellRequest = bootstrap.run();
|
||||
}
|
||||
catch (RuntimeException t) {
|
||||
throw t;
|
||||
}
|
||||
finally {
|
||||
HandlerUtils.flushAllHandlers(Logger.getLogger(""));
|
||||
}
|
||||
|
||||
System.exit(exitShellRequest.getExitCode());
|
||||
}
|
||||
|
||||
public Bootstrap() {
|
||||
this(null, CONTEXT_PATH);
|
||||
}
|
||||
|
||||
public Bootstrap(String[] args) throws IOException {
|
||||
this(args, CONTEXT_PATH);
|
||||
}
|
||||
|
||||
public Bootstrap(String[] args, String[] contextPath) {
|
||||
try {
|
||||
commandLine = SimpleShellCommandLineOptions.parseCommandLine(args);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ShellException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
ctx = new GenericApplicationContext();
|
||||
ctx.registerShutdownHook();
|
||||
configureApplicationContext(ctx);
|
||||
// built-in commands and converters
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
|
||||
if (commandLine.getDisableInternalCommands()) {
|
||||
scanner.scan("org.springframework.shell.converters", "org.springframework.shell.plugin.support");
|
||||
}
|
||||
else {
|
||||
scanner.scan("org.springframework.shell.commands", "org.springframework.shell.converters",
|
||||
"org.springframework.shell.plugin.support");
|
||||
}
|
||||
// user contributed commands
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);
|
||||
reader.loadBeanDefinitions(contextPath);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
private void configureApplicationContext(GenericApplicationContext annctx) {
|
||||
createAndRegisterBeanDefinition(annctx, org.springframework.shell.core.JLineShellComponent.class, "shell");
|
||||
annctx.getBeanFactory().registerSingleton("commandLine", commandLine);
|
||||
}
|
||||
|
||||
protected void createAndRegisterBeanDefinition(GenericApplicationContext annctx, Class<?> clazz, String name) {
|
||||
RootBeanDefinition rbd = new RootBeanDefinition();
|
||||
rbd.setBeanClass(clazz);
|
||||
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) annctx.getBeanFactory();
|
||||
if (name != null) {
|
||||
bf.registerBeanDefinition(name, rbd);
|
||||
}
|
||||
else {
|
||||
bf.registerBeanDefinition(clazz.getSimpleName(), rbd);
|
||||
}
|
||||
}
|
||||
|
||||
public ExitShellRequest run() {
|
||||
StopWatch sw = new StopWatch("Spring Shell");
|
||||
sw.start();
|
||||
String[] commandsToExecuteAndThenQuit = commandLine.getShellCommandsToExecute();
|
||||
// The shell is used
|
||||
JLineShellComponent shell = ctx.getBean("shell", JLineShellComponent.class);
|
||||
ExitShellRequest exitShellRequest;
|
||||
|
||||
if (null != commandsToExecuteAndThenQuit) {
|
||||
boolean successful = false;
|
||||
exitShellRequest = ExitShellRequest.FATAL_EXIT;
|
||||
|
||||
for (String cmd : commandsToExecuteAndThenQuit) {
|
||||
successful = shell.executeCommand(cmd).isSuccess();
|
||||
if (!successful)
|
||||
break;
|
||||
}
|
||||
|
||||
// if all commands were successful, set the normal exit status
|
||||
if (successful) {
|
||||
exitShellRequest = ExitShellRequest.NORMAL_EXIT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
shell.start();
|
||||
exitShellRequest = shell.getExitShellRequest();
|
||||
if (exitShellRequest == null) {
|
||||
// shouldn't really happen, but we'll fallback to this anyway
|
||||
exitShellRequest = ExitShellRequest.NORMAL_EXIT;
|
||||
}
|
||||
shell.waitForComplete();
|
||||
}
|
||||
|
||||
ctx.close();
|
||||
sw.stop();
|
||||
if (shell.isDevelopmentMode()) {
|
||||
System.out.println("Total execution time: " + sw.getLastTaskTimeMillis() + " ms");
|
||||
}
|
||||
return exitShellRequest;
|
||||
}
|
||||
|
||||
public JLineShellComponent getJLineShellComponent() {
|
||||
return ctx.getBean("shell", JLineShellComponent.class);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulates the list of argument passed to the shell.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class CommandLine {
|
||||
|
||||
private String[] args;
|
||||
private int historySize;
|
||||
private String[] shellCommandsToExecute;
|
||||
private boolean disableInternalCommands;
|
||||
|
||||
/**
|
||||
* Construct a new CommandLine
|
||||
* @param args an array of strings from main(String[] args)
|
||||
* @param historySize the size of this history buffer
|
||||
* @param shellCommandsToExecute semi-colon delimited list of commands for the shell to execute
|
||||
*/
|
||||
public CommandLine(String[] args, int historySize, String[] shellCommandsToExecute) {
|
||||
this(args,historySize,shellCommandsToExecute, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new CommandLine
|
||||
* @param args an array of strings from main(String[] args)
|
||||
* @param historySize the size of this history buffer
|
||||
* @param shellCommandsToExecute semi-colon delimited list of commands for the shell to execute
|
||||
* @param disableInternalCommands if true, do not load the built-in shell commands
|
||||
*/
|
||||
public CommandLine(String[] args, int historySize, String[] shellCommandsToExecute, boolean disableInternalCommands) {
|
||||
this.args = args;
|
||||
this.historySize = historySize;
|
||||
this.shellCommandsToExecute = shellCommandsToExecute;
|
||||
this.disableInternalCommands = disableInternalCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command line arguments
|
||||
* @return the command line arguments
|
||||
*/
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the historySize
|
||||
*/
|
||||
public int getHistorySize() {
|
||||
return historySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the shellCommandsToExecute
|
||||
*/
|
||||
public String[] getShellCommandsToExecute() {
|
||||
return shellCommandsToExecute;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the disableInternalCommands value
|
||||
*/
|
||||
public boolean getDisableInternalCommands() {
|
||||
return disableInternalCommands;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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;
|
||||
|
||||
|
||||
/**
|
||||
* Shell exception.
|
||||
*
|
||||
* @author David Wintefeldt
|
||||
*/
|
||||
public class ShellException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1123895874463364743L;
|
||||
|
||||
public ShellException() {}
|
||||
|
||||
public ShellException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ShellException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public ShellException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
|
||||
/**
|
||||
* Used to pass in command line options to customize the shell on launch
|
||||
*
|
||||
* @author vnagaraja
|
||||
*/
|
||||
public class SimpleShellCommandLineOptions {
|
||||
|
||||
private static final Logger LOGGER = HandlerUtils.getLogger(SimpleShellCommandLineOptions.class);
|
||||
public static final int DEFAULT_HISTORY_SIZE = 3000;
|
||||
String[] executeThenQuit = null;
|
||||
Map<String, String> extraSystemProperties = new HashMap<String, String>();
|
||||
int historySize = DEFAULT_HISTORY_SIZE;
|
||||
boolean disableCommands;
|
||||
|
||||
public static CommandLine parseCommandLine(String[] args)
|
||||
throws IOException {
|
||||
if (args == null) {
|
||||
args = new String[] {};
|
||||
}
|
||||
SimpleShellCommandLineOptions options = new SimpleShellCommandLineOptions();
|
||||
List<String> commands = new ArrayList<String>();
|
||||
int i = 0;
|
||||
while (i < args.length) {
|
||||
String arg = args[i++];
|
||||
if (arg.equals("--profiles")) {
|
||||
try {
|
||||
String profiles = args[i++];
|
||||
options.extraSystemProperties.put("spring.profiles.active", profiles);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
LOGGER.warning("No value specified for --profiles option");
|
||||
}
|
||||
} else if (arg.equals("--cmdfile")) {
|
||||
try {
|
||||
File f = new File(args[i++]);
|
||||
commands.addAll(FileUtils.readLines(f));
|
||||
} catch (IOException e) {
|
||||
LOGGER.warning("Could not read lines from command file: " + e.getMessage());
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
LOGGER.warning("No value specified for --cmdfile option");
|
||||
}
|
||||
} else if (arg.equals("--histsize")) {
|
||||
try {
|
||||
String histSizeArg = args[i++];
|
||||
int histSize = Integer.parseInt(histSizeArg);
|
||||
if (histSize <= 0) {
|
||||
LOGGER.warning("histsize option must be > 0, using default value of " + DEFAULT_HISTORY_SIZE);
|
||||
} else {
|
||||
options.historySize = histSize;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.warning("Unable to parse histsize value to an integer ");
|
||||
} catch (ArrayIndexOutOfBoundsException ae) {
|
||||
LOGGER.warning("No value specified for --histsize option");
|
||||
}
|
||||
} else if (arg.equals("--disableInternalCommands")) {
|
||||
options.disableCommands = true;
|
||||
} else if (arg.equals("--help")) {
|
||||
printUsage();
|
||||
System.exit(0);
|
||||
} else {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (; i < args.length; i++) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(args[i]);
|
||||
}
|
||||
|
||||
if (sb.length() > 0) {
|
||||
String[] cmdLineCommands = sb.toString().split(";");
|
||||
for (String s : cmdLineCommands) {
|
||||
// add any command line commands after the commands loaded from the file
|
||||
commands.add(s.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (commands.size() > 0) {
|
||||
options.executeThenQuit = commands.toArray(new String[commands.size()]);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : options.extraSystemProperties.entrySet()) {
|
||||
System.setProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return new CommandLine(args, options.historySize, options.executeThenQuit, options.disableCommands);
|
||||
}
|
||||
|
||||
private static void printUsage() {
|
||||
System.out.println("Usage: --help --histsize [size] --cmdfile [file name] --profiles [comma-separated list of profile names]");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.springframework.shell;
|
||||
|
||||
/**
|
||||
* To be implemented by command result objects that can adapt to the terminal size when they are being rendered.
|
||||
*
|
||||
* <p>An object which does not implement this interface will simply be rendered by invoking its {@link #toString()}
|
||||
* method.</p>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public interface TerminalSizeAware {
|
||||
|
||||
CharSequence render(int terminalWidth);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 static org.fusesource.jansi.Ansi.ansi;
|
||||
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Commands related to the manipulation of the jline console.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class ConsoleCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value = { "cls", "clear" }, help = "Clears the console")
|
||||
public void clear() {
|
||||
AnsiConsole.out().print(ansi().eraseScreen().cursor(0, 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Commands related to the dates
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class DateCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value = { "date" }, help = "Displays the local date and time")
|
||||
public String date() {
|
||||
return DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.getDefault()).format(new Date());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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 org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.ExitShellRequest;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Commands related to exiting the shell
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class ExitCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value={"exit", "quit"}, help="Exits the shell")
|
||||
public ExitShellRequest quit() {
|
||||
return ExitShellRequest.NORMAL_EXIT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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 org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.JLineShellComponent;
|
||||
import org.springframework.shell.core.SimpleParser;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Provides a listing of commands known to the shell.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Mark Pollack
|
||||
* @author Jarred Li
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class HelpCommands implements CommandMarker, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext ctx;
|
||||
|
||||
@CliCommand(value = "help", help = "List all commands usage")
|
||||
public void obtainHelp(
|
||||
@CliOption(key = { "", "command" }, optionContext = "disable-string-converter availableCommands", help = "Command name to provide help for")
|
||||
String buffer) {
|
||||
JLineShellComponent shell = ctx.getBean("shell", JLineShellComponent.class);
|
||||
SimpleParser parser = shell.getSimpleParser();
|
||||
parser.obtainHelp(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.ctx = applicationContext;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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 org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Commands relating to inline comments
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class InlineCommentCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value = { "//", ";" }, help = "Inline comment markers (start of line only)")
|
||||
public void inlineComment() {}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Command type to allow execution of native OS commands from the Spring Shell.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
public class OsCommands implements CommandMarker {
|
||||
|
||||
private static final Logger LOGGER = HandlerUtils
|
||||
.getLogger(OsCommands.class);
|
||||
|
||||
private OsOperations osOperations = new OsOperationsImpl();
|
||||
|
||||
@CliCommand(value = "!", help = "Allows execution of operating system (OS) commands")
|
||||
public void command(
|
||||
@CliOption(key = { "", "command" }, mandatory = false, specifiedDefaultValue = "", unspecifiedDefaultValue = "", help = "The command to execute") final String command) {
|
||||
|
||||
System.out.println("command is:" + command);
|
||||
if (command != null && command.length() > 0) {
|
||||
try {
|
||||
osOperations.executeCommand(command);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOGGER.severe("Unable to execute command " + command + " ["
|
||||
+ e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
|
||||
/**
|
||||
* Operations type to allow execution of native OS commands from the Spring Roo
|
||||
* shell.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface OsOperations {
|
||||
|
||||
/**
|
||||
* Attempts the execution of a commands and delegates the output to the
|
||||
* standard logger.
|
||||
*
|
||||
* @param command the command to execute
|
||||
* @throws IOException if an error occurs
|
||||
*/
|
||||
void executeCommand(String command) throws IOException;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OsOperations} interface.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
public class OsOperationsImpl implements OsOperations {
|
||||
private static final Logger LOGGER = HandlerUtils.getLogger(OsOperationsImpl.class);
|
||||
|
||||
public void executeCommand(final String command) throws IOException {
|
||||
final File root = new File(".");
|
||||
final Process p = Runtime.getRuntime().exec(command, null, root);
|
||||
Reader input = new InputStreamReader(p.getInputStream());
|
||||
Reader errors = new InputStreamReader(p.getErrorStream());
|
||||
|
||||
for (String line : IOUtils.readLines(input)) {
|
||||
if (line.startsWith("[ERROR]")) {
|
||||
LOGGER.severe(line);
|
||||
}
|
||||
else if (line.startsWith("[WARNING]")) {
|
||||
LOGGER.warning(line);
|
||||
}
|
||||
else {
|
||||
LOGGER.info(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (String line : IOUtils.readLines(errors)) {
|
||||
if (line.startsWith("[ERROR]")) {
|
||||
LOGGER.severe(line);
|
||||
}
|
||||
else if (line.startsWith("[WARNING]")) {
|
||||
LOGGER.warning(line);
|
||||
}
|
||||
else {
|
||||
LOGGER.info(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
p.getOutputStream().close();
|
||||
|
||||
|
||||
try {
|
||||
if (p.waitFor() != 0) {
|
||||
LOGGER.warning("The command '" + command + "' did not complete successfully");
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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 static org.springframework.shell.support.util.OsUtils.LINE_SEPARATOR;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Commands related to system properties
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class SystemPropertyCommands implements CommandMarker {
|
||||
|
||||
@CliCommand(value = { "system properties" }, help = "Shows the shell's properties")
|
||||
public String props() {
|
||||
final Set<String> data = new TreeSet<String>(); // For repeatability
|
||||
for (final Entry<Object, Object> entry : System.getProperties().entrySet()) {
|
||||
data.add(entry.getKey() + " = " + entry.getValue());
|
||||
}
|
||||
|
||||
return StringUtils.collectionToDelimitedString(data, LINE_SEPARATOR) + LINE_SEPARATOR;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.springframework.shell.commands;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.plugin.BannerProvider;
|
||||
import org.springframework.shell.plugin.PluginUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Essential built-in shell commands.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
@Component
|
||||
public class VersionCommands implements CommandMarker, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext ctx;
|
||||
|
||||
@CliCommand(value = { "version" }, help = "Displays shell version")
|
||||
public String version() {
|
||||
return PluginUtils.getHighestPriorityProvider(ctx, BannerProvider.class).getVersion();
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.ctx = applicationContext;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package org.springframework.shell.converters;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A converter that knows how to use other converters to create arrays of supported types.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Component
|
||||
public class ArrayConverter implements Converter<Object[]>{
|
||||
|
||||
private Set<Converter<?>> converters;
|
||||
|
||||
@Autowired
|
||||
public void setConverters(Set<Converter<?>> converters) {
|
||||
this.converters = converters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> type, String optionContext) {
|
||||
return findComponentConverter(type, optionContext) != null && !optionContext.contains("disable-array-converter");
|
||||
|
||||
}
|
||||
|
||||
private Converter<?> findComponentConverter(Class<?> targetType, String optionContext) {
|
||||
if (!targetType.isArray()) {
|
||||
return null;
|
||||
}
|
||||
Class<?> componentType = targetType.getComponentType();
|
||||
for (Converter<?> converter : converters) {
|
||||
if (converter.supports(componentType, optionContext)) {
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] convertFromText(String value, Class<?> targetType, String optionContext) {
|
||||
Class<?> componentType = targetType.getComponentType();
|
||||
|
||||
String splittingRegex = inferSplittingRegex(targetType, optionContext);
|
||||
String[] splits = value.split(splittingRegex);
|
||||
Object[] result = (Object[]) Array.newInstance(componentType, splits.length);
|
||||
Converter<?> converter = findComponentConverter(targetType, optionContext);
|
||||
|
||||
for (int i = 0; i < splits.length; i++) {
|
||||
result[i] = converter.convertFromText(splits[i], componentType, optionContext);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a regex used to split the string representation of items.
|
||||
* <p>The default delimiter is a comma, unless we're dealing with Files, in which case
|
||||
* {@link java.io.File.pathSeparator} is used.</p>
|
||||
* <p>Delimiters can be protected by an escape character, which is '\' by default.</p>
|
||||
* <p>Command methods may override bot the delimiter and the escape through the {@code splittingRegex} option context
|
||||
* string.</p>
|
||||
*/
|
||||
private String inferSplittingRegex(Class<?> targetType, String optionContext) {
|
||||
String regex = extract(optionContext, "splittingRegex");
|
||||
if (regex == null) {
|
||||
// Default for files is to use system separator with no way to escape
|
||||
if (File[].class.isAssignableFrom(targetType)) {
|
||||
regex = File.pathSeparator;
|
||||
} else {
|
||||
String delimiter = ",";
|
||||
String escape = "\\";
|
||||
regex = String.format("(?<!\\Q%s\\E)\\Q%s\\E", escape, delimiter);
|
||||
}
|
||||
}
|
||||
return regex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData, String optionContext, MethodTarget target) {
|
||||
Class<?> componentType = targetType.getComponentType();
|
||||
|
||||
String splittingRegex = inferSplittingRegex(targetType, optionContext);
|
||||
String[] splits = existingData.split(splittingRegex);
|
||||
Converter<?> converter = findComponentConverter(targetType, optionContext);
|
||||
|
||||
// Search for completions with the last part only, prefixing the results by everything that was
|
||||
// before the delimiter
|
||||
String last = splits[splits.length - 1];
|
||||
int end = existingData.lastIndexOf(last);
|
||||
String prefix = existingData.substring(0, end);
|
||||
List<Completion> ours = new ArrayList<Completion>();
|
||||
|
||||
// Passing our method target below, as we can't do better. Obviously, method sig will be wrong
|
||||
boolean result = converter.getAllPossibleValues(ours, componentType, last, optionContext, target);
|
||||
for (Completion completion : ours) {
|
||||
completions.add(new Completion(prefix + completion.getValue(), completion.getValue(), null, 0));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String extract(String optionContext, String key) {
|
||||
String[] splits = optionContext.split(" ");
|
||||
String prefix = key + "=";
|
||||
for (String split : splits) {
|
||||
if (split.startsWith(prefix)) {
|
||||
return split.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.JLineShellComponent;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Available commands converter.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Eric Bottard
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class AvailableCommandsConverter implements Converter<String> {
|
||||
|
||||
@Autowired
|
||||
private JLineShellComponent shell;
|
||||
|
||||
@Override
|
||||
public String convertFromText(final String text, final Class<?> requiredType, final String optionContext) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return String.class.isAssignableFrom(requiredType) && optionContext.contains("availableCommands");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
|
||||
for (String s : shell.getSimpleParser().getEveryCommand()) {
|
||||
completions.add(new Completion(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link BigDecimal}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class BigDecimalConverter implements Converter<BigDecimal> {
|
||||
|
||||
@Override
|
||||
public BigDecimal convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new BigDecimal(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return BigDecimal.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link BigInteger}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class BigIntegerConverter implements Converter<BigInteger> {
|
||||
|
||||
@Override
|
||||
public BigInteger convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new BigInteger(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return BigInteger.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Boolean}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class BooleanConverter implements Converter<Boolean> {
|
||||
|
||||
@Override
|
||||
public Boolean convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
if ("true".equalsIgnoreCase(value) || "1".equals(value) || "yes".equalsIgnoreCase(value)) {
|
||||
return true;
|
||||
}
|
||||
else if ("false".equalsIgnoreCase(value) || "0".equals(value) || "no".equalsIgnoreCase(value)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Cannot convert " + value + " to type Boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
completions.add(new Completion("true"));
|
||||
completions.add(new Completion("false"));
|
||||
completions.add(new Completion("yes"));
|
||||
completions.add(new Completion("no"));
|
||||
completions.add(new Completion("1"));
|
||||
completions.add(new Completion("0"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Boolean.class.isAssignableFrom(requiredType) || boolean.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Character}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class CharacterConverter implements Converter<Character> {
|
||||
|
||||
@Override
|
||||
public Character convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return value.charAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Character.class.isAssignableFrom(requiredType) || char.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Date}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class DateConverter implements Converter<Date> {
|
||||
|
||||
// Fields
|
||||
private final DateFormat dateFormat;
|
||||
|
||||
public DateConverter() {
|
||||
this.dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.getDefault());
|
||||
}
|
||||
|
||||
public DateConverter(final DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
try {
|
||||
return dateFormat.parse(value);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Could not parse date: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Date.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Double}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class DoubleConverter implements Converter<Double> {
|
||||
|
||||
@Override
|
||||
public Double convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new Double(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Double.class.isAssignableFrom(requiredType) || double.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Enum}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Alan Stewart
|
||||
* @since 1.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
@Component
|
||||
public class EnumConverter implements Converter<Enum<?>> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enum<?> convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
if (!Enum.class.isAssignableFrom(requiredType)) {
|
||||
return null;
|
||||
}
|
||||
Class<Enum> enumClass = (Class<Enum>) requiredType;
|
||||
return Enum.valueOf(enumClass, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
if (!Enum.class.isAssignableFrom(requiredType)) {
|
||||
return false;
|
||||
}
|
||||
Class<Enum> enumClass = (Class<Enum>) requiredType;
|
||||
for (Enum<?> enumValue : enumClass.getEnumConstants()) {
|
||||
String candidate = enumValue.name();
|
||||
if ("".equals(existingData) || candidate.startsWith(existingData) || existingData.startsWith(candidate)
|
||||
|| candidate.toUpperCase().startsWith(existingData.toUpperCase())
|
||||
|| existingData.toUpperCase().startsWith(candidate.toUpperCase())) {
|
||||
completions.add(new Completion(candidate));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Enum.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.shell.support.util.FileUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link File}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Roman Kuzmik
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class FileConverter implements Converter<File> {
|
||||
|
||||
private static final String HOME_DIRECTORY_SYMBOL = "~";
|
||||
// Constants
|
||||
private static final String home = System.getProperty("user.home");
|
||||
|
||||
// Fields
|
||||
|
||||
/**
|
||||
* @return the "current working directory" this {@link FileConverter} should use if the user fails to provide
|
||||
* an explicit directory in their input (required)
|
||||
*/
|
||||
protected abstract File getWorkingDirectory();
|
||||
|
||||
public File convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new File(convertUserInputIntoAFullyQualifiedPath(value));
|
||||
}
|
||||
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String originalUserInput, final String optionContext, final MethodTarget target) {
|
||||
String adjustedUserInput = convertUserInputIntoAFullyQualifiedPath(originalUserInput);
|
||||
|
||||
String directoryData = adjustedUserInput.substring(0, adjustedUserInput.lastIndexOf(File.separator) + 1);
|
||||
adjustedUserInput = adjustedUserInput.substring(adjustedUserInput.lastIndexOf(File.separator) + 1);
|
||||
|
||||
populate(completions, adjustedUserInput, originalUserInput, directoryData);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void populate(final List<Completion> completions, final String adjustedUserInput, final String originalUserInput, final String directoryData) {
|
||||
File directory = new File(directoryData);
|
||||
|
||||
if (!directory.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : directory.listFiles()) {
|
||||
if (adjustedUserInput == null || adjustedUserInput.length() == 0 ||
|
||||
file.getName().startsWith(adjustedUserInput)) {
|
||||
|
||||
String completion = "";
|
||||
if (directoryData.length() > 0)
|
||||
completion += directoryData;
|
||||
completion += file.getName();
|
||||
|
||||
completion = convertCompletionBackIntoUserInputStyle(originalUserInput, completion);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
completions.add(new Completion(completion + File.separator));
|
||||
} else {
|
||||
completions.add(new Completion(completion));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return File.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
|
||||
private String convertCompletionBackIntoUserInputStyle(final String originalUserInput, final String completion) {
|
||||
if (FileUtils.denotesAbsolutePath(originalUserInput)) {
|
||||
// Input was originally as a fully-qualified path, so we just keep the completion in that form
|
||||
return completion;
|
||||
}
|
||||
if (originalUserInput.startsWith(HOME_DIRECTORY_SYMBOL)) {
|
||||
// Input originally started with this symbol, so replace the user's home directory with it again
|
||||
Assert.notNull(home, "Home directory could not be determined from system properties");
|
||||
return HOME_DIRECTORY_SYMBOL + completion.substring(home.length());
|
||||
}
|
||||
// The path was working directory specific, so strip the working directory given the user never typed it
|
||||
return completion.substring(getWorkingDirectoryAsString().length());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user input starts with a tilde character (~), replace the tilde character with the
|
||||
* user's home directory. If the user input does not start with a tilde, simply return the original
|
||||
* user input without any changes if the input specifies an absolute path, or return an absolute path
|
||||
* based on the working directory if the input specifies a relative path.
|
||||
*
|
||||
* @param userInput the user input, which may commence with a tilde (required)
|
||||
* @return a string that is guaranteed to no longer contain a tilde as the first character (never null)
|
||||
*/
|
||||
private String convertUserInputIntoAFullyQualifiedPath(final String userInput) {
|
||||
if (FileUtils.denotesAbsolutePath(userInput)) {
|
||||
// Input is already in a fully-qualified path form
|
||||
return userInput;
|
||||
}
|
||||
if (userInput.startsWith(HOME_DIRECTORY_SYMBOL)) {
|
||||
// Replace this symbol with the user's actual home directory
|
||||
Assert.notNull(home, "Home directory could not be determined from system properties");
|
||||
if (userInput.length() > 1) {
|
||||
return home + userInput.substring(1);
|
||||
}
|
||||
}
|
||||
// The path is working directory specific, so prepend the working directory
|
||||
String fullPath = getWorkingDirectoryAsString() + userInput;
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
private String getWorkingDirectoryAsString() {
|
||||
try {
|
||||
return getWorkingDirectory().getCanonicalPath() + File.separator;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Float}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class FloatConverter implements Converter<Float> {
|
||||
|
||||
@Override
|
||||
public Float convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new Float(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Float.class.isAssignableFrom(requiredType) || float.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.springframework.shell.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Integer}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class IntegerConverter implements Converter<Integer> {
|
||||
|
||||
@Override
|
||||
public Integer convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new Integer(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Integer.class.isAssignableFrom(requiredType) || int.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Locale}. Supports locales with ISO-639 (ie 'en') or a combination of ISO-639 and
|
||||
* ISO-3166 (ie 'en_AU').
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1
|
||||
*/
|
||||
@Component
|
||||
public class LocaleConverter implements Converter<Locale> {
|
||||
|
||||
@Override
|
||||
public Locale convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
if (value.length() == 2) {
|
||||
// In case only a simpele ISO-639 code is provided we use that code also for the country (ie 'de_DE')
|
||||
return new Locale(value, value.toUpperCase());
|
||||
}
|
||||
else if (value.length() == 5) {
|
||||
String[] split = value.split("_");
|
||||
return new Locale(split[0], split[1]);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Locale.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Long}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class LongConverter implements Converter<Long> {
|
||||
|
||||
@Override
|
||||
public Long convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new Long(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Long.class.isAssignableFrom(requiredType) || long.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link Short}.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class ShortConverter implements Converter<Short> {
|
||||
|
||||
@Override
|
||||
public Short convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return new Short(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return Short.class.isAssignableFrom(requiredType) || short.class.isAssignableFrom(requiredType);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell.core.Shell;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SimpleFileConverter extends FileConverter {
|
||||
@Autowired
|
||||
private Shell shell;
|
||||
|
||||
@Override
|
||||
protected File getWorkingDirectory() {
|
||||
return shell.getHome();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import org.springframework.shell.core.Converter;
|
||||
|
||||
/**
|
||||
* Interface for adding and removing classes that provide static fields which should
|
||||
* be made available via a {@link Converter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface StaticFieldConverter extends Converter<Object> {
|
||||
|
||||
void add(Class<?> clazz);
|
||||
|
||||
void remove(Class<?> clazz);
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A simple {@link Converter} for those classes which provide public static fields to represent possible textual values.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class StaticFieldConverterImpl implements StaticFieldConverter {
|
||||
|
||||
// Fields
|
||||
private final Map<Class<?>, Map<String, Field>> fields = new HashMap<Class<?>, Map<String, Field>>();
|
||||
|
||||
@Override
|
||||
public void add(final Class<?> clazz) {
|
||||
Assert.notNull(clazz, "A class to provide conversion services is required");
|
||||
Assert.isNull(fields.get(clazz), "Class '" + clazz + "' is already registered for completion services");
|
||||
Map<String, Field> ffields = new HashMap<String, Field>();
|
||||
for (Field field : clazz.getFields()) {
|
||||
int modifier = field.getModifiers();
|
||||
if (Modifier.isStatic(modifier) && Modifier.isPublic(modifier)) {
|
||||
ffields.put(field.getName(), field);
|
||||
}
|
||||
}
|
||||
Assert.notEmpty(ffields, "Zero public static fields accessible in '" + clazz + "'");
|
||||
fields.put(clazz, ffields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final Class<?> clazz) {
|
||||
Assert.notNull(clazz, "A class that was providing conversion services is required");
|
||||
fields.remove(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Field> ffields = fields.get(requiredType);
|
||||
if (ffields == null) {
|
||||
return null;
|
||||
}
|
||||
Field f = ffields.get(value);
|
||||
if (f == null) {
|
||||
// Fallback to case insensitive search
|
||||
for (Field candidate : ffields.values()) {
|
||||
if (candidate.getName().equalsIgnoreCase(value)) {
|
||||
f = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (f == null) {
|
||||
// Still not found, despite a case-insensitive search
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return f.get(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to acquire field '" + value + "' from '" + requiredType.getName()
|
||||
+ "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
Map<String, Field> ffields = fields.get(requiredType);
|
||||
if (ffields == null) {
|
||||
return true;
|
||||
}
|
||||
for (String field : ffields.keySet()) {
|
||||
completions.add(new Completion(field));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return fields.get(requiredType) != null;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.converters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link String}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
@Component
|
||||
public class StringConverter implements Converter<String> {
|
||||
|
||||
@Override
|
||||
public String convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
|
||||
final String existingData, final String optionContext, final MethodTarget target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(final Class<?> requiredType, final String optionContext) {
|
||||
return String.class.isAssignableFrom(requiredType)
|
||||
&& (optionContext == null || !optionContext.contains("disable-string-converter"));
|
||||
}
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2016 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.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jline.TerminalFactory;
|
||||
|
||||
import org.springframework.shell.TerminalSizeAware;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
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.VersionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Provides a base {@link Shell} implementation.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Gunnar Hillert
|
||||
*/
|
||||
public abstract class AbstractShell extends AbstractShellStatusPublisher implements Shell {
|
||||
|
||||
// Constants
|
||||
private static final String MY_SLOT = AbstractShell.class.getName();
|
||||
|
||||
//TODO Abstract out to make configurable.
|
||||
protected static final String ROO_PROMPT = "spring> ";
|
||||
|
||||
// Public static fields; don't rename, make final, or make non-public, as
|
||||
// they are part of the public API, e.g. are changed by STS.
|
||||
public static String completionKeys = "TAB";
|
||||
public static String shellPrompt = ROO_PROMPT;
|
||||
|
||||
// Instance fields
|
||||
protected final Logger logger = HandlerUtils.getLogger(getClass());
|
||||
|
||||
protected final Logger exceptionLogger = Logger.getLogger(getClass().getName() + ".exceptions");
|
||||
|
||||
protected boolean inBlockComment;
|
||||
protected ExitShellRequest exitShellRequest;
|
||||
|
||||
protected abstract String getHomeAsString();
|
||||
|
||||
protected abstract ExecutionStrategy getExecutionStrategy();
|
||||
|
||||
protected abstract Parser getParser();
|
||||
|
||||
|
||||
/**
|
||||
* Execute the single line from a script.
|
||||
* <p>
|
||||
* This method can be overridden by sub-classes to pre-process script lines.
|
||||
*/
|
||||
public boolean executeScriptLine(final String line) {
|
||||
return executeCommand(line).isSuccess();
|
||||
}
|
||||
|
||||
public CommandResult executeCommand(String line) {
|
||||
// Another command was attempted
|
||||
setShellStatus(ShellStatus.Status.PARSING);
|
||||
|
||||
final ExecutionStrategy executionStrategy = getExecutionStrategy();
|
||||
boolean flashedMessage = false;
|
||||
while (executionStrategy == null || !executionStrategy.isReadyForCommands()) {
|
||||
// Wait
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ignore) {}
|
||||
if (!flashedMessage) {
|
||||
flash(Level.INFO, "Please wait - still loading", MY_SLOT);
|
||||
flashedMessage = true;
|
||||
}
|
||||
}
|
||||
if (flashedMessage) {
|
||||
flash(Level.INFO, "", MY_SLOT);
|
||||
}
|
||||
|
||||
ParseResult parseResult = null;
|
||||
try {
|
||||
// We support simple block comments; ie a single pair per line
|
||||
if (!inBlockComment && line.contains("/*") && line.contains("*/")) {
|
||||
blockCommentBegin();
|
||||
String lhs = line.substring(0, line.lastIndexOf("/*"));
|
||||
if (line.contains("*/")) {
|
||||
line = lhs + line.substring(line.lastIndexOf("*/") + 2);
|
||||
blockCommentFinish();
|
||||
} else {
|
||||
line = lhs;
|
||||
}
|
||||
}
|
||||
if (inBlockComment) {
|
||||
if (!line.contains("*/")) {
|
||||
return new CommandResult(true);
|
||||
}
|
||||
blockCommentFinish();
|
||||
line = line.substring(line.lastIndexOf("*/") + 2);
|
||||
}
|
||||
// We also support inline comments (but only at start of line, otherwise valid
|
||||
// command options like http://www.helloworld.com will fail as per ROO-517)
|
||||
if (!inBlockComment && (line.trim().startsWith("//") || line.trim().startsWith("#"))) { // # support in ROO-1116
|
||||
line = "";
|
||||
}
|
||||
// Convert any TAB characters to whitespace (ROO-527)
|
||||
line = line.replace('\t', ' ');
|
||||
if ("".equals(line.trim())) {
|
||||
setShellStatus(Status.EXECUTION_SUCCESS);
|
||||
return new CommandResult(true);
|
||||
}
|
||||
parseResult = getParser().parse(line);
|
||||
if (parseResult == null) {
|
||||
return new CommandResult(false);
|
||||
}
|
||||
|
||||
setShellStatus(Status.EXECUTING);
|
||||
Object result = executionStrategy.execute(parseResult);
|
||||
setShellStatus(Status.EXECUTION_RESULT_PROCESSING);
|
||||
if (result != null) {
|
||||
if (result instanceof ExitShellRequest) {
|
||||
exitShellRequest = (ExitShellRequest) result;
|
||||
// Give ProcessManager a chance to close down its threads before the overall OSGi framework is terminated (ROO-1938)
|
||||
executionStrategy.terminate();
|
||||
} else {
|
||||
handleExecutionResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
logCommandIfRequired(line, true);
|
||||
setShellStatus(Status.EXECUTION_SUCCESS, line, parseResult);
|
||||
return new CommandResult(true, result, null);
|
||||
} catch (RuntimeException e) {
|
||||
setShellStatus(Status.EXECUTION_FAILED, line, parseResult);
|
||||
exceptionLogger.log(Level.WARNING, e.getMessage(), e);
|
||||
// We rely on execution strategy to log it
|
||||
try {
|
||||
logCommandIfRequired(line, false);
|
||||
} catch (Exception ignored) {}
|
||||
return new CommandResult(false, null, e);
|
||||
} finally {
|
||||
setShellStatus(Status.USER_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a subclass to log the execution of a well-formed command. This is invoked after a command
|
||||
* has completed, and indicates whether the command returned normally or returned an exception. Note
|
||||
* that attempted commands that are not well-formed (eg they are missing a mandatory argument) will
|
||||
* never be presented to this method, as the command execution is never actually attempted in those
|
||||
* cases. This method is only invoked if an attempt is made to execute a particular command.
|
||||
*
|
||||
* <p>
|
||||
* Implementations should consider specially handling the "script" commands, and also
|
||||
* indicating whether a command was successful or not. Implementations that wish to behave
|
||||
* consistently with other {@link AbstractShell} subclasses are encouraged to simply override
|
||||
* {@link #logCommandToOutput(String)} instead, and only override this method if you actually
|
||||
* need to fine-tune the output logic.
|
||||
*
|
||||
* @param line the parsed line (any comments have been removed; never null)
|
||||
* @param successful if the command was successful or not
|
||||
*/
|
||||
protected void logCommandIfRequired(final String line, final boolean successful) {
|
||||
if (line.startsWith("script")) {
|
||||
logCommandToOutput((successful ? "// " : "// [failed] ") + line);
|
||||
} else {
|
||||
logCommandToOutput((successful ? "" : "// [failed] ") + line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a subclass to actually write the resulting logged command to some form of output. This
|
||||
* frees subclasses from needing to implement the logic within {@link #logCommandIfRequired(String, boolean)}.
|
||||
*
|
||||
* <p>
|
||||
* Implementations should invoke {@link #getExitShellRequest()} to monitor any attempts to exit the shell and
|
||||
* release resources such as output log files.
|
||||
*
|
||||
* @param processedLine the line that should be appended to some type of output (excluding the \n character)
|
||||
*/
|
||||
protected void logCommandToOutput(final String processedLine) {}
|
||||
|
||||
/**
|
||||
* Base implementation of the {@link Shell#setPromptPath(String)} method, designed for simple shell
|
||||
* implementations. Advanced implementations (eg those that support ANSI codes etc) will likely want
|
||||
* to override this method and set the {@link #shellPrompt} variable directly.
|
||||
*
|
||||
* @param path to set (can be null or empty; must NOT be formatted in any special way eg ANSI codes)
|
||||
*/
|
||||
public void setPromptPath(final String path) {
|
||||
if (path == null || "".equals(path)) {
|
||||
shellPrompt = ROO_PROMPT;
|
||||
} else {
|
||||
shellPrompt = path + " " + ROO_PROMPT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of {@link Shell#setPromptPath(String, boolean))} method to satisfy STS compatibility.
|
||||
*
|
||||
* @param path to set (can be null or empty)
|
||||
* @param overrideStyle
|
||||
*/
|
||||
public void setPromptPath(String path, boolean overrideStyle) {
|
||||
setPromptPath(path);
|
||||
}
|
||||
|
||||
public ExitShellRequest getExitShellRequest() {
|
||||
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");
|
||||
inBlockComment = true;
|
||||
}
|
||||
|
||||
@CliCommand(value = { "*/" }, help = "End of block comment")
|
||||
public void blockCommentFinish() {
|
||||
Assert.isTrue(inBlockComment, "Cannot close a block comment when it has not been opened");
|
||||
inBlockComment = false;
|
||||
}
|
||||
|
||||
public String versionInfo(){
|
||||
return VersionUtils.versionInfo();
|
||||
}
|
||||
|
||||
public String getShellPrompt() {
|
||||
return shellPrompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the home directory for the current shell instance.
|
||||
*
|
||||
* <p>
|
||||
* Note: calls the {@link #getHomeAsString()} method to allow subclasses to provide the home directory location as
|
||||
* string using different environment-specific strategies.
|
||||
*
|
||||
* <p>
|
||||
* If the path indicated by {@link #getHomeAsString()} exists and refers to a directory, that directory
|
||||
* is returned.
|
||||
*
|
||||
* <p>
|
||||
* If the path indicated by {@link #getHomeAsString()} exists and refers to a file, an exception is thrown.
|
||||
*
|
||||
* <p>
|
||||
* If the path indicated by {@link #getHomeAsString()} does not exist, it will be created as a directory.
|
||||
* If this fails, an exception will be thrown.
|
||||
*
|
||||
* @return the home directory for the current shell instance (which is guaranteed to exist and be a directory)
|
||||
*/
|
||||
public File getHome() {
|
||||
String rooHome = getHomeAsString();
|
||||
File f = new File(rooHome);
|
||||
Assert.isTrue(!f.exists() || (f.exists() && f.isDirectory()), "Path '" + f.getAbsolutePath() + "' must be a directory, or it must not exist");
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
Assert.isTrue(f.exists() && f.isDirectory(), "Path '" + f.getAbsolutePath() + "' is not a directory; please specify roo.home system property correctly");
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link #flash(Level, String, String)} that simply displays the message via the logger. It is
|
||||
* strongly recommended shell implementations override this method with a more effective approach.
|
||||
*/
|
||||
public void flash(final Level level, final String message, final String slot) {
|
||||
Assert.notNull(level, "Level is required for a flash message");
|
||||
Assert.notNull(message, "Message is required for a flash message");
|
||||
Assert.hasText(slot, "Slot name must be specified for a flash message");
|
||||
if (!("".equals(message))) {
|
||||
logger.log(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the result of execution of a command. Given <i>result</i> is
|
||||
* expected to be not <code>null</code>. If <i>result</i> is a
|
||||
* {@link java.lang.Iterable} object, it will be iterated through to print
|
||||
* the output of <i>toString</i>. For other type of objects, simply output
|
||||
* of <i>toString</i> is shown. Subclasses can alter this implementation
|
||||
* to handle the <i>result</i> differently.
|
||||
*
|
||||
* @param result not <code>null</code> result of execution of a command.
|
||||
*/
|
||||
protected void handleExecutionResult(Object result) {
|
||||
if (result instanceof Iterable<?>) {
|
||||
for (Object o : (Iterable<?>) result) {
|
||||
handleExecutionResult(o);
|
||||
}
|
||||
} else if (result instanceof TerminalSizeAware) {
|
||||
int width = TerminalFactory.get().getWidth();
|
||||
logger.info(((TerminalSizeAware) result).render(width).toString());
|
||||
} else {
|
||||
logger.info(result.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
/**
|
||||
* Marker interface indicating a provider of one or more shell commands.
|
||||
*/
|
||||
public interface CommandMarker {}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 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.core;
|
||||
|
||||
public class CommandResult {
|
||||
|
||||
private boolean success;
|
||||
|
||||
private Object result;
|
||||
|
||||
private Throwable exception;
|
||||
|
||||
public CommandResult(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
public CommandResult(boolean success, Object result, Throwable exception) {
|
||||
super();
|
||||
this.success = success;
|
||||
this.result = result;
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public Throwable getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommandResult [success=" + success + ", result=" + result
|
||||
+ ", exception=" + exception + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.springframework.shell.support.util.AnsiEscapeCode;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class Completion {
|
||||
|
||||
// Fields
|
||||
private final int order;
|
||||
private final String formattedValue;
|
||||
private final String heading;
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public Completion(final String value) {
|
||||
this(value, value, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value
|
||||
* @param formattedValue
|
||||
* @param heading
|
||||
* @param order
|
||||
*/
|
||||
public Completion(final String value, final String formattedValue, String heading, final int order) {
|
||||
this.formattedValue = formattedValue;
|
||||
this.order = order;
|
||||
this.value = value;
|
||||
if (StringUtils.hasText(heading)) {
|
||||
heading = AnsiEscapeCode.decorate(heading, AnsiEscapeCode.UNDERSCORE, AnsiEscapeCode.FG_GREEN);
|
||||
}
|
||||
this.heading = heading;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getFormattedValue() {
|
||||
return formattedValue;
|
||||
}
|
||||
|
||||
public String getHeading() {
|
||||
return heading;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return order + ". " + heading + " - " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Completion that = (Completion) o;
|
||||
if (formattedValue != null ? !formattedValue.equals(that.formattedValue) : that.formattedValue != null) {
|
||||
return false;
|
||||
}
|
||||
if (heading != null ? !heading.equals(that.heading) : that.heading != null) {
|
||||
return false;
|
||||
}
|
||||
if (value != null ? !value.equals(that.value) : that.value != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = value != null ? value.hashCode() : 0;
|
||||
result = 31 * result + (formattedValue != null ? formattedValue.hashCode() : 0);
|
||||
result = 31 * result + (heading != null ? heading.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
|
||||
/**
|
||||
* Converts between Strings (as displayed by and entered via the shell) and Java objects
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @param <T> the type being converted to/from
|
||||
*/
|
||||
public interface Converter<T> {
|
||||
|
||||
/**
|
||||
* The prefix for the option context property that indicates how many successive tab completion requests have
|
||||
* occurred.
|
||||
*/
|
||||
public static final String TAB_COMPLETION_COUNT_PREFIX = "tab-completion-count-";
|
||||
|
||||
/**
|
||||
* Indicates whether this converter supports the given type in the given option context
|
||||
*
|
||||
* @param type the type being checked
|
||||
* @param optionContext a non-<code>null</code> string that customises the behaviour of this converter for a given
|
||||
* {@link CliOption} of a given {@link CliCommand}; the contents will have special meaning to this converter (e.g.
|
||||
* be a comma-separated list of keywords known to this converter)
|
||||
* @return see above
|
||||
*/
|
||||
boolean supports(Class<?> type, String optionContext);
|
||||
|
||||
/**
|
||||
* Converts from the given String value to type T
|
||||
*
|
||||
* @param value the value to convert
|
||||
* @param targetType the type being converted to; can't be <code>null</code>
|
||||
* @param optionContext a non-<code>null</code> string that customises the behaviour of this converter for a given
|
||||
* {@link CliOption} of a given {@link CliCommand}; the contents will have special meaning to this converter (e.g.
|
||||
* be a comma-separated list of keywords known to this converter)
|
||||
* @return see above
|
||||
* @throws RuntimeException if the given value could not be converted
|
||||
*/
|
||||
T convertFromText(String value, Class<?> targetType, String optionContext);
|
||||
|
||||
/**
|
||||
* Populates the given list with the possible completions
|
||||
*
|
||||
* @param completions the list to populate; can't be <code>null</code>
|
||||
* @param targetType the type of parameter for which a string is being entered
|
||||
* @param existingData what the user has typed so far
|
||||
* @param optionContext a non-<code>null</code> string that customises the behaviour of this converter for a given
|
||||
* {@link CliOption} of a given {@link CliCommand}; the contents will have special meaning to this converter (e.g.
|
||||
* be a comma-separated list of keywords known to this converter)
|
||||
* @param target
|
||||
* @return <code>true</code> if all the added completions are complete values, or <code>false</code> if the user can
|
||||
* press TAB to add further information to some or all of them
|
||||
*/
|
||||
boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData,
|
||||
String optionContext, MethodTarget target);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.springframework.shell.event.ParseResult;
|
||||
|
||||
/**
|
||||
* Extension interface allowing command provider to be called
|
||||
* in a generic fashion just before, and right after, executing a command.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.springframework.shell.event.ParseResult;
|
||||
|
||||
/**
|
||||
* Strategy interface to permit the controlled execution of methods.
|
||||
*
|
||||
* <p>
|
||||
* This interface is used to enable a {@link Shell} to execute methods in a consistent, system-wide
|
||||
* manner. A typical use case is to ensure user interface commands are not executed concurrently
|
||||
* when other background threads are performing certain operations.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*
|
||||
*/
|
||||
public interface ExecutionStrategy {
|
||||
|
||||
/**
|
||||
* Executes the method indicated by the {@link ParseResult}.
|
||||
*
|
||||
* @param parseResult that should be executed (never presented as null)
|
||||
* @return an object which will be rendered by the {@link Shell} implementation (may return null)
|
||||
* @throws RuntimeException which is handled by the {@link Shell} implementation
|
||||
*/
|
||||
Object execute(ParseResult parseResult) throws RuntimeException;
|
||||
|
||||
/**
|
||||
* Indicates commands are able to be presented. This generally means all important
|
||||
* system startup activities have completed.
|
||||
*
|
||||
* @return whether commands can be presented for processing at this time
|
||||
*/
|
||||
boolean isReadyForCommands();
|
||||
|
||||
/**
|
||||
* Indicates the execution runtime should be terminated. This allows it to cleanup before returning
|
||||
* control flow to the caller. Necessary for clean shutdowns.
|
||||
*/
|
||||
void terminate();
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
/**
|
||||
* An immutable representation of a request to exit the shell.
|
||||
*
|
||||
* <p>
|
||||
* Implementations of the shell are free to handle these requests in whatever
|
||||
* way they wish. Callers should not expect an exit request to be completed.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class ExitShellRequest {
|
||||
|
||||
// Constants
|
||||
public static final ExitShellRequest NORMAL_EXIT = new ExitShellRequest(0);
|
||||
public static final ExitShellRequest FATAL_EXIT = new ExitShellRequest(1);
|
||||
public static final ExitShellRequest JVM_TERMINATED_EXIT = new ExitShellRequest(99); // Ensure 99 is maintained in o.s.r.bootstrap.Main as it's the default for a null roo.exit code
|
||||
|
||||
// Fields
|
||||
private final int exitCode;
|
||||
|
||||
private ExitShellRequest(final int exitCode) {
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import jline.UnsupportedTerminal;
|
||||
|
||||
/**
|
||||
* Terminal used for debugging inside an IDE. See the development instructions.
|
||||
*/
|
||||
public class IdeTerminal extends UnsupportedTerminal {
|
||||
|
||||
public boolean isANSISupported() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import static org.fusesource.jansi.Ansi.ansi;
|
||||
import static org.fusesource.jansi.Ansi.Color.GREEN;
|
||||
import static org.fusesource.jansi.Ansi.Color.MAGENTA;
|
||||
import static org.fusesource.jansi.Ansi.Color.RED;
|
||||
import static org.springframework.shell.support.util.OsUtils.LINE_SEPARATOR;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import jline.console.ConsoleReader;
|
||||
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.fusesource.jansi.Ansi.Attribute;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* JDK logging {@link Handler} that emits log messages to a JLine {@link ConsoleReader}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
public class JLineLogHandler extends Handler {
|
||||
|
||||
// Fields
|
||||
private ConsoleReader reader;
|
||||
|
||||
private ShellPromptAccessor shellPromptAccessor;
|
||||
|
||||
private static ThreadLocal<Boolean> redrawProhibit = new ThreadLocal<Boolean>();
|
||||
|
||||
private static String lastMessage;
|
||||
|
||||
private static boolean includeThreadName = false;
|
||||
|
||||
private boolean ansiSupported;
|
||||
|
||||
private String userInterfaceThreadName;
|
||||
|
||||
private static boolean suppressDuplicateMessages = true;
|
||||
|
||||
public JLineLogHandler(final ConsoleReader reader, final ShellPromptAccessor shellPromptAccessor) {
|
||||
Assert.notNull(reader, "Console reader required");
|
||||
Assert.notNull(shellPromptAccessor, "Shell prompt accessor required");
|
||||
this.reader = reader;
|
||||
this.shellPromptAccessor = shellPromptAccessor;
|
||||
this.userInterfaceThreadName = Thread.currentThread().getName();
|
||||
this.ansiSupported = reader.getTerminal().isAnsiSupported();
|
||||
|
||||
setFormatter(new Formatter() {
|
||||
@Override
|
||||
public String format(final LogRecord record) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (record.getMessage() != null) {
|
||||
sb.append(record.getMessage()).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (record.getThrown() != null) {
|
||||
PrintWriter pw = null;
|
||||
try {
|
||||
StringWriter sw = new StringWriter();
|
||||
pw = new PrintWriter(sw);
|
||||
record.getThrown().printStackTrace(pw);
|
||||
sb.append(sw.toString());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(pw);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
|
||||
public static void prohibitRedraw() {
|
||||
redrawProhibit.set(true);
|
||||
}
|
||||
|
||||
public static void cancelRedrawProhibition() {
|
||||
redrawProhibit.remove();
|
||||
}
|
||||
|
||||
public static void setIncludeThreadName(final boolean include) {
|
||||
includeThreadName = include;
|
||||
}
|
||||
|
||||
public static void resetMessageTracking() {
|
||||
lastMessage = null; // see ROO-251
|
||||
}
|
||||
|
||||
public static boolean isSuppressDuplicateMessages() {
|
||||
return suppressDuplicateMessages;
|
||||
}
|
||||
|
||||
public static void setSuppressDuplicateMessages(final boolean suppressDuplicateMessages) {
|
||||
JLineLogHandler.suppressDuplicateMessages = suppressDuplicateMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final LogRecord record) {
|
||||
try {
|
||||
// Avoid repeating the same message that displayed immediately before the current message (ROO-30, ROO-1873)
|
||||
String toDisplay = toDisplay(record);
|
||||
if (toDisplay.equals(lastMessage) && suppressDuplicateMessages) {
|
||||
return;
|
||||
}
|
||||
lastMessage = toDisplay;
|
||||
|
||||
StringBuilder buffer = reader.getCursorBuffer().copy().buffer;
|
||||
int cursor = reader.getCursorBuffer().cursor;
|
||||
if (reader.getCursorBuffer().length() > 0) {
|
||||
// The user has semi-typed something, so put a new line in so the debug message is separated
|
||||
reader.println();
|
||||
|
||||
// We need to cancel whatever they typed (it's reset later on), so the line appears empty
|
||||
reader.getCursorBuffer().clear();
|
||||
}
|
||||
|
||||
// This ensures nothing is ever displayed when redrawing the line
|
||||
reader.setPrompt("");
|
||||
reader.redrawLine();
|
||||
// Now restore the line formatting settings back to their original
|
||||
reader.setPrompt(shellPromptAccessor.getShellPrompt());
|
||||
|
||||
reader.getCursorBuffer().write(buffer.toString());
|
||||
reader.getCursorBuffer().cursor = cursor;
|
||||
|
||||
reader.print(toDisplay);
|
||||
|
||||
Boolean prohibitingRedraw = redrawProhibit.get();
|
||||
if (prohibitingRedraw == null) {
|
||||
reader.redrawLine();
|
||||
}
|
||||
|
||||
reader.flush();
|
||||
}
|
||||
catch (Exception e) {
|
||||
reportError("Could not publish log message", e, Level.SEVERE.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
private String toDisplay(final LogRecord event) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String threadName;
|
||||
String eventString;
|
||||
if (includeThreadName && !userInterfaceThreadName.equals(Thread.currentThread().getName())
|
||||
&& !"".equals(Thread.currentThread().getName())) {
|
||||
threadName = "[" + Thread.currentThread().getName() + "]";
|
||||
|
||||
// Build an event string that will indent nicely given the left hand side now contains a thread name
|
||||
StringBuilder lineSeparatorAndIndentingString = new StringBuilder();
|
||||
for (int i = 0; i <= threadName.length(); i++) {
|
||||
lineSeparatorAndIndentingString.append(" ");
|
||||
}
|
||||
|
||||
eventString = " "
|
||||
+ getFormatter().format(event).replace(LINE_SEPARATOR,
|
||||
LINE_SEPARATOR + lineSeparatorAndIndentingString.toString());
|
||||
if (eventString.endsWith(lineSeparatorAndIndentingString.toString())) {
|
||||
eventString = eventString.substring(0, eventString.length() - lineSeparatorAndIndentingString.length());
|
||||
}
|
||||
}
|
||||
else {
|
||||
threadName = "";
|
||||
eventString = getFormatter().format(event);
|
||||
}
|
||||
|
||||
if (ansiSupported) {
|
||||
Ansi ansi = ansi(sb);
|
||||
if (event.getLevel().intValue() >= Level.SEVERE.intValue()) {
|
||||
ansi.a(Attribute.NEGATIVE_ON).a(threadName).a(Attribute.NEGATIVE_OFF).fg(RED).a(eventString).reset();
|
||||
}
|
||||
else if (event.getLevel().intValue() >= Level.WARNING.intValue()) {
|
||||
ansi.a(Attribute.NEGATIVE_ON).a(threadName).a(Attribute.NEGATIVE_OFF).fg(MAGENTA).a(eventString)
|
||||
.reset();
|
||||
}
|
||||
else if (event.getLevel().intValue() >= Level.INFO.intValue()) {
|
||||
ansi.a(Attribute.NEGATIVE_ON).a(threadName).a(Attribute.NEGATIVE_OFF).fg(GREEN).a(eventString).reset();
|
||||
}
|
||||
else {
|
||||
ansi.a(Attribute.NEGATIVE_ON).a(threadName).a(Attribute.NEGATIVE_OFF).a(eventString);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
sb.append(threadName).append(eventString);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,704 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import static org.fusesource.jansi.Ansi.ansi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jline.WindowsTerminal;
|
||||
import jline.console.ConsoleReader;
|
||||
import jline.console.UserInterruptException;
|
||||
import jline.console.history.History;
|
||||
import jline.console.history.MemoryHistory;
|
||||
|
||||
import org.apache.commons.io.input.ReversedLinesFileReader;
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.fusesource.jansi.Ansi.Attribute;
|
||||
import org.fusesource.jansi.Ansi.Color;
|
||||
import org.fusesource.jansi.Ansi.Erase;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.springframework.shell.event.ShellStatus;
|
||||
import org.springframework.shell.event.ShellStatus.Status;
|
||||
import org.springframework.shell.event.ShellStatusListener;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.shell.support.util.VersionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Uses the feature-rich <a href="http://sourceforge.net/projects/jline/">JLine</a> library to provide an interactive
|
||||
* shell.
|
||||
*
|
||||
* <p>
|
||||
* Due to Windows' lack of color ANSI services out-of-the-box, this implementation automatically detects the classpath
|
||||
* presence of <a href="http://jansi.fusesource.org/">Jansi</a> and uses it if present. This library is not necessary
|
||||
* for *nix machines, which support colour ANSI without any special effort. This implementation has been written to use
|
||||
* reflection in order to avoid hard dependencies on Jansi.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Jarred Li
|
||||
* @author Glenn Renfro
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class JLineShell extends AbstractShell implements Shell, Runnable {
|
||||
|
||||
// Constants
|
||||
private static final String ANSI_CONSOLE_CLASSNAME = "org.fusesource.jansi.AnsiConsole";
|
||||
|
||||
private static final boolean JANSI_AVAILABLE = ClassUtils.isPresent(ANSI_CONSOLE_CLASSNAME,
|
||||
JLineShell.class.getClassLoader());
|
||||
|
||||
private static final char ESCAPE = 27;
|
||||
|
||||
private static final String BEL = "\007";
|
||||
|
||||
// Fields
|
||||
protected volatile ConsoleReader reader;
|
||||
|
||||
private boolean developmentMode = false;
|
||||
|
||||
private FileWriter fileLog;
|
||||
|
||||
private final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
protected ShellStatusListener statusListener; // ROO-836
|
||||
|
||||
/** key: slot name, value: flashInfo instance */
|
||||
private final Map<String, FlashInfo> flashInfoMap = new HashMap<String, FlashInfo>();
|
||||
|
||||
/** key: row number, value: eraseLineFromPosition */
|
||||
private final Map<Integer, Integer> rowErasureMap = new HashMap<Integer, Integer>();
|
||||
|
||||
private boolean shutdownHookFired = false; // ROO-1599
|
||||
|
||||
private int historySize;
|
||||
|
||||
public void run() {
|
||||
reader = createConsoleReader();
|
||||
|
||||
setPromptPath(null);
|
||||
|
||||
JLineLogHandler handler = new JLineLogHandler(reader, this);
|
||||
JLineLogHandler.prohibitRedraw(); // Affects this thread only
|
||||
Logger mainLogger = Logger.getLogger("");
|
||||
removeHandlers(mainLogger);
|
||||
mainLogger.addHandler(handler);
|
||||
|
||||
reader.addCompleter(new ParserCompleter(getParser()));
|
||||
|
||||
reader.setBellEnabled(true);
|
||||
if (Boolean.getBoolean("jline.nobell")) {
|
||||
reader.setBellEnabled(false);
|
||||
}
|
||||
|
||||
// reader.setDebug(new PrintWriter(new FileWriter("writer.debug", true)));
|
||||
|
||||
openFileLogIfPossible();
|
||||
History history = this.reader.getHistory();
|
||||
if (history instanceof MemoryHistory) {
|
||||
((MemoryHistory) history).setMaxSize(getHistorySize());
|
||||
}
|
||||
// Try to build previous command history from the project's log
|
||||
String[] filteredLogEntries = filterLogEntry();
|
||||
for (String logEntry : filteredLogEntries) {
|
||||
reader.getHistory().add(logEntry);
|
||||
}
|
||||
|
||||
flashMessageRenderer();
|
||||
flash(Level.FINE, this.getProductName() + " " + this.getVersion(), Shell.WINDOW_TITLE_SLOT);
|
||||
printBannerAndWelcome();
|
||||
|
||||
String startupNotifications = getStartupNotifications();
|
||||
if (StringUtils.hasText(startupNotifications)) {
|
||||
logger.info(startupNotifications);
|
||||
}
|
||||
|
||||
setShellStatus(Status.STARTED);
|
||||
|
||||
try {
|
||||
// Monitor CTRL+C initiated shutdowns (ROO-1599)
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||
public void run() {
|
||||
shutdownHookFired = true;
|
||||
}
|
||||
}, getProductName() + " JLine Shutdown Hook"));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
}
|
||||
|
||||
// Handle any "execute-then-quit" operation
|
||||
|
||||
String rooArgs = System.getProperty("roo.args");
|
||||
if (rooArgs != null && !"".equals(rooArgs)) {
|
||||
setShellStatus(Status.USER_INPUT);
|
||||
boolean success = executeCommand(rooArgs).isSuccess();
|
||||
if (exitShellRequest == null) {
|
||||
// The command itself did not specify an exit shell code, so we'll fall back to something sensible here
|
||||
executeCommand("quit"); // ROO-839
|
||||
exitShellRequest = success ? ExitShellRequest.NORMAL_EXIT : ExitShellRequest.FATAL_EXIT;
|
||||
}
|
||||
setShellStatus(Status.SHUTTING_DOWN);
|
||||
}
|
||||
else {
|
||||
// Normal RPEL processing
|
||||
promptLoop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* read history commands from history log. the history size if determined by --histsize options.
|
||||
*
|
||||
* @return history commands
|
||||
*/
|
||||
private String[] filterLogEntry() {
|
||||
ArrayList<String> entries = new ArrayList<String>();
|
||||
ReversedLinesFileReader reversedReader = null;
|
||||
try {
|
||||
reversedReader = new ReversedLinesFileReader(new File(getHistoryFileName()), 4096, Charset.forName("UTF-8"));
|
||||
int size = 0;
|
||||
String line = null;
|
||||
while ((line = reversedReader.readLine()) != null) {
|
||||
if (!line.startsWith("//")) {
|
||||
size++;
|
||||
if (size > historySize) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
entries.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warning("read history file failed. Reason:" + e.getMessage());
|
||||
}
|
||||
finally {
|
||||
closeReversedReader(reversedReader);
|
||||
}
|
||||
Collections.reverse(entries);
|
||||
return entries.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void closeReversedReader(ReversedLinesFileReader reversedReader) {
|
||||
if (reversedReader != null) {
|
||||
try {
|
||||
reversedReader.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
logger.warning("Cloud not close ReversedLinesFileReader: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new jline ConsoleReader. On Windows if jansi is available, uses createAnsiWindowsReader(). Otherwise,
|
||||
* always creates a default ConsoleReader. Sub-classes of this class can plug in their version of ConsoleReader by
|
||||
* overriding this method, if required.
|
||||
*
|
||||
* @return a jline ConsoleReader instance
|
||||
*/
|
||||
protected ConsoleReader createConsoleReader() {
|
||||
ConsoleReader consoleReader = null;
|
||||
try {
|
||||
if (isJansiAvailable()) {
|
||||
try {
|
||||
consoleReader = createAnsiWindowsReader();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Try again using default ConsoleReader constructor
|
||||
logger.warning("Can't initialize jansi AnsiConsole, falling back to default: " + e);
|
||||
}
|
||||
}
|
||||
if (consoleReader == null) {
|
||||
consoleReader = new ConsoleReader();
|
||||
}
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new IllegalStateException("Cannot start console class", ioe);
|
||||
}
|
||||
consoleReader.setExpandEvents(false);
|
||||
consoleReader.setHandleUserInterrupt(true);
|
||||
return consoleReader;
|
||||
}
|
||||
|
||||
private boolean isJansiAvailable() {
|
||||
return JANSI_AVAILABLE && OsUtils.isWindows() && System.getProperty("jline.terminal") == null;
|
||||
}
|
||||
|
||||
public void printBannerAndWelcome() {
|
||||
}
|
||||
|
||||
public String getStartupNotifications() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void removeHandlers(final Logger l) {
|
||||
Handler[] handlers = l.getHandlers();
|
||||
if (handlers != null && handlers.length > 0) {
|
||||
for (Handler h : handlers) {
|
||||
l.removeHandler(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPromptPath(final String path) {
|
||||
setPromptPath(path, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPromptPath(final String path, final boolean overrideStyle) {
|
||||
if (reader.getTerminal().isAnsiSupported()) {
|
||||
// ANSIBuffer ansi = JLineLogHandler.getANSIBuffer();
|
||||
Ansi ansi = ansi();
|
||||
if (path == null || "".equals(path)) {
|
||||
shellPrompt = ansi.fg(Color.YELLOW).a(getPromptText()).reset().toString();
|
||||
}
|
||||
else {
|
||||
if (overrideStyle) {
|
||||
ansi.a(path);
|
||||
}
|
||||
else {
|
||||
ansi.fg(Color.CYAN).a(path).reset();
|
||||
}
|
||||
shellPrompt = ansi.fg(Color.YELLOW).a(" " + getPromptText()).toString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The superclass will do for this non-ANSI terminal
|
||||
super.setPromptPath(path);
|
||||
}
|
||||
|
||||
// The shellPrompt is now correct; let's ensure it now gets used
|
||||
reader.setPrompt(AbstractShell.shellPrompt);
|
||||
}
|
||||
|
||||
protected ConsoleReader createAnsiWindowsReader() throws Exception {
|
||||
// Get decorated OutputStream that parses ANSI-codes
|
||||
final PrintStream ansiOut = (PrintStream) ClassUtils
|
||||
.forName(ANSI_CONSOLE_CLASSNAME, JLineShell.class.getClassLoader()).getMethod("out").invoke(null);
|
||||
WindowsTerminal ansiTerminal = new WindowsTerminal() {
|
||||
@Override
|
||||
public synchronized boolean isAnsiSupported() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
ansiTerminal.init();
|
||||
// Make sure to reset the original shell's colors on shutdown by closing the stream
|
||||
statusListener = new ShellStatusListener() {
|
||||
public void onShellStatusChange(final ShellStatus oldStatus, final ShellStatus newStatus) {
|
||||
if (newStatus.getStatus().equals(Status.SHUTTING_DOWN)) {
|
||||
ansiOut.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
addShellStatusListener(statusListener);
|
||||
|
||||
// return new ConsoleReader(new FileInputStream(FileDescriptor.in), new PrintWriter(new OutputStreamWriter(
|
||||
// ansiOut,
|
||||
// // Default to Cp850 encoding for Windows console output (ROO-439)
|
||||
// System.getProperty("jline.WindowsTerminal.output.encoding", "Cp850"))), null, ansiTerminal);
|
||||
|
||||
OutputStream out = AnsiConsole.wrapOutputStream(ansiOut);
|
||||
return new ConsoleReader(new FileInputStream(FileDescriptor.in), out, ansiTerminal);
|
||||
}
|
||||
|
||||
private void flashMessageRenderer() {
|
||||
if (!reader.getTerminal().isAnsiSupported()) {
|
||||
return;
|
||||
}
|
||||
// Setup a thread to ensure flash messages are displayed and cleared correctly
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
while (!shellStatus.getStatus().equals(Status.SHUTTING_DOWN) && !shutdownHookFired) {
|
||||
synchronized (flashInfoMap) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Set<String> toRemove = new HashSet<String>();
|
||||
for (String slot : flashInfoMap.keySet()) {
|
||||
FlashInfo flashInfo = flashInfoMap.get(slot);
|
||||
|
||||
if (flashInfo.flashMessageUntil < now) {
|
||||
// Message has expired, so clear it
|
||||
toRemove.add(slot);
|
||||
doAnsiFlash(flashInfo.rowNumber, Level.ALL, "");
|
||||
}
|
||||
else {
|
||||
// The expiration time for this message has not been reached, so preserve it
|
||||
doAnsiFlash(flashInfo.rowNumber, flashInfo.flashLevel, flashInfo.flashMessage);
|
||||
}
|
||||
}
|
||||
for (String slot : toRemove) {
|
||||
flashInfoMap.remove(slot);
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, getProductName() + " JLine Flash Message Manager");
|
||||
t.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flash(final Level level, final String message, final String slot) {
|
||||
Assert.notNull(level, "Level is required for a flash message");
|
||||
Assert.notNull(message, "Message is required for a flash message");
|
||||
Assert.hasText(slot, "Slot name must be specified for a flash message");
|
||||
|
||||
if (Shell.WINDOW_TITLE_SLOT.equals(slot)) {
|
||||
if (reader != null && reader.getTerminal().isAnsiSupported()) {
|
||||
// We can probably update the window title, as requested
|
||||
if (!StringUtils.hasText(message)) {
|
||||
System.out.println("No text");
|
||||
}
|
||||
|
||||
Ansi ansi = ansi();
|
||||
ansi.a(ESCAPE + "]0;").a(message).a(BEL);
|
||||
try {
|
||||
reader.print(ansi.toString());
|
||||
reader.flush();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if ((reader != null && !reader.getTerminal().isAnsiSupported())) {
|
||||
super.flash(level, message, slot);
|
||||
return;
|
||||
}
|
||||
synchronized (flashInfoMap) {
|
||||
FlashInfo flashInfo = flashInfoMap.get(slot);
|
||||
|
||||
if ("".equals(message)) {
|
||||
// Request to clear the message, but give the user some time to read it first
|
||||
if (flashInfo == null) {
|
||||
// We didn't have a record of displaying it in the first place, so just quit
|
||||
return;
|
||||
}
|
||||
flashInfo.flashMessageUntil = System.currentTimeMillis() + 1500;
|
||||
}
|
||||
else {
|
||||
// Display this message displayed until further notice
|
||||
if (flashInfo == null) {
|
||||
// Find a row for this new slot; we basically take the first line number we discover
|
||||
flashInfo = new FlashInfo();
|
||||
flashInfo.rowNumber = Integer.MAX_VALUE;
|
||||
outer: for (int i = 1; i < Integer.MAX_VALUE; i++) {
|
||||
for (FlashInfo existingFlashInfo : flashInfoMap.values()) {
|
||||
if (existingFlashInfo.rowNumber == i) {
|
||||
// Veto, let's try the new candidate row number
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
// If we got to here, nobody owns this row number, so use it
|
||||
flashInfo.rowNumber = i;
|
||||
break outer;
|
||||
}
|
||||
|
||||
// Store it
|
||||
flashInfoMap.put(slot, flashInfo);
|
||||
}
|
||||
// Populate the instance with the latest data
|
||||
flashInfo.flashMessageUntil = Long.MAX_VALUE;
|
||||
flashInfo.flashLevel = level;
|
||||
flashInfo.flashMessage = message;
|
||||
|
||||
// Display right now
|
||||
doAnsiFlash(flashInfo.rowNumber, flashInfo.flashLevel, flashInfo.flashMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Externally synchronized via the two calling methods having a mutex on flashInfoMap
|
||||
private void doAnsiFlash(final int row, final Level level, final String message) {
|
||||
Ansi ansi = ansi();
|
||||
if (isAppleTerminal()) {
|
||||
ansi.a(ESCAPE + "7");
|
||||
}
|
||||
else {
|
||||
ansi.saveCursorPosition();
|
||||
}
|
||||
|
||||
// Figure out the longest line we're presently displaying (or were) and erase the line from that position
|
||||
int mostFurtherLeftColNumber = Integer.MAX_VALUE;
|
||||
for (Integer candidate : rowErasureMap.values()) {
|
||||
if (candidate < mostFurtherLeftColNumber) {
|
||||
mostFurtherLeftColNumber = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
if (mostFurtherLeftColNumber == Integer.MAX_VALUE) {
|
||||
// There is nothing to erase
|
||||
}
|
||||
else {
|
||||
ansi.cursor(row, mostFurtherLeftColNumber);
|
||||
ansi.eraseLine(Erase.FORWARD); // Clear what was present on the line
|
||||
}
|
||||
|
||||
if (("".equals(message))) {
|
||||
// They want the line blank; we've already achieved this if needed via the erasing above
|
||||
// Just need to record we no longer care about this line the next time doAnsiFlash is invoked
|
||||
rowErasureMap.remove(row);
|
||||
}
|
||||
else {
|
||||
if (shutdownHookFired) {
|
||||
return; // ROO-1599
|
||||
}
|
||||
// They want some message displayed
|
||||
int startFrom = reader.getTerminal().getWidth() - message.length() + 1;
|
||||
if (startFrom < 1) {
|
||||
startFrom = 1;
|
||||
}
|
||||
ansi.cursor(row, startFrom);
|
||||
ansi.a(Attribute.NEGATIVE_ON).a(message).a(Attribute.NEGATIVE_OFF);
|
||||
// Record we want to erase from this positioning next time (so we clean up after ourselves)
|
||||
rowErasureMap.put(row, startFrom);
|
||||
}
|
||||
if (isAppleTerminal()) {
|
||||
ansi.a(ESCAPE + "8");
|
||||
}
|
||||
else {
|
||||
ansi.restorCursorPosition();
|
||||
}
|
||||
|
||||
try {
|
||||
reader.print(ansi.toString());
|
||||
reader.flush();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Awaits user input, executes the command and displays the prompt to the user.
|
||||
*/
|
||||
public void promptLoop() {
|
||||
setShellStatus(Status.USER_INPUT);
|
||||
String line = null;
|
||||
String prompt = getPromptText();
|
||||
|
||||
try {
|
||||
while (exitShellRequest == null) {
|
||||
try {
|
||||
line = reader.readLine();
|
||||
}
|
||||
catch (UserInterruptException e) {
|
||||
if (e.getPartialLine().length() == 0) {
|
||||
exitShellRequest = ExitShellRequest.FATAL_EXIT;
|
||||
}
|
||||
}
|
||||
JLineLogHandler.resetMessageTracking();
|
||||
setShellStatus(Status.USER_INPUT);
|
||||
|
||||
if (StringUtils.hasText(line)) {
|
||||
executeCommand(line);
|
||||
}
|
||||
//update the prompt after the command has been executed in case an application event listener in the
|
||||
//command changes state in the prompt provider.
|
||||
prompt = generatePromptUpdate(prompt);
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new IllegalStateException("Shell line reading failure", ioe);
|
||||
}
|
||||
setShellStatus(Status.SHUTTING_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the latest prompt and if the latest prompt is different than the existing prompt,
|
||||
* the shellPrompt is updated.
|
||||
* @param existingPrompt The prompt that is recognized as the current prompt.
|
||||
* @return The prompt that the shellPrompt displays.
|
||||
*/
|
||||
public String generatePromptUpdate(String existingPrompt) {
|
||||
String newPrompt = getPromptText();
|
||||
if (!ObjectUtils.nullSafeEquals(existingPrompt, newPrompt)) {
|
||||
setPromptPath(null);
|
||||
}
|
||||
return newPrompt;
|
||||
}
|
||||
|
||||
public void setDevelopmentMode(final boolean developmentMode) {
|
||||
JLineLogHandler.setIncludeThreadName(developmentMode);
|
||||
JLineLogHandler.setSuppressDuplicateMessages(!developmentMode); // We want to see duplicate messages during
|
||||
// development time (ROO-1873)
|
||||
this.developmentMode = developmentMode;
|
||||
}
|
||||
|
||||
public boolean isDevelopmentMode() {
|
||||
return this.developmentMode;
|
||||
}
|
||||
|
||||
private void openFileLogIfPossible() {
|
||||
try {
|
||||
fileLog = new FileWriter(getHistoryFileName(), true);
|
||||
// First write, so let's record the date and time of the first user command
|
||||
fileLog.write("// " + getProductName() + " " + versionInfo() + " log opened at " + df.format(new Date())
|
||||
+ "\n");
|
||||
fileLog.flush();
|
||||
}
|
||||
catch (IOException ignoreIt) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logCommandToOutput(final String processedLine) {
|
||||
if (fileLog == null) {
|
||||
openFileLogIfPossible();
|
||||
if (fileLog == null) {
|
||||
// Still failing, so give up
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
fileLog.write(processedLine + "\n"); // Unix line endings only from Roo
|
||||
fileLog.flush(); // So tail -f will show it's working
|
||||
if (getExitShellRequest() != null) {
|
||||
// Shutting down, so close our file (we can always reopen it later if needed)
|
||||
fileLog.write("// " + getProductName() + " " + versionInfo() + " log closed at "
|
||||
+ df.format(new Date()) + "\n");
|
||||
IOUtils.closeQuietly(fileLog);
|
||||
fileLog = null;
|
||||
}
|
||||
}
|
||||
catch (IOException ignoreIt) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the "roo.home" from the system property, falling back to the current working directory if missing.
|
||||
*
|
||||
* @return the 'roo.home' system property
|
||||
*/
|
||||
@Override
|
||||
protected String getHomeAsString() {
|
||||
String rooHome = System.getProperty("roo.home");
|
||||
if (rooHome == null) {
|
||||
try {
|
||||
rooHome = new File(".").getCanonicalPath();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return rooHome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by a subclass before deactivating the shell.
|
||||
*/
|
||||
protected void closeShell() {
|
||||
// Notify we're closing down (normally our status is already shutting_down, but if it was a CTRL+C via the
|
||||
// o.s.r.bootstrap.Main hook)
|
||||
setShellStatus(Status.SHUTTING_DOWN);
|
||||
if (statusListener != null) {
|
||||
removeShellStatusListener(statusListener);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlashInfo {
|
||||
String flashMessage;
|
||||
|
||||
long flashMessageUntil;
|
||||
|
||||
Level flashLevel;
|
||||
|
||||
int rowNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* get history file name from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return history file name
|
||||
*/
|
||||
abstract protected String getHistoryFileName();
|
||||
|
||||
/**
|
||||
* get prompt text from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return prompt text
|
||||
*/
|
||||
abstract protected String getPromptText();
|
||||
|
||||
/**
|
||||
* get product name
|
||||
*
|
||||
* @return Product Name
|
||||
*/
|
||||
abstract protected String getProductName();
|
||||
|
||||
/**
|
||||
* get version information
|
||||
*
|
||||
* @return Version
|
||||
*/
|
||||
protected String getVersion() {
|
||||
return VersionUtils.versionInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the historySize
|
||||
*/
|
||||
public int getHistorySize() {
|
||||
return historySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param historySize the historySize to set
|
||||
*/
|
||||
public void setHistorySize(int historySize) {
|
||||
this.historySize = historySize;
|
||||
}
|
||||
|
||||
private static boolean isAppleTerminal() {
|
||||
final String terminalName = System.getenv("TERM_PROGRAM");
|
||||
return ("Apple_Terminal".equalsIgnoreCase(terminalName) || Boolean.getBoolean("is.apple.terminal"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
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.SmartLifecycle;
|
||||
import org.springframework.shell.CommandLine;
|
||||
import org.springframework.shell.plugin.BannerProvider;
|
||||
import org.springframework.shell.plugin.HistoryFileNameProvider;
|
||||
import org.springframework.shell.plugin.PluginUtils;
|
||||
import org.springframework.shell.plugin.PromptProvider;
|
||||
|
||||
/**
|
||||
* Launcher for {@link JLineShell}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.1
|
||||
*/
|
||||
public class JLineShellComponent extends JLineShell implements SmartLifecycle, ApplicationContextAware, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private CommandLine commandLine;
|
||||
|
||||
private volatile boolean running = false;
|
||||
private Thread shellThread;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private boolean printBanner = true;
|
||||
|
||||
private String historyFileName;
|
||||
private String promptText;
|
||||
private String productName;
|
||||
private String banner;
|
||||
private String version;
|
||||
private String welcomeMessage;
|
||||
|
||||
private ExecutionStrategy executionStrategy = new SimpleExecutionStrategy();
|
||||
private SimpleParser parser = new SimpleParser();
|
||||
|
||||
public SimpleParser getSimpleParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stop(Runnable callback) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
|
||||
public int getPhase() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
//customizePlug must run before start thread to take plugin's configuration into effect
|
||||
customizePlugin();
|
||||
shellThread = new Thread(this, "Spring Shell");
|
||||
shellThread.start();
|
||||
running = true;
|
||||
}
|
||||
|
||||
|
||||
public void stop() {
|
||||
if (running) {
|
||||
closeShell();
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
Map<String, CommandMarker> commands = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, CommandMarker.class);
|
||||
for (CommandMarker command : commands.values()) {
|
||||
getSimpleParser().add(command);
|
||||
}
|
||||
|
||||
Map<String, Converter> converters = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, Converter.class);
|
||||
for (Converter<?> converter : converters.values()) {
|
||||
getSimpleParser().add(converter);
|
||||
}
|
||||
|
||||
setHistorySize(commandLine.getHistorySize());
|
||||
if (commandLine.getShellCommandsToExecute() != null) {
|
||||
setPrintBanner(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wait the shell command to complete by typing "quit" or "exit"
|
||||
*
|
||||
*/
|
||||
public void waitForComplete() {
|
||||
try {
|
||||
shellThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExecutionStrategy getExecutionStrategy() {
|
||||
return executionStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parser getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStartupNotifications() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void customizePlugin() {
|
||||
this.historyFileName = getHistoryFileName();
|
||||
this.promptText = getPromptText();
|
||||
String[] banner = getBannerText();
|
||||
this.banner = banner[0];
|
||||
this.welcomeMessage = banner[1];
|
||||
this.version = banner[2];
|
||||
this.productName = banner[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* get history file name from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return history file name
|
||||
*/
|
||||
protected String getHistoryFileName() {
|
||||
HistoryFileNameProvider historyFileNameProvider = PluginUtils.getHighestPriorityProvider(this.applicationContext,HistoryFileNameProvider.class);
|
||||
String providerHistoryFileName = historyFileNameProvider.getHistoryFileName();
|
||||
if (providerHistoryFileName != null) {
|
||||
return providerHistoryFileName;
|
||||
} else {
|
||||
return historyFileName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get prompt text from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return prompt text
|
||||
*/
|
||||
protected String getPromptText() {
|
||||
PromptProvider promptProvider = PluginUtils.getHighestPriorityProvider(this.applicationContext,PromptProvider.class);
|
||||
String providerPromptText = promptProvider.getPrompt();
|
||||
if (providerPromptText != null) {
|
||||
return providerPromptText;
|
||||
} else {
|
||||
return promptText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Banner and Welcome Message from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
* @return BannerText[0]: Banner
|
||||
* BannerText[1]: Welcome Message
|
||||
* BannerText[2]: Version
|
||||
* BannerText[3]: Product Name
|
||||
*/
|
||||
private String[] getBannerText() {
|
||||
String[] bannerText = new String[4];
|
||||
BannerProvider provider = PluginUtils.getHighestPriorityProvider(this.applicationContext,BannerProvider.class);
|
||||
bannerText[0] = provider.getBanner();
|
||||
bannerText[1] = provider.getWelcomeMessage();
|
||||
bannerText[2] = provider.getVersion();
|
||||
bannerText[3] = provider.getProviderName();
|
||||
return bannerText;
|
||||
}
|
||||
|
||||
|
||||
public void printBannerAndWelcome() {
|
||||
if (printBanner) {
|
||||
logger.info(this.banner);
|
||||
logger.info(getWelcomeMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the welcome message at start.
|
||||
*
|
||||
* @return welcome message
|
||||
*/
|
||||
public String getWelcomeMessage() {
|
||||
return this.welcomeMessage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param printBanner the printBanner to set
|
||||
*/
|
||||
public void setPrintBanner(boolean printBanner) {
|
||||
this.printBanner = printBanner;
|
||||
}
|
||||
|
||||
protected String getProductName() {
|
||||
return productName;
|
||||
}
|
||||
|
||||
protected String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A method that can be executed via a shell command.
|
||||
* <p>
|
||||
* Immutable since 1.2.0.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class MethodTarget {
|
||||
|
||||
// Fields
|
||||
private final Method method;
|
||||
|
||||
private final Object target;
|
||||
|
||||
private final String remainingBuffer;
|
||||
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* Constructor for a <code>null remainingBuffer</code> and <code>key</code>
|
||||
*
|
||||
* @param method the method to invoke (required)
|
||||
* @param target the object on which the method is to be invoked (required)
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public MethodTarget(final Method method, final Object target) {
|
||||
this(method, target, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that allows all fields to be set
|
||||
*
|
||||
* @param method the method to invoke (required)
|
||||
* @param target the object on which the method is to be invoked (required)
|
||||
* @param remainingBuffer can be blank
|
||||
* @param key can be blank
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public MethodTarget(final Method method, final Object target, final String remainingBuffer, final String key) {
|
||||
Assert.notNull(method, "Method is required");
|
||||
Assert.notNull(target, "Target is required");
|
||||
this.key = StringUtils.trimWhitespace(key);
|
||||
this.method = method;
|
||||
this.remainingBuffer = remainingBuffer;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof MethodTarget)) {
|
||||
return false;
|
||||
}
|
||||
final MethodTarget otherMethodTarget = (MethodTarget) other;
|
||||
return this.method.equals(otherMethodTarget.getMethod()) && this.target.equals(otherMethodTarget.getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(method) + ObjectUtils.nullSafeHashCode(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
final ToStringCreator tsc = new ToStringCreator(this);
|
||||
tsc.append("target", target);
|
||||
tsc.append("method", method);
|
||||
tsc.append("remainingBuffer", remainingBuffer);
|
||||
tsc.append("key", key);
|
||||
return tsc.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a non-<code>null</code> method
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public Method getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public String getRemainingBuffer() {
|
||||
return this.remainingBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a non-<code>null</code> Object
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public Object getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.shell.event.ParseResult;
|
||||
|
||||
/**
|
||||
* Interface for {@link SimpleParser}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Alan Stewart
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface Parser {
|
||||
|
||||
ParseResult parse(String buffer);
|
||||
|
||||
/**
|
||||
* Populates a list of completion candidates. This method is required for backward compatibility for STS versions up to 2.8.0.
|
||||
*
|
||||
* @param buffer
|
||||
* @param cursor
|
||||
* @param candidates
|
||||
* @return
|
||||
*/
|
||||
int complete(String buffer, int cursor, List<String> candidates);
|
||||
|
||||
/**
|
||||
* Populates a list of completion candidates.
|
||||
*
|
||||
* @param buffer
|
||||
* @param cursor
|
||||
* @param candidates
|
||||
* @return
|
||||
*/
|
||||
int completeAdvanced(String buffer, int cursor, List<Completion> candidates);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user