//
// 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 environments, the Karaf console supports some key bindings:

* the arrows key to navigate in the commands history
* CTRL-D to logout/shutdown Karaf. Note: to avoid accidental logouts, 
this can be disabled by setting `disableEofExit = true` in `etc/org.apache.karaf.shell.cfg`.
* 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 felix
felix-httplite                    │ 0.1.6            │          │ Uninstalled │ standard-4.4.0           │ Felix Httplite HTTP Service
felix-http                        │ 4.1.12           │          │ Uninstalled │ standard-4.4.0           │ Felix HTTP Service
----

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

Karaf console provides some core commands similar to a 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. Note: to avoid accidental logouts, 
this can be disabled by setting `disableLogout = true` in `etc/org.apache.karaf.shell.cfg`.
* `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 scripts.
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 name your 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 for
the user connected to the console, you can define, depending on 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.
