Remove everything prior to Shell 2 migration

This commit is contained in:
Eric Bottard
2017-08-08 11:04:41 +02:00
parent 7424ccad05
commit 3cd5a1be3b
233 changed files with 0 additions and 17574 deletions

17
.gitignore vendored
View File

@@ -1,17 +0,0 @@
/.classpath
/.project
.settings/
.gradle
build
target/
/log.roo
/bin/
/*.log
/.idea
/*.iml
/*.ipr
/*.iws
out
.gradletasknamecache

View File

@@ -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>

View File

@@ -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.

View File

@@ -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

View File

@@ -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>

View File

@@ -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;}

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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">&lt;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"&gt;
&lt;context:component-scan
base-package="org.springframework.shell.samples.helloworld.commands" /&gt;
&lt;/beans&gt;</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&gt;</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>

View File

@@ -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>

View File

@@ -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>&lt;spring-shell-install-dir&gt;/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>

View File

@@ -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

Binary file not shown.

View File

@@ -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
View File

@@ -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
View File

@@ -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

View File

@@ -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'
}
}
}
}
}

View File

@@ -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.

View File

@@ -1,8 +0,0 @@
/.classpath
/.project
.settings/
target/
/log.roo
*.log
/bin/

View File

@@ -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>

View File

@@ -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'
}

View File

@@ -1,7 +0,0 @@
springShellVersion = 1.2.0.RELEASE
junitVersion = 4.10
log4jVersion = 1.2.17
version = 1.0.0.RELEASE

View File

@@ -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

View File

@@ -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 "$@"

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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";
}
}

View File

@@ -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";
}
}

View File

@@ -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";
}
}

View File

@@ -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>

View File

@@ -1 +0,0 @@
log4j.rootCategory=OFF

View File

@@ -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());
}
}

View File

@@ -1 +0,0 @@
rootProject.name = 'spring-shell'

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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]");
}
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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() {}
}

View File

@@ -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() + "]");
}
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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"));
}
}

View File

@@ -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());
}
}
}

View File

@@ -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 {}

View File

@@ -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 + "]";
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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"));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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