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

=== Using the console

==== Available commands

To see a list of the available commands in the console, you can use the `help`:

----
karaf@root()> help
bundle                            Enter the subshell
bundle:capabilities               Displays OSGi capabilities of a given bundles.
bundle:classes                    Displays a list of classes/resources contained in the bundle
bundle:diag                       Displays diagnostic information why a bundle is not Active
bundle:dynamic-import             Enables/disables dynamic-import for a given bundle.
bundle:find-class                 Locates a specified class in any deployed bundle
bundle:headers                    Displays OSGi headers of a given bundles.
bundle:id                         Gets the bundle ID.
...
----

You have the list of all commands with a short description.

You can use the tab key to get a quick list of all commands:

----
karaf@root()> Display all 294 possibilities? (y or n)
...
----

==== Subshell and completion mode

The commands have a scope and a name. For instance, the command `feature:list` has `feature` as scope, and `list` as name.

Karaf "groups" the commands by scope. Each scope form a subshell.

You can directly execute a command with its full qualified name (scope:name):

----
karaf@root()> feature:list
...
----

or enter in a subshell and type the command contextual to the subshell:

----
karaf@root()> feature
karaf@root(feature)> list
----

You can note that you enter in a subshell directly by typing the subshell name (here `feature`). You can "switch" directly from a subshell to another:

----
karaf@root()> feature
karaf@root(feature)> bundle
karaf@root(bundle)>
----

The prompt displays the current subshell between ().

The `exit` command goes to the parent subshell:

----
karaf@root()> feature
karaf@root(feature)> exit
karaf@root()>
----

The completion mode defines the behaviour of the tab key and the help command.

You have three different modes available:

* GLOBAL
* FIRST
* SUBSHELL

You can define your default completion mode using the completionMode property in `etc/org.apache.karaf.shell.cfg` file. By default, you have:

----
completionMode = GLOBAL
----

You can also change the completion mode “on the fly” (while using the Karaf shell console) using the `shell:completion` command:

----
karaf@root()> shell:completion
GLOBAL
karaf@root()> shell:completion FIRST
karaf@root()> shell:completion
FIRST
----

`shell:completion` can inform you about the current completion mode used. You can also provide the new completion mode that you want.

GLOBAL completion mode is the default one in Karaf 4.0.0 (mostly for transition purpose).

GLOBAL mode doesn’t really use subshell: it’s the same behavior as in previous Karaf versions.

When you type the tab key, whatever in which subshell you are, the completion will display all commands and all aliases:

----
karaf@root()> <TAB>
karaf@root()> Display all 273 possibilities? (y or n)
...
karaf@root()> feature
karaf@root(feature)> <TAB>
karaf@root(feature)> Display all 273 possibilities? (y or n)
----

FIRST completion mode is an alternative to the GLOBAL completion mode.

If you type the tab key on the root level subshell, the completion will display the commands and the aliases from all subshells (as in GLOBAL mode).
However, if you type the tab key when you are in a subshell, the completion will display only the commands of the current subshell:

----
karaf@root()> shell:completion FIRST
karaf@root()> <TAB>
karaf@root()> Display all 273 possibilities? (y or n)
...
karaf@root()> feature
karaf@root(feature)> <TAB>
karaf@root(feature)>
info install list repo-add repo-list repo-remove uninstall version-list
karaf@root(feature)> exit
karaf@root()> log
karaf@root(log)> <TAB>
karaf@root(log)>
clear display exception-display get log set tail
----

SUBSHELL completion mode is the real subshell mode.

If you type the tab key on the root level, the completion displays the subshell commands (to go into a subshell), and the global aliases.
Once you are in a subshell, if you type the TAB key, the completion displays the commands of the current subshell:

----
karaf@root()> shell:completion SUBSHELL
karaf@root()> <TAB>
karaf@root()>
* bundle cl config dev feature help instance jaas kar la ld lde log log:list man package region service shell ssh system
karaf@root()> bundle
karaf@root(bundle)> <TAB>
karaf@root(bundle)>
capabilities classes diag dynamic-import find-class headers info install list refresh requirements resolve restart services start start-level stop
uninstall update watch
karaf@root(bundle)> exit
karaf@root()> camel
karaf@root(camel)> <TAB>
karaf@root(camel)>
backlog-tracer-dump backlog-tracer-info backlog-tracer-start backlog-tracer-stop context-info context-list context-start context-stop endpoint-list route-info route-list route-profile route-reset-stats
route-resume route-show route-start route-stop route-suspend
----

==== Unix like environment

Karaf console provides a full Unix like environment.

===== Help or man

We already saw the usage of the `help` command to display all commands available.

But you can also use the `help` command to get details about a command or 
the `man` command which is an alias to the `help` command.
You can also use another form to get the command help, by using the `--help` option to the command.

So these commands 

----
karaf@root()> help feature:list
karaf@root()> man feature:list
karaf@root()> feature:list --help
----

All produce the same help output:

----
DESCRIPTION
        feature:list

        Lists all existing features available from the defined repositories.

SYNTAX
        feature:list [options]

OPTIONS
        --help
                Display this help message
        -o, --ordered
                Display a list using alphabetical order
        -i, --installed
                Display a list of all installed features only
        --no-format
                Disable table rendered output

----

===== Completion

When you type the tab key, Karaf tries to complete:

* subshell
* commands
* aliases
* command arguments
* command options

===== Alias

An alias is another name associated to a given command.

The `shell:alias` command creates a new alias. For instance, to create the `list-installed-features` alias to the actual
`feature:list -i` command, you can do:

----
karaf@root()> alias "list-features-installed = { feature:list -i }"
karaf@root()> list-features-installed 
Name       | Version | Required | State   | Repository     | Description
------------------------------------------------------------------------------------------------------------------------------
feature    | 4.0.0   | x        | Started | standard-4.0.0 | Features Support
shell      | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell
deployer   | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Deployer
bundle     | 4.0.0   | x        | Started | standard-4.0.0 | Provide Bundle support
config     | 4.0.0   | x        | Started | standard-4.0.0 | Provide OSGi ConfigAdmin support
diagnostic | 4.0.0   | x        | Started | standard-4.0.0 | Provide Diagnostic support
instance   | 4.0.0   | x        | Started | standard-4.0.0 | Provide Instance support
jaas       | 4.0.0   | x        | Started | standard-4.0.0 | Provide JAAS support
log        | 4.0.0   | x        | Started | standard-4.0.0 | Provide Log support
package    | 4.0.0   | x        | Started | standard-4.0.0 | Package commands and mbeans
service    | 4.0.0   | x        | Started | standard-4.0.0 | Provide Service support
system     | 4.0.0   | x        | Started | standard-4.0.0 | Provide System support
kar        | 4.0.0   | x        | Started | standard-4.0.0 | Provide KAR (KARaf archive) support
ssh        | 4.0.0   | x        | Started | standard-4.0.0 | Provide a SSHd server on Karaf
management | 4.0.0   | x        | Started | standard-4.0.0 | Provide a JMX MBeanServer and a set of MBeans in
----

At login, the Apache Karaf console reads the `etc/shell.init.script` file where you can create your aliases.
It's similar to a bashrc or profile file on Unix.

----
ld = { log:display $args } ;
lde = { log:exception-display $args } ;
la = { bundle:list -t 0 $args } ;
ls = { service:list $args } ;
cl = { config:list "(service.pid=$args)" } ;
halt = { system:shutdown -h -f $args } ;
help = { *:help $args | more } ;
man = { help $args } ;
log:list = { log:get ALL } ;
----

You can see here the aliases available by default:

* `ld` is a short form to display log (alias to `log:display` command)
* `lde` is a short form to display exceptions (alias to `log:exception-display` command)
* `la` is a short form to list all bundles (alias to `bundle:list -t 0` command)
* `ls` is a short form to list all services (alias to `service:list` command)
* `cl` is a short form to list all configurations (alias to `config:list` command)
* `halt` is a short form to shutdown Apache Karaf (alias to `system:shutdown -h -f` command)
* `help` is a short form to display help (alias to `*:help` command)
* `man` is the same as help (alias to `help` command)
* `log:list` displays all loggers and level (alias to `log:get ALL` command)

You can create your own aliases in the `etc/shell.init.script` file.

===== Key binding

Like on most Unix environment, Karaf console support some key bindings:

* the arrows key to navigate in the commands history
* CTRL-D to logout/shutdown Karaf
* CTRL-R to search previously executed command
* CTRL-U to remove the current line

===== Pipe

You can pipe the output of one command as input to another one. It's a pipe, using the | character:

----
karaf@root()> feature:list |grep -i war
pax-war                       | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  | Provide support of a full WebContainer
pax-war-tomcat                | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  |
war                           | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Turn Karaf as a full WebContainer
blueprint-web                 | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Provides an OSGI-aware Servlet ContextListener fo
----

===== Grep, more, find, ...

Karaf console provides some core commands similar to Unix environment:

* `shell:alias` creates an alias to an existing command
* `shell:cat` displays the content of a file or URL
* `shell:clear` clears the current console display
* `shell:completion` displays or change the current completion mode
* `shell:date` displays the current date (optionally using a format)
* `shell:each` executes a closure on a list of arguments
* `shell:echo` echoes and prints arguments to stdout
* `shell:edit` calls a text editor on the current file or URL
* `shell:env` displays or sets the value of a shell session variable
* `shell:exec` executes a system command
* `shell:grep` prints lines matching the given pattern
* `shell:head` displays the first line of the input
* `shell:history` prints the commands history
* `shell:if` allows you to use conditions (if, then, else blocks) in script
* `shell:info` prints various information about the current Karaf instance
* `shell:java` executes a Java application
* `shell:less` file pager
* `shell:logout` disconnects shell from current session
* `shell:more` is a file pager
* `shell:new` creates a new Java object
* `shell:printf` formats and prints arguments
* `shell:sleep` sleeps for a bit then wakes up
* `shell:sort` writes sorted concatenation of all files to stdout
* `shell:source` executes commands contained in a script
* `shell:stack-traces-print` prints the full stack trace in the console when the execution of a command throws an exception
* `shell:tac` captures the STDIN and returns it as a string
* `shell:tail` displays the last lines of the input
* `shell:threads` prints the current thread
* `shell:watch` periodically executes a command and refresh the output
* `shell:wc` prints newline, words, and byte counts for each file
* `shell:while` loop while the condition is true

You don't have to use the fully qualified name of the command, you can directly use the command name as long as it is unique.
So you can use 'head' instead of 'shell:head'

Again, you can find details and all options of these commands using `help` command or `--help` option.

===== Scripting

The Apache Karaf Console supports a complete scripting language, similar to bash or csh on Unix.

The `each` (`shell:each`) command can iterate in a list:

----
karaf@root()> list = [1 2 3]; each ($list) { echo $it }
1
2
3
----

[NOTE]
====
The same loop could be written with the `shell:while` command:

----
karaf@root()> a = 0 ; while { %((a+=1) <= 3) } { echo $a } 
1
2
3
----
====

You can create the list yourself (as in the previous example), or some commands can return a list too.

We can note that the console created a "session" variable with the name `list` that you can access with `$list`.

The `$it` variable is an implicit one corresponding to the current object (here the current iterated value from the
list).

When you create a list with `[]`, Apache Karaf console creates a Java ArrayList. It means that you can use methods
available in the ArrayList objects (like get or size for instance):

----
karaf@root()> list = ["Hello" world]; echo ($list get 0) ($list get 1)
Hello world
----

We can note here that calling a method on an object is directly using `(object method argument)`.
Here `($list get 0)` means `$list.get(0)` where `$list` is the ArrayList.

The `class` notation will display details about the object:

----
karaf@root()> $list class
...
ProtectionDomain     ProtectionDomain  null
 null
 <no principals>
 java.security.Permissions@6521c24e (
 ("java.security.AllPermission" "<all permissions>" "<all actions>")
)


Signers              null
SimpleName           ArrayList
TypeParameters       [E]
----

You can "cast" a variable to a given type.

----
karaf@root()> ("hello world" toCharArray)
[h, e, l, l, o,  , w, o, r, l, d]
----

If it fails, you will see the casting exception:

----
karaf@root()> ("hello world" toCharArray)[0]
Error executing command: [C cannot be cast to [Ljava.lang.Object;
----

You can "call" a script using the `shell:source` command:

----
karaf@root> shell:source script.txt
True!
----

where `script.txt` contains:

----
foo = "foo"
if { $foo equals "foo" } {
  echo "True!"
}
----

[NOTE]
====
The spaces are important when writing script.
For instance, the following script is not correct:

----
if{ $foo equals "foo" } ...
----

and will fail with:

----
karaf@root> shell:source script.txt
Error executing command: Cannot coerce echo "true!"() to any of []
----

because a space is missing after the `if` statement.
====

As for the aliases, you can create init scripts in the `etc/shell.init.script` file.
You can also named you script with an alias. Actually, the aliases are just scripts.

See the Scripting section of the developers guide for details.

==== Security

The Apache Karaf console supports a Role Based Access Control (RBAC) security mechanism. It means that depending of
the user connected to the console, you can define, depending of the user's groups and roles, the permission to execute
some commands, or limit the values allowed for the arguments.

Console security is detailed in the link:security[Security section] of this user guide.
