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

== Quick Start

These instructions should help you get Apache Karaf up and running in 5 to 15 minutes.

=== Prerequisites

Karaf requires a Java SE 8 or higher to run. Refer to http://www.oracle.com/technetwork/java/javase/ for details on how to download and install Java SE 1.8 or greater.

* Open a Web browser and access the following URL: http://karaf.apache.org/download.html
* Download the binary distribution that matches your system (zip for windows, tar.gz for unixes)
* Extract the archive to a new folder on your hard drive; for example in c:\karaf - from now on this directory will be referenced as <KARAF_HOME>.

=== Start the server

Open a command line console and change the directory to <KARAF_HOME>.

To start the server, run the following command in Windows:

----
bin\karaf.bat
----

respectively on Unix:

----
bin/karaf
----

You should see the following information on the command line console:

----
        __ __                  ____
       / //_/____ __________ _/ __/
      / ,<  / __ `/ ___/ __ `/ /_
     / /| |/ /_/ / /  / /_/ / __/
    /_/ |_|\__,_/_/   \__,_/_/

  Apache Karaf (4.2.0)

Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.

karaf@root()>
----

=== Shell console basics

You can now run your first command.  Simply type the `<tab>` key in the console.

----
karaf@root()>
karaf: do you wish to see to see all 356 possibilities (219 lines)?
karaf@root()> Display all 294 possibilities? (y or n)
...
shell:logout                        shell:more                          shell:new                           shell:printf                        shell:sleep                         shell:sort                          shell:source
shell:stack-traces-print            shell:tac                           shell:tail                          shell:threads                       shell:watch                         shell:wc                            shell:while
shutdown                            sleep                               sort                                source                              ssh                                 ssh                                 ssh-host-change
ssh-port-change                     ssh:ssh                             stack-traces-print                  start                               start-level                         status                              stop
su                                  sudo                                system                              system:framework                    system:name                         system:property                     system:shutdown
system:start-level                  system:version                      tac                                 tail                                threads                             tree-show                           uninstall
update                              user-add                            user-delete                         user-list                           version                             version-list                        wait
watch                               wc                                  while
----

You can then grab more specific help for a given command using the `--help` option for this command:

----
karaf@root()> bundle:list --help
DESCRIPTION
        bundle:list

        Lists all installed bundles.

SYNTAX
        bundle:list [options] [ids]

ARGUMENTS
        ids
                The list of bundle (identified by IDs or name or name/version) separated by whitespaces

OPTIONS
        -name, -n
                Show bundle name
        -u
                Shows the update locations
        -r
                Shows the bundle revisions
        --no-ellipsis

        -l
                Show the locations
        -s
                Shows the symbolic name
        --context, -c
                Use the given bundle context
                (defaults to 0)
        --help
                Display this help message
        -t
                Specifies the bundle threshold; bundles with a start-level less than this value will not get printed out.
        --no-format
                Disable table rendered output
----

Note that the console supports tab completion so if you start typing a command it will show all possible completions and also auto complete if there is only one completion.

=== Deploy a sample application

While you will learn in the Karaf user's guide how to fully use and leverage Apache Karaf, let's install a sample http://camel.apache.org[Apache Camel] application for now:

Copy and paste the following commands in the console:

----
feature:repo-add camel
feature:install deployer camel-blueprint aries-blueprint
cat > deploy/example.xml <<END
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">
        <route>
            <from uri="timer://test?fixedRate=true&amp;period=2000" />
            <setBody>
                <simple>Message at ${date:now:yyyy-MM-dd HH:mm:ss}</simple>
            </setBody>
            <to uri="log:test" />
        </route>
    </camelContext>

</blueprint>
END
----

The example that is installed is using Camel to start a timer every 2 seconds and output a message in the log.
The previous commands downloaded the Camel features descriptor and installed the example feature.

You can display the log in the shell:

----
karaf@root()> log:display
...
2017-10-13 10:04:11,225 | INFO  | 7 - timer://test | test                             | 28 - org.apache.camel.camel-core - 2.20.0 | Exchange[ExchangePattern: InOnly, BodyType: String, Body: Message at 2017-10-13 10:04:11]
2017-10-13 10:04:13,225 | INFO  | 7 - timer://test | test                             | 28 - org.apache.camel.camel-core - 2.20.0 | Exchange[ExchangePattern: InOnly, BodyType: String, Body: Message at 2017-10-13 10:04:13]
----

=== Stopping and uninstalling the sample application

To stop and uninstall the demo, run the following command:

----
karaf@root()> bundle:stop example.xml
karaf@root()> bundle:uninstall example.xml
----

=== Stopping Karaf

To stop Karaf from the console, enter `^D` in the console:

----
^D
----

Alternatively, you can also run the following command:

----
karaf@root()> feature:install system
karaf@root()> system:shutdown
Confirm: halt instance root (yes/no): yes
karaf@root()>
----

halt is also an alias for system:shutdown:

----
karaf@root()> halt
----

=== Cleaning the Karaf state

Normally Karaf remembers the features and bundles you installed and started. To reset Karaf into a clean state, just delete the data directory when Karaf is not running.

=== Summary

This document shows how simple it is to get Apache Karaf up and running and install a simple Apache Camel application.
