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

=== KAR

As described in the link:provisioning[Provisioning section], Apache Karaf features describe applications.

A feature defines different resources to resolve using URLs (for instance, bundles URLs, or configuration files URLs).
As described in the [Artifacts repositories and URLs section|urls], Apache Karaf looks for artifacts (bundles,
configuration files, ...) in the artifact repositories.
Apache Karaf may have to download artifacts from remote repositories.

Apache Karaf provides a special type of artifact that package a features XML and all resources described in the features
of this XML. This artifact is named a KAR (KAraf aRchive).

A KAR file is essentially a jar (so a zip file) which contains a set of feature descriptor and bundle jar files.

A KAR file contains:

* a `repository` folder containing:
** a set of features repositories XML or JSON files
** the artifacts (jar files) following the Maven directory structure (`groupId/artifactId/version/artifactId-version.type`).
* optionally a `resources` folder containing all resources that could be included in a Karaf distribution (script files, configuration files, ...)

NB: as kar is a zip file, it doesn't require a `META-INF/MANIFEST.MF` file. However, as the `karaf-maven-plugin` plugin uses Jar archive to create kar, it includes a `META-INF/MANIFEST.MF` (even if useless).

For instance, the `spring-4.0.0.kar` contains:

----
~$ unzip -l spring-4.0.0.kar
Archive:  spring-4.0.0.kar
  Length      Date    Time    Name
---------  ---------- -----   ----
      143  2013-12-06 10:52   META-INF/MANIFEST.MF
    12186  2013-12-06 10:52   repository/org/apache/karaf/features/spring/4.0.0/spring-4.0.0-features.xml
   575389  2013-12-06 10:52   repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
   232019  2013-12-06 10:52   repository/commons-beanutils/commons-beanutils/1.8.3/commons-beanutils-1.8.3.jar
   673109  2013-12-06 10:52   repository/org/apache/servicemix/bundles/org.apache.servicemix.bundles.struts/1.3.10_1/org.apache.servicemix.bundles.struts-1.3.10_1.jar
    37084  2013-12-06 10:52   repository/org/springframework/org.springframework.web.struts/3.2.4.RELEASE/org.springframework.web.struts-3.2.4.RELEASE.jar
     7411  2013-12-06 10:52   repository/org/springframework/org.springframework.instrument/3.2.4.RELEASE/org.springframework.instrument-3.2.4.RELEASE.jar
   246881  2013-12-06 10:52   repository/org/springframework/org.springframework.transaction/3.2.4.RELEASE/org.springframework.transaction-3.2.4.RELEASE.jar
    16513  2013-12-06 10:52   repository/org/apache/servicemix/bundles/org.apache.servicemix.bundles.aopalliance/1.0_6/org.apache.servicemix.bundles.aopalliance-1.0_6.jar
   881124  2013-12-06 10:52   repository/org/springframework/org.springframework.core/3.2.4.RELEASE/org.springframework.core-3.2.4.RELEASE.jar
   199240  2013-12-06 10:52   repository/org/springframework/org.springframework.expression/3.2.4.RELEASE/org.springframework.expression-3.2.4.RELEASE.jar
   614646  2013-12-06 10:52   repository/org/springframework/org.springframework.beans/3.2.4.RELEASE/org.springframework.beans-3.2.4.RELEASE.jar
   340841  2013-12-06 10:52   repository/org/springframework/org.springframework.aop/3.2.4.RELEASE/org.springframework.aop-3.2.4.RELEASE.jar
   877369  2013-12-06 10:52   repository/org/springframework/org.springframework.context/3.2.4.RELEASE/org.springframework.context-3.2.4.RELEASE.jar
   130224  2013-12-06 10:52   repository/org/springframework/org.springframework.context.support/3.2.4.RELEASE/org.springframework.context.support-3.2.4.RELEASE.jar
    30640  2013-12-06 10:52   repository/org/apache/karaf/deployer/org.apache.karaf.deployer.spring/4.0.0/org.apache.karaf.deployer.spring-4.0.0.jar
    51951  2013-12-06 10:52   repository/org/springframework/org.springframework.aspects/3.2.4.RELEASE/org.springframework.aspects-3.2.4.RELEASE.jar
   411175  2013-12-06 10:52   repository/org/springframework/org.springframework.jdbc/3.2.4.RELEASE/org.springframework.jdbc-3.2.4.RELEASE.jar
    48049  2013-12-06 10:52   repository/javax/portlet/portlet-api/2.0/portlet-api-2.0.jar
   190883  2013-12-06 10:52   repository/org/springframework/org.springframework.web.portlet/3.2.4.RELEASE/org.springframework.web.portlet-3.2.4.RELEASE.jar
   635680  2013-12-06 10:52   repository/org/springframework/org.springframework.web/3.2.4.RELEASE/org.springframework.web-3.2.4.RELEASE.jar
   645946  2013-12-06 10:52   repository/org/springframework/org.springframework.web.servlet/3.2.4.RELEASE/org.springframework.web.servlet-3.2.4.RELEASE.jar
   464911  2013-12-06 10:52   repository/org/springframework/org.springframework.test/3.2.4.RELEASE/org.springframework.test-3.2.4.RELEASE.jar
    69784  2013-12-06 10:52   repository/org/springframework/osgi/spring-osgi-web/1.2.1/spring-osgi-web-1.2.1.jar
    16030  2013-12-06 10:52   repository/org/apache/geronimo/specs/geronimo-jta_1.1_spec/1.1.1/geronimo-jta_1.1_spec-1.1.1.jar
    32359  2013-12-06 10:52   repository/org/apache/geronimo/specs/geronimo-jms_1.1_spec/1.1.1/geronimo-jms_1.1_spec-1.1.1.jar
   208684  2013-12-06 10:52   repository/org/springframework/org.springframework.jms/3.2.4.RELEASE/org.springframework.jms-3.2.4.RELEASE.jar
    75672  2013-12-06 10:52   repository/org/springframework/org.springframework.oxm/3.2.4.RELEASE/org.springframework.oxm-3.2.4.RELEASE.jar
   393607  2013-12-06 10:52   repository/org/springframework/org.springframework.orm/3.2.4.RELEASE/org.springframework.orm-3.2.4.RELEASE.jar
   338559  2013-12-06 10:52   repository/org/apache/servicemix/bundles/org.apache.servicemix.bundles.cglib/3.0_1/org.apache.servicemix.bundles.cglib-3.0_1.jar
    35859  2013-12-06 10:52   repository/org/springframework/osgi/spring-osgi-io/1.2.1/spring-osgi-io-1.2.1.jar
   362889  2013-12-06 10:52   repository/org/springframework/osgi/spring-osgi-core/1.2.1/spring-osgi-core-1.2.1.jar
   120822  2013-12-06 10:52   repository/org/springframework/osgi/spring-osgi-extender/1.2.1/spring-osgi-extender-1.2.1.jar
    24231  2013-12-06 10:52   repository/org/springframework/osgi/spring-osgi-annotation/1.2.1/spring-osgi-annotation-1.2.1.jar
    12597  2013-12-06 10:52   repository/org/apache/karaf/bundle/org.apache.karaf.bundle.springstate/4.0.0/org.apache.karaf.bundle.springstate-4.0.0.jar
    31903  2013-12-06 10:52   repository/org/eclipse/gemini/blueprint/gemini-blueprint-io/1.0.0.RELEASE/gemini-blueprint-io-1.0.0.RELEASE.jar
   578205  2013-12-06 10:52   repository/org/eclipse/gemini/blueprint/gemini-blueprint-core/1.0.0.RELEASE/gemini-blueprint-core-1.0.0.RELEASE.jar
   178525  2013-12-06 10:52   repository/org/eclipse/gemini/blueprint/gemini-blueprint-extender/1.0.0.RELEASE/gemini-blueprint-extender-1.0.0.RELEASE.jar
---------                     -------
  9803140                     38 files
----

As a KAR file is a simple zip file, you can create the KAR file by hand.

For instance, the following Unix commands create a very simple KAR file:

----
~$ mkdir repository
~$ cp /path/to/features.xml repository/features.xml
~$ cp /path/to/my.jar repository/my/project/my/1.0.0/my-1.0.0.jar
~$ zip -r my.kar repository
updating: repository/ (stored 0%)
  adding: repository/my/project/my/1.0.0/my-1.0.0.jar (deflated 0%)
----

You can create KAR files using Apache Maven, or directly in the Apache Karaf console.

==== Maven

Apache Karaf provides a Maven plugin: `karaf-maven-plugin`.

The Apache Karaf Maven plugin provides the `kar` goal.

The `kar` goal does:

. Reads all features specified in the features XML.
. For each feature described in the features XML, the goal resolves the bundles described in the feature.
. The goal finally packages the features XML, and the resolved bundles in a zip file.
. NB: the `kar` goal uses Maven JarArchiver to create kar files, meaning that a `META-INF/MANIFEST.MF` is generated and included in the kar, even if not actually used.

For instance, you can use the following POM to create `my-kar.kar`:

----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>my.groupId</groupId>
    <artifactId>my-kar</artifactId>
    <version>1.0</version>
    <packaging>kar</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.karaf.tooling</groupId>
                <artifactId>karaf-maven-plugin</artifactId>
                <version>4.0.0</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>

</project>
----

To create the KAR file, simply type:

----
~$ mvn install
----

The kar will be installed in the `target` directory.

==== Commands

Apache Karaf provides `kar:*` commands to manage KAR archives.

===== `kar:list`

The `kar:list` command lists the installed KAR archives.

----
karaf@root()> kar:list
KAR Name
-------------------
my-kar-1.0-SNAPSHOT
----

A KAR is identified by its name.

===== `kar:create`

Instead of using the `karaf-maven-plugin` or create the KAR archive by hand, you can use the `kar:create` command.

The `kar:create` command creates a KAR file using a registered features repository.

For instance, you want to create a KAR file for the Pax Web repository.

The `feature:repo-list` command gives you the list of registered features repositories:

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

You can use one of these features repositories to create the kar file:

----
karaf@root()> kar:create org.ops4j.pax.web-8.0.2
Adding feature pax-web-karaf
Adding feature pax-web-core
Adding feature pax-web-http-tomcat
Adding feature pax-web-websockets
Adding feature pax-web-jetty
Adding feature pax-web-undertow
Adding feature pax-web-jetty-http2
Adding feature pax-web-http-undertow
Adding feature pax-web-whiteboard
Adding feature pax-web-tomcat-websockets
Adding feature pax-web-jsp
Adding feature pax-web-undertow-websockets
Adding feature pax-web-war
Adding feature pax-web-jetty-websockets
Adding feature pax-web-tomcat
Adding feature pax-web-jetty-http2-jdk8
Adding feature pax-web-http-jetty
Adding feature pax-web-jetty-http2-jdk9
Adding feature pax-web-specs
Kar file created : /data/servers/apache-karaf-4.4.0-SNAPSHOT/data/kar/org.ops4j.pax.web-8.0.2.kar
----

You can see that the KAR file has been created in the `KARAF_DATA/kar` folder.

By default, the `kar:create` command creates a KAR file, packaging all features in the features descriptor.

You can provide the list of features that you want to package into the KAR file:

----
karaf@root()> kar:create org.ops4j.pax.web-8.0.2 pax-web-http-jetty pax-web-jetty
Adding feature pax-web-core
Adding feature pax-web-jetty
Adding feature pax-web-http-jetty
Kar file created : /data/servers/apache-karaf-4.4.0-SNAPSHOT/data/kar/org.ops4j.pax.web-8.0.2.kar
----

===== `kar:install`

You can deploy a KAR file using `kar:install` command.

The `kar:install` command expects the KAR URL. Any URL described in the [Artifacts repositories and URLs section|urls]
is supported by the `kar:install` command:

----
karaf@root()> kar:install file:/tmp/my-kar-1.0-SNAPSHOT.kar
----

The KAR file is uncompressed and used to populate the `KARAF_BASE/system` folder.

The Apache Karaf KAR service is looking for features XML files in the KAR file, registers the features XML and automatically
installs all features described in the features repositories present in the KAR file.

Optionally, you can control if the bundles should be automatically started or not using `--no-start` option.

===== `kar:uninstall`

The `kar:uninstall` command uninstalls a KAR file (identified by a name).

By uninstall, it means that:

* the features previously installed by the KAR file are uninstalled
* delete (from the `KARAF_DATA/system` repository) all files previously "populated" by the KAR file

For instance, to uninstall the previously installed `my-kar-1.0-SNAPSHOT.kar` KAR file:

----
karaf@root()> kar:uninstall my-kar-1.0-SNAPSHOT
----

==== Deployer

Apache Karaf also provides a KAR deployer. It means that you can drop a KAR file directly in the `deploy` folder.

Apache Karaf will automatically install KAR files from the `deploy` folder.

You can change the behaviours of the KAR deployer in the `etc/org.apache.karaf.kar.cfg`:

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

#
# Enable or disable the refresh of the bundles when installing
# the features contained in a KAR file
#
noAutoRefreshBundles=false

#
# Enable or disable the automatic start of the bundles when installing
# the features contained in a KAR file
#
noAutoStartBundles=false

#
# Directory where the kar are stored (when downloaded from Maven for instance)
#
#karStorage=${karaf.data}/kar
----

By default, when the KAR deployer installs features, it refreshes the bundles already installed.
You can disable the automatic bundles refresh by setting the `noAutoRefreshBundles` property to `false`.

==== JMX KarMBean

On the JMX layer, you have a MBean dedicated to the management of the KAR files.

The ObjectName to use is `org.apache.karaf:type=kar,name=*`.

===== Attributes

The `Kars` attributes provides the list of KAR files (name) installed.

===== Operations

* `install(url)` installs the KAR file at the given `url`.
* `install(url, noAutoStartBundles)` installs the KAR file at the given `url`, deciding if you want to automatically start the bundles or not.
* `create(repository, features)` creates a KAR file using the given features `repository` name, and optionally the
list of `features` to include in the KAR file.
* `uninstall(name)` uninstalls a KAR file with the given `name`.
