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

=== Provisioning

Apache Karaf is OSGi powered container.

It natively supports the deployment of OSGi applications.

An OSGi application is a set of OSGi bundles. An OSGi bundles is a regular jar file, with additional metadata in the jar MANIFEST.

In OSGi, a bundle can depend to other bundles. So, it means that to deploy an OSGi application, most of the time, you have
to firstly deploy a lot of other bundles required by the application.

So, you have to find these bundles first, install the bundles. Again, these "dependency" bundles may require other bundles
to satisfy their own dependencies.

More over, typically, an application requires configuration (see the [Configuration section|configuration] of the user guide).
So, before being able to start your application, in addition of the dependency bundles, you have to create or deploy the
configuration.

Deploying all the requirements (bundles and configurations) of an application into a container is called the "provisioning".

As we can see, the provisioning of an application can be very long and fastidious.

Apache Karaf provides a simple and flexible way to provision applications.

In Apache Karaf, the application provisioning is an Apache Karaf "feature".

A feature describes an application as:

* a name
* a version
* a optional description (eventually with a long description)
* a set of bundles
* optionally a set configurations or configuration files
* optionally a set of dependency features

When you install a feature, Apache Karaf installs all resources described in the feature. It means that it will
automatically resolves and installs all bundles, configurations, and dependency features described in the feature.

==== Features repositories

The features are described in a features XML descriptor. This XML file contains the description of a set of features.

A features XML descriptor is named a "features repository". Before being able to install a feature, you have to register
the features repository that provides the feature (using `feature:repo-add` command or FeatureMBean as described later).

For instance, the following XML file (or "features repository") describes the `feature1` and `feature2` features:

----
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
  <feature name="feature1" version="1.0.0">
    <bundle>...</bundle>
    <bundle>...</bundle>
  </feature>
  <feature name="feature2" version="1.1.0">
    <feature>feature1</feature>
    <bundle>...</bundle>
  </feature>
</features>
----

We can note that the features XML has a schema. Take a look on [Features XML Schema section|provisioning-schema] of the user guide
for details.
The `feature1` feature is available in version `1.0.0`, and contains two bundles. The `<bundle/>` element contains a URL
to the bundle artifact (see [Artifacts repositories and URLs section|urls] for details). If you install the `feature1` feature
(using `feature:install` or the FeatureMBean as described later), Apache Karaf will automatically installs the two bundles
described.
The `feature2` feature is available in version `1.1.0`, and contains a reference to the `feature1` feature and a bundle.
The `<feature/>` element contains the name of a feature. A specific feature version can be defined using the `version`
attribute to the `<feature/>` element (`<feature version="1.0.0">feature1</feature>`). If the `version` attribute is
not specified, Apache Karaf will install the latest version available. If you install the `feature2` feature (using `feature:install`
or the FeatureMBean as described later), Apache Karaf will automatically installs `feature1` (if it's not already installed)
and the bundle.

A feature repository is registered using the URL to the features XML file.

The features state is stored in the Apache Karaf cache (in the `KARAF_DATA` folder). You can restart Apache Karaf, the
previously installed features remain installed and available after restart.
If you do a clean restart or you delete the Apache Karaf cache (delete the `KARAF_DATA` folder), all previously features
repositories registered and features installed will be lost: you will have to register the features repositories and install
features by hand again.
To prevent this behaviour, you can specify features as boot features.

==== Boot features

You can describe some features as boot features. A boot feature will be automatically install by Apache Karaf, even if it has
not been previously installed using `feature:install` or FeatureMBean.

Apache Karaf features configuration is located in the `etc/org.apache.karaf.features.cfg` configuration file.

This configuration file contains the two properties to use to define boot features:

* `featuresRepositories` contains a list (coma separated) of features repositories (features XML) URLs.
* `featuresBoot` contains a list (come separated) of features to install at boot.

==== Features upgrade

Right now, Apache Karaf doesn't provide complete upgrade cycle for features.

Basically, a feature upgrade means:

* Uninstall the features first (eventually providing the feature version to uninstall), and the features repository.
* Register the new version of the features repository and install the features with the target version.

==== Feature bundles

===== Start Level

By default, the bundles deployed by a feature will have a start-level equals to the value defined in the `etc/config.properties`
configuration file, in the `karaf.startlevel.bundle` property.

This value can be "overrided" by the `start-level` attribute of the `<bundle/>` element, in the features XML.

----
  <feature name="my-project" version="1.0.0">
    <bundle start-level="80">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>
----

The start-level attribute insure that the `myproject-dao` bundle is started before the bundles that use it.

Instead of using start-level, a better solution is to simply let the OSGi framework know what your dependencies are by
defining the packages or services you need. It is more robust than setting start levels.

===== Start and stop

You can install a bundle without starting it. By default, the bundles in a feature are automatically started.

A feature can specify that a bundle should not be started automatically (the bundle stays in resolved state).
To do so, a feature can specify the `start` attribute to false in the `<bundle/>` element:

----
  <feature name="my-project" version="1.0.0">
    <bundle start-level="80" start="false">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85" start="false">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>
----

[NOTE]
====
Before Apache Karaf 3.0.0 the start-level was not considered during the feature startup, but only the order in which bundles
are defined in your feature.xml.
Starting with Apache Karaf 3.0.0, the start-level is considered correctly.
If you need to use the old behavior you can uncomment and set the `respectStartLvlDuringFeatureStartup` property to false in
`etc/org.apache.karaf.features.xml` configuration file.
Note that it will be removed in 4.0 and should therefore be used only temporarily.
====

===== Dependency

A bundle can be flagged as being a dependency, using the `dependency` attribute set to true on the `<bundle/>` element.

This information can be used by resolvers to compute the full list of bundles to be installed.

==== Dependent features

A feature can depend to a set of other features:

----
  <feature name="my-project" version="1.0.0">
    <feature>other</feature>
    <bundle start-level="80" start="false">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85" start="false">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>
----

When the `my-project` feature will be installed, the `other` feature will be automatically installed as well.

It's possible to define a version range for a dependent feature:

----
<feature name="spring-dm">
  <feature version="[2.5.6,4)">spring</feature>
  ...
</feature>
----

The feature with the highest version available in the range will be installed.

If a single version is specified, this version will be chosen.

If nothing is specified, the highest available will be installed.

==== Feature configurations

The `<config/>` element in a feature XML allows a feature to create and/or populate a configuration (identified by a configuration PID).

----
<config name="com.foo.bar">
  myProperty = myValue
</config>
----

The `name` attribute of the `<config/>` element corresponds to the configuration PID (see the [Configuration section|configuration] for details).

The installation of the feature will have the same effect as dropping a file named `com.foo.bar.cfg` in the `etc` folder.

The content of the `<config/>` element is a set of properties, following the key=value standard.

==== Feature configuration files

Instead of using the `<config/>` element, a feature can specify `<configfile/>` elements.

----
<configfile finalname="/etc/myfile.cfg" override="false">URL</configfile>
----

Instead of directly manipulating the Apache Karaf configuration layer (as when using the `<config/>` element), the
`<configfile/>` element takes directly a file specified by a URL, and copy the file in the location specified by the
`finalname` attribute. The location is relative from the `KARAF_BASE` variable. If the file is already present at
the desired location it is kept and the deployment of the configuration file is skipped, as a already existing file might
contain customization. This behaviour can be overriden by `override` set to true. 

The file URL is any URL supported by Apache Karaf (see the [Artifacts repositories and URLs|urls] of the user guide for details).

==== Feature resolver

A feature accepts a `resolver` attribute:

----
<feature name="my-project" version="1.0.0" resolver="(obr)">
...
</feature>
----

This `resolver` attribute forces the usage of a specific resolver, instead of the default resolution process.

A resolver is used to obtain the list of bundles to install, when installing the feature.

The default resolver simply returns the list of bundles as described by the `<bundle/>` elements in a feature.

You can install a OBR (OSGi Bundle Repository) resolver instead of the default one.
The OBR resolver use the OBR service to get the list of bundles to install (see the [OBR section|obr] of the user guide for details).

==== Commands

===== `feature:repo-list`

The `feature:repo-list` command lists all registered features repository:

----
karaf@root()> feature:repo-list
Repository                | URL
------------------------------------------------------------------------------------------------
standard-3.0.0            | mvn:org.apache.karaf.features/standard/3.0.0/xml/features
enterprise-3.0.0          | mvn:org.apache.karaf.features/enterprise/3.0.0/xml/features
org.ops4j.pax.web-3.0.5   | mvn:org.ops4j.pax.web/pax-web-features/3.0.5/xml/features
spring-3.0.0              | mvn:org.apache.karaf.features/spring/3.0.0/xml/features
----

Each repository has a name and the URL to the features XML.

Apache Karaf parses the features XML when you register the features repository URL (using `feature:repo-add` command
or the FeatureMBean as described later). If you want to force Apache Karaf to reload the features repository URL (and
so update the features definition), you can use the `-r` option:

----
karaf@root()> feature:repo-list -r
Reloading all repositories from their urls

Repository                | URL
------------------------------------------------------------------------------------------------
standard-3.0.0            | mvn:org.apache.karaf.features/standard/3.0.0/xml/features
org.ops4j.pax.web-3.0.5   | mvn:org.ops4j.pax.web/pax-web-features/3.0.5/xml/features
enterprise-3.0.0          | mvn:org.apache.karaf.features/enterprise/3.0.0/xml/features
spring-3.0.0              | mvn:org.apache.karaf.features/spring/3.0.0/xml/features
----

===== `feature:repo-add`

To register a features repository (and so having new features available in Apache Karaf), you have to use the
`feature:repo-add` command.

The `feature:repo-add` command requires the `name/url` argument. This argument accepts:

* a feature repository URL. It's an URL directly to the features XML file. Any URL described in the [Artifacts repositories and URLs section|urls]
 of the user guide is supported.
* a feature repository name defined in the `etc/org.apache.karaf.features.repos.cfg` configuration file.

The `etc/org.apache.karaf.features.repos.cfg` defines a list of "pre-installed/available" features repositories:

----
################################################################################
#
#    Licensed to the Apache Software Foundation (ASF) under one or more
#    contributor license agreements.  See the NOTICE file distributed with
#    this work for additional information regarding copyright ownership.
#    The ASF licenses this file to You 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.
#
################################################################################

#
# This file describes the features repository URL
# It could be directly installed using feature:repo-add command
#

cellar       = org.apache.karaf.cellar:apache-karaf-cellar:xml:features:(0,]
camel        = org.apache.camel.karaf:apache-camel:xml:features:(0,]
camel-extras = org.apache-extras.camel-extra.karaf:camel-extra:xml:features:(0,]
cxf          = org.apache.cxf.karaf:apache-cxf:xml:features:(0,]
cxf-dosgi    = org.apache.cxf.dosgi:cxf-dosgi:xml:features:(0,]
activemq     = org.apache.activemq:activemq-karaf:xml:features:(0,]
jclouds      = org.jclouds.karaf:jclouds-karaf:xml:features:(0,]
openejb      = org.apache.openejb:openejb-feature:xml:features:(0,]
wicket       = org.ops4j.pax.wicket:features:xml:features:(0,]
hawtio       = io.hawt:hawtio-karaf:xml:features:(0,]
----

You can directly provide a features repository name to the `feature:repo-add` command. For install, to install Apache Karaf Cellar, you can do:

----
karaf@root()> feature:repo-add cellar
Adding feature url mvn:org.apache.karaf.cellar/apache-karaf-cellar/LATEST/xml/features
----

When you don't provide the optional `version` argument, Apache Karaf installs the latest version of the features repository available.
You can specify a target version with the `version` argument:

----
karaf@root()> feature:repo-add cellar 2.3.1
Adding feature url mvn:org.apache.karaf.cellar/apache-karaf-cellar/2.3.1/xml/features
----

Instead of providing a features repository name defined in the `etc/org.apache.karaf.features.repos.cfg` configuration file,
you can directly provide the features repository URL to the `feature:repo-add` command:

----
karaf@root()> feature:repo-add mvn:org.apache.karaf.cellar/apache-karaf-cellar/2.3.1/xml/features
Adding feature url mvn:org.apache.karaf.cellar/apache-karaf-cellar/2.3.1/xml/features
----

By default, the `feature:repo-add` command just registers the features repository, it doesn't install any feature.
If you specify the `-i` option, the `feature:repo-add` command registers the features repository and installs all
features described in this features repository:

----
karaf@root()> feature:repo-add -i cellar
----

===== `feature:repo-refresh`

Apache Karaf parses the features repository XML when you register it (using `feature:repo-add` command or the FeatureMBean).
If the features repository XML changes, you have to indicate to Apache Karaf to refresh the features repository to load the changes.

The `feature:repo-refresh` command refreshes the features repository.

Without argument, the command refreshes all features repository:

----
karaf@root()> feature:repo-refresh
Refreshing feature url mvn:org.apache.karaf.features/standard/3.0.0/xml/features
Refreshing feature url mvn:org.apache.karaf.features/enterprise/3.0.0/xml/features
Refreshing feature url mvn:org.ops4j.pax.web/pax-web-features/3.0.4/xml/features
Refreshing feature url mvn:org.apache.karaf.features/spring/3.0.0/xml/features
----

Instead of refreshing all features repositories, you can specify the features repository to refresh, by providing the URL
or the features repository name (and optionally version):

----
karaf@root()> feature:repo-refresh mvn:org.apache.karaf.features/standard/3.0.0-SNAPSHOT/xml/features
Refreshing feature url mvn:org.apache.karaf.features/standard/3.0.0-SNAPSHOT/xml/features
----

----
karaf@root()> feature:repo-refresh cellar
Refreshing feature url mvn:org.apache.karaf.cellar/apache-karaf-cellar/LATEST/xml/features
----

===== `feature:repo-remove`

The `feature:repo-remove` command removes a features repository from the registered ones.

The `feature:repo-remove` command requires a argument:

* the features repository name (as displayed in the repository column of the `feature:repo-list` command output)
* the features repository URL (as displayed in the URL column of the `feature:repo-list` command output)

----
karaf@root()> feature:repo-remove karaf-cellar-3.0.0
----

----
karaf@root()> feature:repo-remove mvn:org.apache.karaf.cellar/apache-karaf-cellar/LATEST/xml/features
----

By default, the `feature:repo-remove` command just removes the features repository from the registered ones: it doesn't
uninstall the features provided by the features repository.

If you use `-u` option, the `feature:repo-remove` command uninstalls all features described by the features repository:

----
karaf@root()> feature:repo-remove -u karaf-cellar-3.0.0
----

===== `feature:list`

The `feature:list` command lists all available features (provided by the different registered features repositories):

----
karaf@root()> feature:list
Name                          | Version         | Installed | Repository                | Description
--------------------------------------------------------------------------------------------------------------------------------------------
standard                      | 3.0.0           | x         | standard-3.0.0            | Karaf standard feature
aries-annotation              | 3.0.0           |           | standard-3.0.0            | Aries Annotations
wrapper                       | 3.0.0           |           | standard-3.0.0            | Provide OS integration
service-wrapper               | 3.0.0           |           | standard-3.0.0            | Provide OS integration (alias to wrapper feature)
obr                           | 3.0.0           |           | standard-3.0.0            | Provide OSGi Bundle Repository (OBR) support
config                        | 3.0.0           | x         | standard-3.0.0            | Provide OSGi ConfigAdmin support
region                        | 3.0.0           | x         | standard-3.0.0            | Provide Region Support
...
----

If you want to order the features by alphabetical name, you can use the `-o` option:

----
karaf@root()> feature:list -o
Name                          | Version         | Installed | Repository                | Description
--------------------------------------------------------------------------------------------------------------------------------------------
aries-annotation              | 3.0.0-SNAPSHOT  |           | standard-3.0.0-SNAPSHOT   | Aries Annotations
blueprint-web                 | 3.0.0-SNAPSHOT  |           | standard-3.0.0-SNAPSHOT   | Provides an OSGI-aware Servlet ContextListener for
config                        | 3.0.0-SNAPSHOT  | x         | standard-3.0.0-SNAPSHOT   | Provide OSGi ConfigAdmin support
eventadmin                    | 3.0.0-SNAPSHOT  |           | standard-3.0.0-SNAPSHOT   | OSGi Event Admin service specification for event-b
http                          | 3.0.0-SNAPSHOT  |           | standard-3.0.0-SNAPSHOT   | Implementation of the OSGI HTTP Service
http-whiteboard               | 3.0.0-SNAPSHOT  |           | standard-3.0.0-SNAPSHOT   | Provide HTTP Whiteboard pattern support
...
----

By default, the `feature:list` command displays all features, whatever their current state (installed or not installed).

Using the `-i` option displays only installed features:

----
karaf@root()> feature:list -i
Name       | Version        | Installed | Repository              | Description
----------------------------------------------------------------------------------------------------------------------
standard   | 3.0.0          | x         | standard-3.0.0          | Karaf standard feature
config     | 3.0.0          | x         | standard-3.0.0          | Provide OSGi ConfigAdmin support
region     | 3.0.0          | x         | standard-3.0.0          | Provide Region Support
package    | 3.0.0          | x         | standard-3.0.0          | Package commands and mbeans
kar        | 3.0.0          | x         | standard-3.0.0          | Provide KAR (KARaf archive) support
ssh        | 3.0.0          | x         | standard-3.0.0          | Provide a SSHd server on Karaf
management | 3.0.0          | x         | standard-3.0.0          | Provide a JMX MBeanServer and a set of MBeans in K
----

===== `feature:install`

The `feature:install` command installs a feature.

It requires the `feature` argument. The `feature` argument is the name of the feature, or the name/version of the feature.
If only the name of the feature is provided (not the version), the latest version available will be installed.

----
karaf@root()> feature:install eventadmin
----

----
karaf@root()> feature:install eventadmin/3.0.0
----

By default, the `feature:install` command is not verbose. If you want to have some details about actions performed by the `feature:install`
command, you can use the `-v` option:

----
karaf@root()> feature:install -v eventadmin
Installing feature eventadmin 3.0.0
Found installed bundle: org.apache.felix.eventadmin [80]
----

If a feature contains a bundle which is already installed, by default, Apache Karaf will refresh this bundle.
Sometime, this refresh can cause issue to other running applications. If you want to disable the auto-refresh of installed
bundles, you can use the `-r` option:

----
karaf@root()> feature:install -v -r eventadmin
Installing feature eventadmin 3.0.0
Installing bundle mvn:org.apache.felix/org.apache.felix.eventadmin/1.3.2
----

If the installation of a failure fails (for any reason), by default, Apache Karaf will uninstall all bundles installed by the feature.
It will go back in the state before the installation of the feature.

If you want to keep the bundles in the feature successfully installed, you can use the `-c` option. Even if the complete feature
installation fails, the feature successfully installed bundles remain installed.

===== `feature:uninstall`

The `feature:uninstall` command uninstalls a feature. As the `feature:install` command, the `feature:uninstall` command
requires the `feature` argument. The `feature` argument is the name of the feature, or the name/version of the feature.
If only the name of the feature is provided (not the version), the latest version available will be installed.

----
karaf@root()> feature:uninstall eventadmin
----

==== Deployer

You can "hot deploy" a features XML by dropping the file directly in the `deploy` folder.

Apache Karaf provides a features deployer.

When you drop a features XML in the deploy folder, the features deployer does:
* register the features XML as a features repository
* the features with `install` attribute set to "auto" will be automatically installed by the features deployer.

For instance, dropping the following XML in the deploy folder will automatically install feature1 and feature2, whereas
feature3 won't be installed:

----
<?xml version="1.0" encoding="UTF-8"?>
<features name="my-features" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">

    <feature name="feature1" version="1.0" install="auto">
        ...
    </feature>

    <feature name="feature2" version="1.0" install="auto">
        ...
    </feature>

    <feature name="feature3" version="1.0">
        ...
    </feature>

</features>
----

==== JMX FeatureMBean

On the JMX layer, you have a MBean dedicated to the management of the features and features repositories: the FeatureMBean.

The FeatureMBean object name is: `org.apache.karaf:type=feature,name=*`.

===== Attributes

The FeatureMBean provides two attributes:

* `Features` is a tabular data set of all features available.
* `Repositories` is a tabular data set of all registered features repositories.

The `Repositories` attribute provides the following information:

* `Name` is the name of the features repository.
* `Uri` is the URI to the features XML for this repository.
* `Features` is a tabular data set of all features (name and version) provided by this features repository.
* `Repositories` is a tabular data set of features repositories "imported" in this features repository.

The `Features` attribute provides the following information:

* `Name` is the name of the feature.
* `Version` is the version of the feature.
* `Installed` is a boolean. If true, it means that the feature is currently installed.
* `Bundles` is a tabular data set of all bundles (bundles URL) described in the feature.
* `Configurations` is a tabular data set of all configurations described in the feature.
* `Configuration Files` is a tabular data set of all configuration files described in the feature.
* `Dependencies` is a tabular data set of all dependent features described in the feature.

===== Operations

* `addRepository(url)` adds the features repository with the `url`. The `url` can be a `name` as in the `feature:repo-add` command.
* `addRepository(url, install)` adds the features repository with the `url` and automatically installs all bundles if `install` is true. The `url` can be a `name` like in the `feature:repo-add` command.
* `removeRepository(url)` removes the features repository with the `url`. The `url` can be a `name` as in the `feature:repo-remove` command.
* `installFeature(name)` installs the feature with the `name`.
* `installFeature(name, version)` installs the feature with the `name` and `version`.
* `installFeature(name, noClean, noRefresh)` installs the feature with the `name` without cleaning the bundles in case of failure, and without refreshing already installed bundles.
* `installFeature(name, version, noClean, noRefresh) ` installs the feature with the `name` and `version` without cleaning the bundles in case of failure, and without refreshing already installed bundles.
* `uninstallFeature(name)` uninstalls the feature with the `name`.
* `uninstallFeature(name, version)` uninstalls the feature with the `name` and `version`.

===== Notifications

The FeatureMBean sends two kind of notifications (on which you can subscribe and react):

* When a feature repository changes (added or removed).
* When a feature changes (installed or uninstalled).