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-beta9 (http://crsh.googlecode.com) Welcome to juliens-macbook-pro.local! It is Fri Jan 08 21:12:53 CET 2010 now. %
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 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.
[/registry]% rm Administration
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
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 the web.xml file of the CRaSH web archive.
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.
<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:
<listener> <listener-class>org.crsh.term.telnet.TelnetLifeCycle</listener-class> </listener>
To remove the SSH access, remove or comment the following XML:
<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.