<Void,Node>
command to a <Node,Void>
command through a pipe<Void,Node>
command to two <Node,Void>
commands through a pipe<Void,Node>
command to a <Node,Void>
commands through a pipeThe Common Reusable SHell (CRaSH) deploys in a Java runtime and provides interactions with the JVM. Commands are written in Groovy and can be developped at runtime making the extension of the shell very easy with fast development cycle.
CRaSH provides has various ways to be started, it can even be easilty embedded.
CRaSH can use a standard web archive to be deployed in a web container. The war file is used for its packaging capabilities and triggering the CRaSH life cycle start/stop. In this mode CRaSH has two packaging available:
A core war file found under deploy/core/crash.war provides the base CRaSH functionnalities.
A GateIn war file found under deploy/gatein/crash.war provides the additional JCR features but deploys only in a GateIn server (Tomcat or JBoss)
You have to copy the crash.war in the appropriate server, regardless of the packaging you use.
The standalone mode allows you to run CRaSH from the command line. For this matter a few special jars are made available to you. Each jar adds a functionnality when it is added on the classpath, also each jar embeds its dependencies in order to save you the burden of having a long classpath
to continue
You need to connect using telnet, SSH to use the shell, there is a third special mode using the JVM input and output.
Telnet connection is done on port 5000:
(! 520)-> telnet localhost 5000 Trying ::1... Connected to localhost. Escape character is '^]'. ______ .~ ~. |`````````, .'. ..'''' | | | |'''|''''' .''```. .'' |_________| | | `. .' `. ..' | | `.______.' | `. .' `. ....'' | | 1.0.0-beta18-SNAPSHOT Follow and support the project on http://crsh.googlecode.com Welcome to julien.local + ! It is Fri Dec 03 16:20:40 CET 2010 now
The bye
command disconnect from the shell.
SSH connection is done on port 2000 with the password crash :
juliens-macbook-pro:~ julien$ ssh -p 2000 -l root localhost root@localhost's password: CRaSH 1.0.0-beta18-SNAPSHOT (http://crsh.googlecode.com) Welcome to juliens-macbook-pro.local! It is Fri Jan 08 21:12:53 CET 2010 now. %
The bye
command disconnect from the shell.
Line edition: the current line can be edited via left and right arrow keys
History: the key up and key down enable history browsing
Quoting: simple quotes or double quotes allow to insert blanks in command options and arguments, for instance "old boy" or 'old boy'. One quote style can quote another, like "ol' boy".
Completion: an advanced completion system is available
The help
command will display the list of known commands by the shell.
[/]% help Try one of these commands with the -h or --help switch [addmixin, cd, checkin, checkout, commit, connect, disconnect, exportnode, help, importnode, ls, pwd, rm, rollback, select, set]
The basic CRaSH usage is like any shell, you just type a command with its options and arguments. However it is possible to compose commands and create powerful combinations.
Typing the command followed by options and arguments will do the job
% ls -d / ...
Any command help can be displayed by using the -h argument:
% ls -h List the content of a node VAL : Path of the node content to list -d (--depth) N : Print depth
A CRaSH command is able to consume and produce a stream of object, allowing complex interactions between commands where they can exchange stream of compatible objets. Most of the time, JCR nodes are the objects exchanged by the commands but any command is free to produce or consume any type.
By default a command that does not support this feature does not consumer or produce anything. Such commands usually inherits from the org.crsh.command.ClassCommand
class that does not care about it. If you look at this class you will see it extends the the org.crsh.command.BaseCommand
.
More advanced commands inherits from org.crsh.command.BaseCommand
class that specifies two generic types <C>
and <P>
:
<C>
is the type of the object that the command consumes
<P>
is the type of the object that the command produces
The command composition provides two operators:
The pipe operator | allows to stream a command output stream to a command input stream
The distribution operator + allows to distribute an input stream to several commands and to combine the output stream of several commands into a single stream.
Example 1.2. Update the security of all nt:unstructed nodes
% select * from nt:unstructured | setperm -i any -a read + setperm -i any -a write
Example 1.3. Add the mixin mix:referenceable to any node of type nt:file or nt:folder
% select * from nt:file + select * from nt:folder | addmixin mix:referenceable
When a command does not consume a stream but is involved in a distribution it will not receive any stream but will be nevertheless invoked.
Likewise when a command does not produce a stream but is involved in a distribution, it will not produce anything but will be nevertheless invoked.
NAME sleep main - Sleep for some time SYNOPSIS sleep [-h | --help] [-h | --help] main time PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage time Sleep time in seconds
NAME man main - format and display the on-line manual pages SYNOPSIS man [-h | --help] [-h | --help] main command PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage command the command
NAME log SYNOPSIS log [-h | --help] [-h | --help] COMMAND [ARGS] PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage COMMANDS add create one or several loggers set The set command sets the level of a logger. One or several logger names can be specified as arguments and the -l option specify the level among the trace, debug, info, warn and error levels. When no level is specified, the level is cleared and the level will be inherited from its ancestors. % logset -l trace foo % logset foo The logger name can be omitted and instead stream of logger can be consumed as it is a <Logger,Void> command. The following set the level warn on all the available loggers: % log ls | log set -l warn send The send command log one or several loggers with a specified message. For instance the following impersonates the javax.management.mbeanserver class and send a message on its own logger. #% log send -m hello javax.management.mbeanserver Send is a <Logger, Void> command, it can log messages to consumed log objects: % log ls | log send -m hello -l warn info The loginfo command displays information about one or several loggers. % loginfo javax.management.modelmbean javax.management.modelmbean<INFO> The loginfo command is a <Logger,Void> command and it can consumed logger produced by the logls command: % logls -f javax.* | loginfo javax.management.mbeanserver<INFO> javax.management.modelmbean<INFO> ls The logls command list all the available loggers., for instance: % logls org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/].[default] org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/eXoGadgetServer].[concat] org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dashboard].[jsp] ... The -f switch provides filtering with a Java regular expression % logls -f javax.* javax.management.mbeanserver javax.management.modelmbean The logls command is a <Void,Logger> command, therefore any logger produced can be consumed.
NAME ws SYNOPSIS ws [-h | --help] [-h | --help] COMMAND [ARGS] DESCRIPTION The ws command provides a set of commands interacting with JCR workspace. PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage COMMANDS login This command login to a JCR workspace and establish a session with the repository. When you are connected the shell maintain a JCR session and allows you to interact with the session in a shell oriented fashion. The repository name must be specified and optionally you can specify a user name and password to have more privileges. % connect -c portal portal-system Connected to workspace portal-system % connect -c portal -u root -p gtn portal-system Connected to workspace portal-system logout This command logout from the currently connected JCR workspace
NAME cd main - changes the current node SYNOPSIS cd [-h | --help] [-h | --help] main path DESCRIPTION The cd command changes the current node path. The command used with no argument changes to the root node. A relative or absolute path argument can be provided to specify a new current node path. [/]% cd /gadgets [/gadgets]% cd /gadgets [/gadgets]% cd [/]% PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage path a node path
NAME ls main - list the content of a node SYNOPSIS ls [-h | --help] [-h | --help] main [-d | --depth] [-d | --depth] path DESCRIPTION The ls command displays the content of a node. By default it lists the content of the current node, however it also accepts a path argument that can be absolute or relative. [/]% ls / +-properties | +-jcr:primaryType: nt:unstructured | +-jcr:mixinTypes: [exo:owneable,exo:privilegeable] | +-exo:owner: '__system' | +-exo:permissions: [any read,*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administrators set_property,*:/platform/administrators remove] +-children | +-/workspace | +-/contents | +-/Users | +-/gadgets | +-/folder PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage [-d | --depth] Print depth path the path of the node content to list
NAME node SYNOPSIS node [-h | --help] [-h | --help] COMMAND [ARGS] PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage COMMANDS add The addnode command creates one or several nodes. The command takes at least one node as argument, but it can take more. Each path can be either absolute or relative, relative path creates nodes relative to the current node. By default the node type is the default repository node type, but the option -t can be used to specify another one. [/registry]% addnode foo Node /foo created [/registry]% addnode -t nt:file bar juu Node /bar /juu created The addnode command is a <Void,Node> command that produces all the nodes that were created. import Imports a node from an nt:file node located in the workspace: [/]% importnode /gadgets.xml / Node imported export Exports a node as an nt file in the same workspace: [/]% node export gadgets /gadgets.xml The node has been exported
NAME mixin SYNOPSIS mixin [-h | --help] [-h | --help] COMMAND [ARGS] DESCRIPTION The mixin command manipulates JCR node mixins. Mixins can be added to or removed from nodes. PARAMETERS [-h | --help] Provides command usage [-h | --help] Provides command usage COMMANDS add The add command addds a mixin to one or several nodes, this command is a <Node,Void> command, and can add a mixin from an incoming node stream, for instance: [/]% select * from mynode | mixin add mix:versionable remove The remove command removes a mixin from one or several nodes, this command is a <Node,Void> command, and can remove a mixin from an incoming node stream, for instance: [/]% select * from mynode | mixin remove mix:versionable
CRaSH can be configured by tweaking various files of the CRaSH web archive
WEB-INF/web.xml
WEB-INF/groovy/login.groovy
Note that to fully secure the server, you should remove the unauthenticated telnet access as describe below.
The key can be changed by replacing the file WEB-INF/sshd/hostkey.pem. Alternatively you can configure the server to use an external file by using the ssh.keypath parameter. Uncomment the XML section and change the path to the key file.
<!--
<context-param>
<param-name>ssh.keypath</param-name>
<param-value>/path/to/the/key/file</param-value>
<description>The path to the key file</description>
</context-param>
-->
The ports of the server are parameterized by the ssh.port and telnet.port parameters in the web.xml file
<context-param> <param-name>ssh.port</param-name> <param-value>2000</param-value> <description>The SSH port</description> </context-param>
<context-param> <param-name>telnet.port</param-name> <param-value>5000</param-value> <description>The telnet port</description> </context-param>
To remove the telnet access, remove or comment the following XML from the web.xml file
<listener> <listener-class>org.crsh.term.spi.telnet.TelnetLifeCycle</listener-class> </listener>
To remove the SSH access, remove or comment the following XML from the web.xml file
<listener> <listener-class>org.crsh.term.spi.sshd.SSHLifeCycle</listener-class> </listener>
The shell command system is based on the Groovy language and can easily be extended.
Each command has a corresponding Groovy file that contains a command class that will be invoked by the shell. The files are located in the /WEB-INF/groovy/commands directory and new files can be added here.
In addition of that there are two special files called login.groovy and logout.groovy in the /WEB-INF/groovy directory that are executed upon login and logout of a user. Those files can be studied to understand better how the shell works.
When the user types a command in the sell, the command line is parsed by the args4j framework and injected in the command class. A simple example, the command connect -c portal -u root -p gtn portal-system
creates the connect command instance and args4j injects the options and arguments on the class:
@Description("Connect to a workspace") class connect extends org.crsh.command.ClassCommand { @Option(name="-u",aliases=["--username"],usage="user name") def String userName; @Option(name="-p",aliases=["--password"],usage="password") def String password; @Option(name="-c",aliases=["--container"],usage="portal container name (eXo portal specific)") def String containerName; @Argument(required=true,index=0,usage="workspace name") def String workspaceName; public Object execute() throws ScriptException { ... } }
A command is a Groovy object and it can access or use the contextual variables. A few variables are maintained by the shell and should be considered with caution. The shell also provides a few functions that can be used, those functions defined in login.groovy
The session
variable is managed by the connect
and disconnect
commands. Commands should be able to use it for accessing JCR session but not update this variable.
The currentPath
variable contains the current path of the shell and it should not be used directly. Instead one should use the function getCurrentNode()
and setCurrentNode(Node node)
to update the underlying path.
The assertConnected()
checks that the user is connected. It should be used at the beginning of a command that interacts with the session
The getCurrentNode()
returns the current node
The setCurrentNode(Node node)
updates the current node
The findNodeByPath()
functions returns a node based on the provided path. If the provided path is null then the "/" root path is considered. The path can be either relative or absolute. If the path is relative the current node will be used to find the node.
The formatValue(Value value)
formats a JCR value into a suitable text value.
The formatPropertyValue(Property property)
formats a JCR property value into a suitable text value. If the property is multiple then it will return a comma separated list surrounded by square brackets.