<commit_before><?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (c) Contributors to the Eclipse Foundation
   
    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.
   
    SPDX-License-Identifier: Apache-2.0 
 -->

<chapter label="159"
         revision="$Id$"
         version="5.0" xml:id="service.feature"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:ns5="http://www.w3.org/2000/svg"
         xmlns:ns4="http://www.w3.org/1998/Math/MathML"
         xmlns:ns3="http://www.w3.org/1999/xhtml"
         xmlns:ns="http://docbook.org/ns/docbook">
  <title>Feature Service Specification</title>

  <info>
    <releaseinfo><xref endterm="org.osgi.service.feature-version"
    linkend="org.osgi.service.feature"/></releaseinfo>
  </info>

  <section>
    <title>Introduction</title>

    <para>
        OSGi has become a platform capable of running large applications for a variety of purposes, 
        including rich client applications, server-side systems and cloud and container based architectures. 
        As these applications are generally based on many bundles, describing each bundle individually 
        in an application definition becomes unwieldy once the number of bundles reaches a certain level. 
    </para>

    <para>
        When developing large scale applications it is often the case that few people know the role of every 
        single bundle or configuration item in the application. To keep the architecture understandable a grouping 
        mechanism is needed that allows for the representation of parts of the application into larger 
        entities that keep reasoning about the system manageable. In such a domain members of teams 
        spread across an organization will need to be able to both develop new parts for the application 
        as well as make tweaks or enhancements to parts developed by others such as adding configuration and 
        resources or changing one or more bundles relevant to their part of the application.
    </para>

    <para>
        The higher level constructs that define the application should be reusable in different contexts, 
        for example if one team has developed a component to handle job processing, different applications 
        should be able to use it, and if needed tune its configuration or other aspects so that it works in 
        each setting without having to know each and every detail that the job processing component is built 
        up from.
    </para>

    <para>
        Applications are often associated with additional resources or metadata, for example 
        database scripts or custom artifacts.
        By including these with the application definition, all the related entities are encapsulated in
        a single artifact. 
    </para>

    <para>
        By combining various applications 
        or subsystems together, systems are composed of existing, reusable building blocks, where all these 
        blocks can work together. 
        Architects of these systems need to think about components without having to dive into the 
        individual implementation details of each subcomponent. 
        The Features defined in this specification can be used to model such applications. Features
        contain the definition of an application or component and may be composed into larger systems.
    </para>


    <section>
      <title>Essentials</title>

      <itemizedlist>
        <listitem>
          <para><emphasis>Declarative</emphasis> - Features are declarative and can be mapped to different implementations.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Extensible</emphasis> - Features are extensible with custom content to facilitate all information related to 
          a Feature to be co-located.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Human Readable</emphasis> - No special software is needed to read or author Features.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Machine Readable</emphasis> - Features are easily be processed by tools.
          </para>
        </listitem>

      </itemizedlist>
    </section>

    <section>
      <title>Entities</title>

      <para>The following entities are used in this specification:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>Feature</emphasis> - A Feature contains a number of entities that, when provided to a 
          launcher can be turned into an executable system. Features are building blocks which 
          may be assembled into larger systems.</para>
        </listitem>

        <listitem>
          <para><emphasis>Bundles</emphasis> - A Feature can contain one ore more bundles.</para>
        </listitem>

        <listitem>
          <para><emphasis>Configuration</emphasis> - A Feature can contain configurations for the Configuration Admin service.</para>
        </listitem>

        <listitem>
          <para><emphasis>Extension</emphasis> - A Feature can contain a number of extensions with custom content.</para>
        </listitem>
        
        <listitem>
          <para><emphasis>Launcher</emphasis> - A launcher turns one or more Features into an executable system.</para>
        </listitem>
        
        <listitem>
          <para><emphasis>Processor</emphasis> - A Feature processor reads Features and perform a processing
          operation on them, such as validation, transformation or generation of new entities based on the Features.</para>
        </listitem>

        <listitem>
          <para><emphasis>Properties</emphasis> - Framework launching properties can be specified in a Feature.</para>
        </listitem>

      </itemizedlist>

      <figure pgwide="1">
        <title>Features Entity overview</title>

        <mediaobject>
          <imageobject>
            <imagedata align="center" contentdepth="5.100in"
                       contentwidth="6.000in" fileref="feature.svg"/>
          </imageobject>
        </mediaobject>
      </figure>
    </section>
  </section>

  <section>
    <title>Feature</title>

    <para>
      Features are defined by declaring JSON documents or by using the
      <link linkend="org.osgi.service.feature" xrefstyle="hyperlink">Feature API</link>.
      Each Feature has a unique ID which includes a version. It holds a number of entities, including a list of bundles, configurations and others. 
      Features are extensible, that is a Feature can also contain any number of custom entities which are related to the Feature.
    </para>

    <para>
Features may have dependencies on other Features. Features inherit the capabilities and requirements from all bundles listed in the Feature. 
    </para>

    <para>
      Once created, a Feature is immutable. Its definition cannot be modified. However it’s possible to record caching related information in a Feature through transient extensions.
      This cached content is not significant for the definition of the Feature or part of its identity.
    </para>

    <section xml:id="service.feature-identifiers">
      <title>Identifiers</title>

      <para>
        Identifiers used throughout this specification are defined using the Maven Identifier model. They are composed of the following parts:

        <itemizedlist>
          <listitem><para>Group ID</para></listitem>
          <listitem><para>Artifact ID</para></listitem>
          <listitem><para>Version</para></listitem>
          <listitem><para>Type (optional)</para></listitem>
          <listitem><para>Classifier (optional)</para></listitem>
        </itemizedlist>
        Note that if Version has the <code>-SNAPSHOT</code> suffix, the identifier points at an unreleased artifact that is
        under development and may still change.
      </para>
      <para>
        For more information see <xref linkend="service.feature-mvnpom.ref"/>.
        The format used to specify identifiers is as follows:
        <programlisting>group-id ':' artifact-id [ ':' type [ ':' classifier ] ] ':' version</programlisting>
      </para>
    </section>

    <section>
      <title>Feature Identifier</title>
      <para>
        Each Feature has a unique identifier. Apart from providing a persistent handle to the Feature it also provides enough information to find the Feature in an artifact repository. This identifier is defined using the format described in 
        <xref linkend="service.feature-identifiers"/>. 
      </para>
      
      <section>
	      <title>Identifier type</title>
	      <para>Features use as identifier type the value <code>osgifeature</code>.</para>
      </section>
    </section>
    
    <section>
      <title>Attributes</title>
      <para>
        A Feature can have the following attributes:
      </para>

      <table rowheader="firstcol">
        <title>Feature Attributes</title>

        <tgroup cols="4">
          <colspec colnum="4" colwidth="2.5*"/>
          <thead>
            <row>
              <entry>Attribute</entry>
              <entry>Data Type</entry>
              <entry>Kind</entry>
              <entry>Description</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>name</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The short descriptive name of the Feature.</entry>
            </row>
            
            <row>
              <entry>categories</entry>
              <entry>Array of String</entry>
              <entry>Optional, defaults to an empty array</entry>
              <entry>The categories this Feature belongs to. The values are user-defined.</entry>
            </row>

            <row>
              <entry>complete</entry>
              <entry>boolean</entry>
              <entry>Optional, defaults to <code>false</code></entry>
              <entry>Completeness of the Feature. A Feature is complete when it has no external dependencies.</entry>
            </row>

            <row>
              <entry>description</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>A longer description of the Feature.</entry>
            </row>
            
            <row>
              <entry>docURL</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>A location where documentation can be found for the Feature.</entry>
            </row>

            <row>
              <entry>license</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The license of the Feature. The license only relates to the Feature itself and not to any
              artifacts that might be referenced by the Feature. The license follows the <code>Bundle-License</code>
              format as specified in the Core specification.</entry>
            </row>
            
            <row>
              <entry>SCM</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>the SCM information relating to the feature. The syntax of the value
	          follows the Bundle-SCM format. See the 'Bundle Manifest Headers' section
	          in the OSGi Core specification.</entry>
            </row>

            <row>
              <entry>vendor</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The vendor of the Feature.</entry>
            </row>
          </tbody>
        </tgroup>
      </table>

      <para>
        An initial Feature without content can be declared as follows:
      </para>

      <programlisting>{
  "feature-resource-version": "1.0",
  "id": "org.acme:acmeapp:1.0.0",

  "name": "The ACME app",
  "description": 
    "This is the main ACME app, from where all functionality is reached."

  /*
    Additional Feature entities here
    ...
  */
}</programlisting>
      
    </section>
    <section>
      <title>Using the Feature API</title>
      <para>
        Features can also be created, read and written using the Feature API. The main entry point 
        for this API is the FeatureService. 
        <xref linkend="org.osgi.service.feature.FeatureService" xrefstyle="hyperlink"/>
        The Feature API uses
        the builder pattern to create entities used in Features.
      </para>
      
      <para>
        A builder instance is used to create a single entity and cannot be re-used to create a second one.
        Builders are created from the
        <xref linkend="org.osgi.service.feature.BuilderFactory" xrefstyle="hyperlink"/>, which is
        available from the FeatureService through
        <xref linkend="org.osgi.service.feature.FeatureService.getBuilderFactory--"
              xrefstyle="hyperlink"/>. 
     
      </para> 
      
      <programlisting>FeatureService fs = ... // from Service Registry
BuilderFactory factory = fs.getBuilderFactory();

FeatureBuilder builder = factory.newFeatureBuilder(
  fs.getID("org.acme", "acmeapp", "1.0.0"));
builder.setName("The ACME app");
builder.setDescription("This is the main ACME app, "
  + "from where all functionality is reached.");

Feature f = builder.build();</programlisting>
    </section>
  </section>

  <section>
    <title>Comments</title>
      <para>Comments in the form of <xref
      linkend="service.feature-jsmin.ref"/> comments are supported, that
      is, any text on the same line after <code>//</code> is ignored and any
      text between <code>/* */</code> is ignored.</para>
  </section>
  
  <section>
    <title>Bundles</title>
    <para>
      Features list zero or more bundles that implement the functionality provided by the Feature. Bundles are listed by 
      referencing them in the <code>bundles</code> array so that they can be resolved from a repository. Bundles can have 
      metadata associated with them, such 
      as the relative start order of the bundle in the Feature. 
      Custom metadata may also be provided. A single Feature can 
      provide multiple versions of the same bundle, if desired.
    </para>
    <para>
      Bundles are referenced using the identifier format described in 
      <xref linkend="service.feature-identifiers"/>.
      This means that Bundles are referenced using their Maven coordinates. The <code>bundles</code> array 
	  contains JSON objects which can contain the bundle
      IDs and specify optional additional metadata. 
    </para>

    <section>
      <title>Bundle Metadata</title>
      
      <para>
        Arbitrary key-value pairs can be associated with bundle entries to store
        custom metadata alongside the bundle references.
        Reverse DNS naming should be used with the keys to avoid name clashes when
        metadata is provided by multiple entities. Keys not using the reverse DNS 
        naming scheme are reserved for OSGi use.
      </para>
      
      <para>
        Bundle metadata supports String keys and <code>string</code>, 
        <code>number</code> or <code>boolean</code> values.
      </para>
    
      <para>
        The following example shows a simple Feature describing a small application with its dependencies:
        <programlisting>{
  "feature-resource-version": "1.0",
  "id": "org.acme:acmeapp:1.0.1",
    
  "name": "The Acme Application",
  "license": "https://opensource.org/licenses/Apache-2.0",
  "complete": true,

  "bundles": [
    { "id": "org.osgi:org.osgi.util.function:1.1.0" },
    { "id": "org.osgi:org.osgi.util.promise:1.1.1" },
    {
      "id": "org.apache.commons:commons-email:1.5",

      // This attribute is used by custom tooling to 
      // find the associated javadoc
      "org.acme.javadoc.link": 
        "https://commons.apache.org/proper/commons-email/javadocs/api-1.5"
    },
    { "id": "com.acme:acmelib:1.7.2" }      
  ]
   
  /* 
    Additional Feature entities here 
    ...
  */
}</programlisting>
      </para>
    </section>
    
    <section>
      <title>Using the Feature API</title>
      <para>
        A Feature with Bundles can be created using the Feature API as follows:
      </para>
      <programlisting>FeatureService fs = ... // from Service Registry
BuilderFactory factory = fs.getBuilderFactory();

FeatureBuilder builder = factory.newFeatureBuilder(
  fs.getID("org.acme", "acmeapp", "1.0.1"));
builder.setName("The Acme Application");
builder.setLicense("https://opensource.org/licenses/Apache-2.0");
builder.setComplete(true);

FeatureBundle b1 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.osgi:org.osgi.util.function:1.1.0"))
  .build();
FeatureBundle b2 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.osgi:org.osgi.util.promise:1.1.1"))
  .build();
FeatureBundle b3 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.apache.commons:commons-email:1.1.5"))
  .addMetadata("org.acme.javadoc.link",
    "https://commons.apache.org/proper/commons-email/javadocs/api-1.5")
  .build();
FeatureBundle b4 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "com.acme:acmelib:1.7.2"))
  .build();

builder.addBundles(b1, b2, b3, b4);
Feature f = builder.build();</programlisting>
    </section>
  </section>

  <section>
    <title>Configurations</title>
    <para>
      Features support configuration using the OSGi Configurator syntax, see 
      <xref linkend="service.configurator"/>. This is specified with the 
      <code>configurations</code> key in the Feature. A Launcher can apply 
      these configurations to the Configuration Admin service when starting 
      the system.
    </para>

    <para>
      It is an error to define the same PID twice in a single Feature. An entity 
      processing the feature must fail in this case.
    </para>
    
    <para>
      Example:
      <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:osgifeature:configs:1.0.0",
    "configurations": {
        "org.apache.felix.http": {
            "org.osgi.service.http.port": 8080,
            "org.osgi.service.http.port.secure": 8443
        }
    }    
}</programlisting>
    </para>
  </section>

  <section xml:id="service.feature-variables">
    <title>Variables</title>
    <para>
      Configurations and Framework Launching Properties support late binding of values. This enables setting these items through a Launcher,
      for example to specify a database user name, server port number or other information that may be variable between runtimes.
    </para>
    
    <para>
      Variables are declared in the <code>variables</code> section of the Feature and they can have a default value specified.
      The default must be of type <code>string</code>, <code>number</code> or <code>boolean</code>. Variables can also be declared
      to <emphasis>not</emphasis> have a default, which means that they must be provided with a value through the Launcher. 
      This is done by specifying <code>null</code> as the default in the variable declaration.
    </para>
    
    <para>
      Example:
      <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:osgifeature:configs:1.1.0",
    "variables": {
        "http.port": 8080,
        "db.username": "scott",
        "db.password": <PASSWORD>
    },
    "configurations": {
        "org.acme.server.http": {
            "org.osgi.service.http.port:Integer": "${http.port}"
        },
        "org.acme.db": {
            "username": "${db.username}-user",
            "password": <PASSWORD>}"
        }
    }    
}</programlisting>
      Variables are referenced with the curly brace placeholder syntax: <code>${</code> <emphasis><code>variable-name</code></emphasis> <code>}</code>
      in the configuration value or framework launching property value section.
      To support conversion of variables to non-string types the configurator syntax
      specifying the datatype with the configuration key is used, as in the above example.
    </para>
    
    <para>
      Multiple variables can be referenced for a single configuration or framework launching property value and variables may be combined with text.
      Variable substitution is applied recursively, that is if the value of a variable is again a variable it must be substituted.
      If no variable exist with the given name, then the <code>${</code> <emphasis><code>variable-name</code></emphasis> <code>}</code>
      must be retained in the value.
    </para>
  </section> 
    
  <section>
    <title>Extensions</title>
    <para>
      Features can include custom content. This makes it possible to keep custom entities and information relating to the Feature
    together with the rest of the Feature.</para>
    
    <para>
      Custom content is provided through Feature extensions, which are in one of the following formats:
    </para>
     
    <itemizedlist>
      <listitem>
        <para><emphasis>Text</emphasis> - A text extension contains an array of text.</para>
      </listitem>

      <listitem>
        <para><emphasis>JSON</emphasis> - A JSON extension contains embedded custom JSON content.</para>
      </listitem>

      <listitem>
        <para><emphasis>Artifacts</emphasis> - A list of custom artifacts associated with the Feature, listed as identifiers.</para>
      </listitem>
    </itemizedlist>
    
    <para>
      Extensions can have a variety of consumers. For example they may be handled by a Feature Launcher
      or by an external tool which can process the extension at any point of the Feature
      life cycle.
    </para>
    
    <para>
      Extensions are of one of the following three kinds:
    </para>
    
    <itemizedlist>
      <listitem>
        <para><emphasis>Mandatory</emphasis> - The entity processing this Feature 
        <emphasis>must</emphasis> know how to handle this extension.</para>
      </listitem>

      <listitem>
        <para><emphasis>Optional</emphasis> - This extension is optional. If the entity
        processing the Feature cannot handle it, the extension can be skipped or ignored.
        This is the default.</para>
      </listitem>

      <listitem>
        <para><emphasis>Transient</emphasis> - This extension contains transient information
        which may be used to optimize the processing of the Feature. It is not part of the 
        Feature definition.</para>
      </listitem>
    </itemizedlist>
    
    <para>
      Extensions are specified as JSON objects under the <code>extensions</code> key in the Feature. A Feature can
      contain any number of extensions, as long as the extension keys are unique.
      Extension keys should use reverse
      DNS naming to avoid name clashing of multiple extensions in a single Feature.
      Extensions names without DNS prefix are reserved for OSGi use.
    </para>
    
    <section>
      <title>Text Extensions</title>
      
      <para>
        Text extensions support the addition of custom text content to the Feature. 
        The text is provided as a JSON array of strings.
      </para>
      
      <para>
        Example:
        
        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.0.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",
    
    "extensions": {
        "org.acme.mydoc": {
            "type": "text",
            "text": [
                "This application provides the main acme ",
                "functionality."
            ]
        }
    }
}</programlisting>
        
      </para>
    </section>
    
    <section>
      <title>JSON Extensions</title>
      
      <para>
        Custom JSON content is added to Features by using a JSON extension. The content can either be a
        JSON object or a JSON array.
      </para>

      <para>
        The following example extension declares under which execution environment the Feature is complete,
        using a custom JSON object.       
        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.1.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",
    
    "extensions": {
        "execution-environment": {
            "type": "json",
            "json": {
                "environment-capabilities":
                    ["osgi.ee; filter:=\"(&amp;(osgi.ee=JavaSE)(version=11))\""], 
                "framework": "org.osgi:core:6.0.0",
                "provided-features": ["org.acme:platform:1.1"]
            }
        }
    }
}</programlisting>
      </para>
    </section>
      
    <section>
      <title>Artifact list Extension</title>
      
      <para>
        Custom extensions can be used to associate artifacts that are not listed 
        as <code>bundles</code> with the Feature.
      </para>
      
      <para>  
        For example, database definition resources may be listed as artifacts in a Feature. In
        the following example, the extension <code>org.acme.ddlfiles</code> lists 
        Database Definition Resources which <emphasis>must</emphasis> be handled by 
        the launcher agent, that is, the database must be configured when the application is run:

        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.2.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",<commit_msg>[Features] Usage via ServiceLoader<commit_after><?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (c) Contributors to the Eclipse Foundation
   
    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.
   
    SPDX-License-Identifier: Apache-2.0 
 -->

<chapter label="159"
         revision="$Id$"
         version="5.0" xml:id="service.feature"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:ns5="http://www.w3.org/2000/svg"
         xmlns:ns4="http://www.w3.org/1998/Math/MathML"
         xmlns:ns3="http://www.w3.org/1999/xhtml"
         xmlns:ns="http://docbook.org/ns/docbook">
  <title>Feature Service Specification</title>

  <info>
    <releaseinfo><xref endterm="org.osgi.service.feature-version"
    linkend="org.osgi.service.feature"/></releaseinfo>
  </info>

  <section>
    <title>Introduction</title>

    <para>
        OSGi has become a platform capable of running large applications for a variety of purposes, 
        including rich client applications, server-side systems and cloud and container based architectures. 
        As these applications are generally based on many bundles, describing each bundle individually 
        in an application definition becomes unwieldy once the number of bundles reaches a certain level. 
    </para>

    <para>
        When developing large scale applications it is often the case that few people know the role of every 
        single bundle or configuration item in the application. To keep the architecture understandable a grouping 
        mechanism is needed that allows for the representation of parts of the application into larger 
        entities that keep reasoning about the system manageable. In such a domain members of teams 
        spread across an organization will need to be able to both develop new parts for the application 
        as well as make tweaks or enhancements to parts developed by others such as adding configuration and 
        resources or changing one or more bundles relevant to their part of the application.
    </para>

    <para>
        The higher level constructs that define the application should be reusable in different contexts, 
        for example if one team has developed a component to handle job processing, different applications 
        should be able to use it, and if needed tune its configuration or other aspects so that it works in 
        each setting without having to know each and every detail that the job processing component is built 
        up from.
    </para>

    <para>
        Applications are often associated with additional resources or metadata, for example 
        database scripts or custom artifacts.
        By including these with the application definition, all the related entities are encapsulated in
        a single artifact. 
    </para>

    <para>
        By combining various applications 
        or subsystems together, systems are composed of existing, reusable building blocks, where all these 
        blocks can work together. 
        Architects of these systems need to think about components without having to dive into the 
        individual implementation details of each subcomponent. 
        The Features defined in this specification can be used to model such applications. Features
        contain the definition of an application or component and may be composed into larger systems.
    </para>


    <section>
      <title>Essentials</title>

      <itemizedlist>
        <listitem>
          <para><emphasis>Declarative</emphasis> - Features are declarative and can be mapped to different implementations.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Extensible</emphasis> - Features are extensible with custom content to facilitate all information related to 
          a Feature to be co-located.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Human Readable</emphasis> - No special software is needed to read or author Features.
          </para>
        </listitem>

        <listitem>
          <para><emphasis>Machine Readable</emphasis> - Features are easily be processed by tools.
          </para>
        </listitem>

      </itemizedlist>
    </section>

    <section>
      <title>Entities</title>

      <para>The following entities are used in this specification:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>Feature</emphasis> - A Feature contains a number of entities that, when provided to a 
          launcher can be turned into an executable system. Features are building blocks which 
          may be assembled into larger systems.</para>
        </listitem>

        <listitem>
          <para><emphasis>Bundles</emphasis> - A Feature can contain one ore more bundles.</para>
        </listitem>

        <listitem>
          <para><emphasis>Configuration</emphasis> - A Feature can contain configurations for the Configuration Admin service.</para>
        </listitem>

        <listitem>
          <para><emphasis>Extension</emphasis> - A Feature can contain a number of extensions with custom content.</para>
        </listitem>
        
        <listitem>
          <para><emphasis>Launcher</emphasis> - A launcher turns one or more Features into an executable system.</para>
        </listitem>
        
        <listitem>
          <para><emphasis>Processor</emphasis> - A Feature processor reads Features and perform a processing
          operation on them, such as validation, transformation or generation of new entities based on the Features.</para>
        </listitem>

        <listitem>
          <para><emphasis>Properties</emphasis> - Framework launching properties can be specified in a Feature.</para>
        </listitem>

      </itemizedlist>

      <figure pgwide="1">
        <title>Features Entity overview</title>

        <mediaobject>
          <imageobject>
            <imagedata align="center" contentdepth="5.100in"
                       contentwidth="6.000in" fileref="feature.svg"/>
          </imageobject>
        </mediaobject>
      </figure>
    </section>
  </section>

  <section>
    <title>Feature</title>

    <para>
      Features are defined by declaring JSON documents or by using the
      <link linkend="org.osgi.service.feature" xrefstyle="hyperlink">Feature API</link>.
      Each Feature has a unique ID which includes a version. It holds a number of entities, including a list of bundles, configurations and others. 
      Features are extensible, that is a Feature can also contain any number of custom entities which are related to the Feature.
    </para>

    <para>
Features may have dependencies on other Features. Features inherit the capabilities and requirements from all bundles listed in the Feature. 
    </para>

    <para>
      Once created, a Feature is immutable. Its definition cannot be modified. However it’s possible to record caching related information in a Feature through transient extensions.
      This cached content is not significant for the definition of the Feature or part of its identity.
    </para>

    <section xml:id="service.feature-identifiers">
      <title>Identifiers</title>

      <para>
        Identifiers used throughout this specification are defined using the Maven Identifier model. They are composed of the following parts:

        <itemizedlist>
          <listitem><para>Group ID</para></listitem>
          <listitem><para>Artifact ID</para></listitem>
          <listitem><para>Version</para></listitem>
          <listitem><para>Type (optional)</para></listitem>
          <listitem><para>Classifier (optional)</para></listitem>
        </itemizedlist>
        Note that if Version has the <code>-SNAPSHOT</code> suffix, the identifier points at an unreleased artifact that is
        under development and may still change.
      </para>
      <para>
        For more information see <xref linkend="service.feature-mvnpom.ref"/>.
        The format used to specify identifiers is as follows:
        <programlisting>group-id ':' artifact-id [ ':' type [ ':' classifier ] ] ':' version</programlisting>
      </para>
    </section>

    <section>
      <title>Feature Identifier</title>
      <para>
        Each Feature has a unique identifier. Apart from providing a persistent handle to the Feature it also provides enough information to find the Feature in an artifact repository. This identifier is defined using the format described in 
        <xref linkend="service.feature-identifiers"/>. 
      </para>
      
      <section>
	      <title>Identifier type</title>
	      <para>Features use as identifier type the value <code>osgifeature</code>.</para>
      </section>
    </section>
    
    <section>
      <title>Attributes</title>
      <para>
        A Feature can have the following attributes:
      </para>

      <table rowheader="firstcol">
        <title>Feature Attributes</title>

        <tgroup cols="4">
          <colspec colnum="4" colwidth="2.5*"/>
          <thead>
            <row>
              <entry>Attribute</entry>
              <entry>Data Type</entry>
              <entry>Kind</entry>
              <entry>Description</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>name</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The short descriptive name of the Feature.</entry>
            </row>
            
            <row>
              <entry>categories</entry>
              <entry>Array of String</entry>
              <entry>Optional, defaults to an empty array</entry>
              <entry>The categories this Feature belongs to. The values are user-defined.</entry>
            </row>

            <row>
              <entry>complete</entry>
              <entry>boolean</entry>
              <entry>Optional, defaults to <code>false</code></entry>
              <entry>Completeness of the Feature. A Feature is complete when it has no external dependencies.</entry>
            </row>

            <row>
              <entry>description</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>A longer description of the Feature.</entry>
            </row>
            
            <row>
              <entry>docURL</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>A location where documentation can be found for the Feature.</entry>
            </row>

            <row>
              <entry>license</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The license of the Feature. The license only relates to the Feature itself and not to any
              artifacts that might be referenced by the Feature. The license follows the <code>Bundle-License</code>
              format as specified in the Core specification.</entry>
            </row>
            
            <row>
              <entry>SCM</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>the SCM information relating to the feature. The syntax of the value
	          follows the Bundle-SCM format. See the 'Bundle Manifest Headers' section
	          in the OSGi Core specification.</entry>
            </row>

            <row>
              <entry>vendor</entry>
              <entry>String</entry>
              <entry>Optional</entry>
              <entry>The vendor of the Feature.</entry>
            </row>
          </tbody>
        </tgroup>
      </table>

      <para>
        An initial Feature without content can be declared as follows:
      </para>

      <programlisting>{
  "feature-resource-version": "1.0",
  "id": "org.acme:acmeapp:1.0.0",

  "name": "The ACME app",
  "description": 
    "This is the main ACME app, from where all functionality is reached."

  /*
    Additional Feature entities here
    ...
  */
}</programlisting>
      
    </section>
    <section>
      <title>Using the Feature API</title>
      <para>
        Features can also be created, read and written using the Feature API. The main entry point 
        for this API is the FeatureService. 
        <xref linkend="org.osgi.service.feature.FeatureService" xrefstyle="hyperlink"/>
        The Feature API uses
        the builder pattern to create entities used in Features.
      </para>
      
      <para>
        A builder instance is used to create a single entity and cannot be re-used to create a second one.
        Builders are created from the
        <xref linkend="org.osgi.service.feature.BuilderFactory" xrefstyle="hyperlink"/>, which is
        available from the FeatureService through
        <xref linkend="org.osgi.service.feature.FeatureService.getBuilderFactory--"
              xrefstyle="hyperlink"/>. 
     
      </para> 
      
      <programlisting>FeatureService fs = ... // from Service Registry
BuilderFactory factory = fs.getBuilderFactory();

FeatureBuilder builder = factory.newFeatureBuilder(
  fs.getID("org.acme", "acmeapp", "1.0.0"));
builder.setName("The ACME app");
builder.setDescription("This is the main ACME app, "
  + "from where all functionality is reached.");

Feature f = builder.build();</programlisting>

	  <para>
	    The Feature API can also be useful in environments outside of an OSGi Framework where no service registry
	    is available, for example in a build-system
	    environment.
	    In such environments the FeatureService can be obtained by using the <code>java.util.ServiceLoader</code>
	    mechanism.
	  </para>
    </section>
  </section>

  <section>
    <title>Comments</title>
      <para>Comments in the form of <xref
      linkend="service.feature-jsmin.ref"/> comments are supported, that
      is, any text on the same line after <code>//</code> is ignored and any
      text between <code>/* */</code> is ignored.</para>
  </section>
  
  <section>
    <title>Bundles</title>
    <para>
      Features list zero or more bundles that implement the functionality provided by the Feature. Bundles are listed by 
      referencing them in the <code>bundles</code> array so that they can be resolved from a repository. Bundles can have 
      metadata associated with them, such 
      as the relative start order of the bundle in the Feature. 
      Custom metadata may also be provided. A single Feature can 
      provide multiple versions of the same bundle, if desired.
    </para>
    <para>
      Bundles are referenced using the identifier format described in 
      <xref linkend="service.feature-identifiers"/>.
      This means that Bundles are referenced using their Maven coordinates. The <code>bundles</code> array 
	  contains JSON objects which can contain the bundle
      IDs and specify optional additional metadata. 
    </para>

    <section>
      <title>Bundle Metadata</title>
      
      <para>
        Arbitrary key-value pairs can be associated with bundle entries to store
        custom metadata alongside the bundle references.
        Reverse DNS naming should be used with the keys to avoid name clashes when
        metadata is provided by multiple entities. Keys not using the reverse DNS 
        naming scheme are reserved for OSGi use.
      </para>
      
      <para>
        Bundle metadata supports String keys and <code>string</code>, 
        <code>number</code> or <code>boolean</code> values.
      </para>
    
      <para>
        The following example shows a simple Feature describing a small application with its dependencies:
        <programlisting>{
  "feature-resource-version": "1.0",
  "id": "org.acme:acmeapp:1.0.1",
    
  "name": "The Acme Application",
  "license": "https://opensource.org/licenses/Apache-2.0",
  "complete": true,

  "bundles": [
    { "id": "org.osgi:org.osgi.util.function:1.1.0" },
    { "id": "org.osgi:org.osgi.util.promise:1.1.1" },
    {
      "id": "org.apache.commons:commons-email:1.5",

      // This attribute is used by custom tooling to 
      // find the associated javadoc
      "org.acme.javadoc.link": 
        "https://commons.apache.org/proper/commons-email/javadocs/api-1.5"
    },
    { "id": "com.acme:acmelib:1.7.2" }      
  ]
   
  /* 
    Additional Feature entities here 
    ...
  */
}</programlisting>
      </para>
    </section>
    
    <section>
      <title>Using the Feature API</title>
      <para>
        A Feature with Bundles can be created using the Feature API as follows:
      </para>
      <programlisting>FeatureService fs = ... // from Service Registry
BuilderFactory factory = fs.getBuilderFactory();

FeatureBuilder builder = factory.newFeatureBuilder(
  fs.getID("org.acme", "acmeapp", "1.0.1"));
builder.setName("The Acme Application");
builder.setLicense("https://opensource.org/licenses/Apache-2.0");
builder.setComplete(true);

FeatureBundle b1 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.osgi:org.osgi.util.function:1.1.0"))
  .build();
FeatureBundle b2 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.osgi:org.osgi.util.promise:1.1.1"))
  .build();
FeatureBundle b3 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "org.apache.commons:commons-email:1.1.5"))
  .addMetadata("org.acme.javadoc.link",
    "https://commons.apache.org/proper/commons-email/javadocs/api-1.5")
  .build();
FeatureBundle b4 = factory
  .newBundleBuilder(fs.getIDfromMavenCoordinates(
    "com.acme:acmelib:1.7.2"))
  .build();

builder.addBundles(b1, b2, b3, b4);
Feature f = builder.build();</programlisting>
    </section>
  </section>

  <section>
    <title>Configurations</title>
    <para>
      Features support configuration using the OSGi Configurator syntax, see 
      <xref linkend="service.configurator"/>. This is specified with the 
      <code>configurations</code> key in the Feature. A Launcher can apply 
      these configurations to the Configuration Admin service when starting 
      the system.
    </para>

    <para>
      It is an error to define the same PID twice in a single Feature. An entity 
      processing the feature must fail in this case.
    </para>
    
    <para>
      Example:
      <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:osgifeature:configs:1.0.0",
    "configurations": {
        "org.apache.felix.http": {
            "org.osgi.service.http.port": 8080,
            "org.osgi.service.http.port.secure": 8443
        }
    }    
}</programlisting>
    </para>
  </section>

  <section xml:id="service.feature-variables">
    <title>Variables</title>
    <para>
      Configurations and Framework Launching Properties support late binding of values. This enables setting these items through a Launcher,
      for example to specify a database user name, server port number or other information that may be variable between runtimes.
    </para>
    
    <para>
      Variables are declared in the <code>variables</code> section of the Feature and they can have a default value specified.
      The default must be of type <code>string</code>, <code>number</code> or <code>boolean</code>. Variables can also be declared
      to <emphasis>not</emphasis> have a default, which means that they must be provided with a value through the Launcher. 
      This is done by specifying <code>null</code> as the default in the variable declaration.
    </para>
    
    <para>
      Example:
      <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:osgifeature:configs:1.1.0",
    "variables": {
        "http.port": 8080,
        "db.username": "scott",
        "db.password": <PASSWORD>
    },
    "configurations": {
        "org.acme.server.http": {
            "org.osgi.service.http.port:Integer": "${http.port}"
        },
        "org.acme.db": {
            "username": "${db.username}-user",
            "password": <PASSWORD>}"
        }
    }    
}</programlisting>
      Variables are referenced with the curly brace placeholder syntax: <code>${</code> <emphasis><code>variable-name</code></emphasis> <code>}</code>
      in the configuration value or framework launching property value section.
      To support conversion of variables to non-string types the configurator syntax
      specifying the datatype with the configuration key is used, as in the above example.
    </para>
    
    <para>
      Multiple variables can be referenced for a single configuration or framework launching property value and variables may be combined with text.
      Variable substitution is applied recursively, that is if the value of a variable is again a variable it must be substituted.
      If no variable exist with the given name, then the <code>${</code> <emphasis><code>variable-name</code></emphasis> <code>}</code>
      must be retained in the value.
    </para>
  </section> 
    
  <section>
    <title>Extensions</title>
    <para>
      Features can include custom content. This makes it possible to keep custom entities and information relating to the Feature
    together with the rest of the Feature.</para>
    
    <para>
      Custom content is provided through Feature extensions, which are in one of the following formats:
    </para>
     
    <itemizedlist>
      <listitem>
        <para><emphasis>Text</emphasis> - A text extension contains an array of text.</para>
      </listitem>

      <listitem>
        <para><emphasis>JSON</emphasis> - A JSON extension contains embedded custom JSON content.</para>
      </listitem>

      <listitem>
        <para><emphasis>Artifacts</emphasis> - A list of custom artifacts associated with the Feature, listed as identifiers.</para>
      </listitem>
    </itemizedlist>
    
    <para>
      Extensions can have a variety of consumers. For example they may be handled by a Feature Launcher
      or by an external tool which can process the extension at any point of the Feature
      life cycle.
    </para>
    
    <para>
      Extensions are of one of the following three kinds:
    </para>
    
    <itemizedlist>
      <listitem>
        <para><emphasis>Mandatory</emphasis> - The entity processing this Feature 
        <emphasis>must</emphasis> know how to handle this extension.</para>
      </listitem>

      <listitem>
        <para><emphasis>Optional</emphasis> - This extension is optional. If the entity
        processing the Feature cannot handle it, the extension can be skipped or ignored.
        This is the default.</para>
      </listitem>

      <listitem>
        <para><emphasis>Transient</emphasis> - This extension contains transient information
        which may be used to optimize the processing of the Feature. It is not part of the 
        Feature definition.</para>
      </listitem>
    </itemizedlist>
    
    <para>
      Extensions are specified as JSON objects under the <code>extensions</code> key in the Feature. A Feature can
      contain any number of extensions, as long as the extension keys are unique.
      Extension keys should use reverse
      DNS naming to avoid name clashing of multiple extensions in a single Feature.
      Extensions names without DNS prefix are reserved for OSGi use.
    </para>
    
    <section>
      <title>Text Extensions</title>
      
      <para>
        Text extensions support the addition of custom text content to the Feature. 
        The text is provided as a JSON array of strings.
      </para>
      
      <para>
        Example:
        
        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.0.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",
    
    "extensions": {
        "org.acme.mydoc": {
            "type": "text",
            "text": [
                "This application provides the main acme ",
                "functionality."
            ]
        }
    }
}</programlisting>
        
      </para>
    </section>
    
    <section>
      <title>JSON Extensions</title>
      
      <para>
        Custom JSON content is added to Features by using a JSON extension. The content can either be a
        JSON object or a JSON array.
      </para>

      <para>
        The following example extension declares under which execution environment the Feature is complete,
        using a custom JSON object.       
        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.1.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",
    
    "extensions": {
        "execution-environment": {
            "type": "json",
            "json": {
                "environment-capabilities":
                    ["osgi.ee; filter:=\"(&amp;(osgi.ee=JavaSE)(version=11))\""], 
                "framework": "org.osgi:core:6.0.0",
                "provided-features": ["org.acme:platform:1.1"]
            }
        }
    }
}</programlisting>
      </para>
    </section>
      
    <section>
      <title>Artifact list Extensions</title>
      
      <para>
        Custom extensions can be used to associate artifacts that are not listed 
        as <code>bundles</code> with the Feature.
      </para>
      
      <para>  
        For example, database definition resources may be listed as artifacts in a Feature. In
        the following example, the extension <code>org.acme.ddlfiles</code> lists 
        Database Definition Resources which <emphasis>must</emphasis> be handled by 
        the launcher agent, that is, the database must be configured when the application is run:

        <programlisting>{
    "feature-resource-version": "1.0",
    "id": "org.acme:acmeapp:2.2.0",
    
    "name": "The Acme Application",
    "license": "https://opensource.org/licenses/Apache-2.0",
{'fraction_non_alphanumeric': 0.0969353827446659, 'fraction_numerical': 0.0060798358444322, 'mean_word_length': 2.4365369548184903, 'pattern_counts': {'":': 112, '<': 1011, '<?xml version=': 2, '>': 1011, 'https://': 14, 'lorem ipsum': 0, 'www.': 12, 'xml': 22}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5989766', 'n_tokens_mistral': 14302, 'n_tokens_neox': 13631, 'n_words': 4957}