CRaSH is a shell for Java Content Repository that comes bundled as a war file to deploy in eXo Portal 2.5 or GateIn. It provides a file system view of a repository.
You need to connect using telnet or SSH to use the shell.
Telnet connection is done on port 5000:
juliens-macbook-pro:webapps julien$ telnet localhost 5000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Welcome to juliens-macbook-pro.local! It is Mon Nov 23 15:53:44 CET 2009 now. %
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-beta12 (http://crsh.googlecode.com) Welcome to juliens-macbook-pro.local! It is Fri Jan 08 21:12:53 CET 2010 now. %
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".
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]
You must first connect to a repository before any other JCR based operation. When you are connected the shell will maintain a JCR session and allows you to interact with the session in a shell oriented fashion. The connect command is used to perform the connection. 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
or
% connect -c portal -u root -p gtn portal-system Connected to workspace portal-system
The ls command shows the content of a node. By default it lists the content of the current node. It can accept 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
The cd command allows to change the current path. The command used with no argument, change to the root directory but you can provide a path argument that can be absolute or relative.
[/]% cd /gadgets /gadgets
The pwd command shows the current node path.
[/gadgets]% pwd /gadgets
The addnode command creates one of 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 cp command copies a node to a target location in the JCR tree.
[/registry]% cp Registry Registry2
The mv command can move a node to a target location in the JCR tree. It can be used also to rename a node.
[/registry]% mv Registry Registry2
The rm command removes a node or property specified by its path either absolute or relative. This operation is executed against the JCR session, meaning that it will not be effective until it is commited to the JCR server.
[/]% rm foo Node /foo removed
It is possible to specify several nodes.
[/]% rm foo bar Node /foo /bar removed
The *set* command updates the property of a node:
[/gadgets]% set
Create the property foo with the value bar on the root node:
[/]% set foo bar Property created
Update the existing foo property:
[/]% set foo juu Property updated
When a property is created and does not have a property descriptor that constraint its type, you can specify it with the -t option
[/]% set -t LONG long_property 3 Property created
The commit operation saves the current session. Conversely the rollback operation rollback session changes. For both operations It is possible to specify a path to commit a part of the tree.
Queries in SQL format are possible via the select command. You can write a query with the same syntax defined by the specification and add options to control the number of results returned. By default the number of nodes is limited to 5 results:
[/]% select * from nt:base The query matched 1114 nodes +-/ | +-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/administratorsset_property,*:/platform/administrators remove] +-/workspace | +-properties | | +-jcr:primaryType: mop:workspace | | +-jcr:uuid: 'a69f226ec0a80002007ca83e5845cdac' ...
Display 20 nodes from the offset 10:
[/]% select * from nt:base -o 10 -l 20 The query matched 1114 nodes ...
It is possible also to remove the limit of displayed nodes with the -a option (you should use this option with care) :
[/]% select * from nt:base -a The query matched 1114 nodes ...
It is possible to export a node as an nt file of the same workspace with the exportnode command. Then it is usually possible to access the nt file from webdav.
[/]% exportnode gadgets /gadgets.xml The node has been exported
It is possible to import a node from an nt file located in the workspace with the importnode command.
[/]% importnode /gadgets.xml / Node imported
The addmixin command adds a mixin to an existing node.
[/gadgets]% addmixin . mix:versionable
![]() | Warning |
|---|---|
This is command is only available for eXo JCR |
The setperm commands configures the security of a node based on eXo JCR access control. When a node is protected by access control, it owns a mixin called exo:privilegeable that contains a exo:permissions property, for instance:
[/production]% ls /production +-properties | +-jcr:primaryType: nt:unstructured | +-jcr:mixinTypes: [exo:privilegeable] | +-exo:permissions: [*:/platform/administrators read,*:/platform/administrators add_node,*:/platform/administrators set_property,*:/platform/administrators remove] +-children | +-/production/app:gadgets | +-/production/app:applications | +-/production/mop:workspace
You can alter the node permission list with the setperm command:
[/production]% setperm *:/platform/mygroup read add_node Node /production updated to [read,add_node]
You can also remove a permission by prefixing it with a exclamation mark (!).
[/production]% setperm *:/platform/mygroup !add_node Node /production updated to [read]
The setperm command will add automatically the exo:privilegeable mixin on the node when it is missing.
Secure copy can be used to import or export content. The username/password prompted by the SSH server will be used for authentication against the repository when the import or the export is performed.
The following command will export the node /gadgets in the repository portal-system of the portal container portal:
scp -P 2000 root@localhost:portal:portal-system:/production/app:gadgets .
The node will be exported as app_gadgets.xml.
Note that the portal container name is used for GateIn. If you do omit it, then the root container will be used.
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.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.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.