# Customizing p2 Metadata

Disclaimer: Authoring p2 metadata is something we expect to support with better tooling in a future release. The support for customizing metadata with a p2.inf file is provisional although we expect to maintain a basic level of compatibility for common tasks.

On occasion the metadata that is automatically generated by p2 for bundles, features and products does not provide everything required to successfully provision an installable unit. For those cases p2 supports the use of an advice file (a p2.inf file) that can be used to augment the metadata for an installable unit. In this release the p2.inf file will allow an author to customize capabilities, properties, and instructions. In addition support is provided for defining additional installable units that are related to the container IU.

The touchpoint advice file is a java properties file and can be placed:

- In bundles (META-INF/p2.inf): The instructions are added to the installable unit for the bundle.
- In features (a p2.inf file co-located with the feature.xml): The instructions are added to the installable unit for the feature group.
- In products (a p2.inf file co-located with the .product file): The instructions are added to the root installable unit for that product.

Version substitution is a common practice and two special version parameters are supported:

- $version$ - returns the string form of the containing IU's version
- $qualifier$ - returns just the string form of the qualifier of the containing IU's version

One common use for advice files is to allow more fine grained control of the generation of categories used by the UI to group installable features

### Capability Advice

Note: Capability advice will "replace" an existing capability of the same type on the IU if the name and namespace match.

There are three different type of capability advice:

1. provides - these are capabilities that an IU will offer to satisfy the needs of other IUs.
2. requires - these are the capabilities that an IU requires from other IUs in order to resolve correctly.
3. metaRequirements - these are capabilities that the IU puts on the profile that must already be installed before this IU can be installed.

     provides.{#}.namespace = {namespace}
     provides.{#}.name = {name}
     provides.{#}.version = {version} (optional / default: 1.0.0)

     requires.{#}.namespace = {namespace}
     requires.{#}.name = {name}
     requires.{#}.range = {range} (optional / default: 0.0.0)]
     requires.{#}.matchExp = {p2QL expression} (note that in this case the namespace, name and range attributes are not used)
     requires.{#}.greedy = {true|false} (optional / default: true)
     requires.{#}.optional = {true|false} (optional / default: false)
     requires.{#}.multiple = {true|false}  (optional / default: false)
     requires.{#}.min = {integer}
     requires.{#}.max = {integer} (when min and max are specified the optional flag is ignored)

     metaRequirements.{#}.namespace = {namespace}
     metaRequirements.{#}.name = {name}
     metaRequirements.{#}.range = {range} (optional / default: 0.0.0)
     metaRequirements.{#}.matchExp = {p2QL expression} (note that in this case the namespace, name and range attributes are not used)
     metaRequirements.{#}.greedy = {true|false} (optional / default: true)
     metaRequirements.{#}.optional = {true|false} (optional / default: false)
     metaRequirements.{#}.multiple = {true|false}  (optional / default: false)
     metaRequirements.{#}.min = {integer}
     metaRequirements.{#}.max = {integer} (when min and max are specified the optional flag is ignored)

Where {#} is an index for the property, {namespace}, and {name} are the associated named strings, {version} and {range} are version and version range strings respectively.
For example:

     provides.0.namespace = testNamespace1
     provides.0.name = testName1
     provides.0.version = 1.2.3.$qualifier$
     provides.1.namespace = testNamespace2
     provides.1.name = testName2
     provides.1.version = $version$

     requires.0.namespace = testNamespace1
     requires.0.name = testName1
     requires.0.range = [1.2.3.$qualifier$, 2)
     requires.0.greedy = true
     requires.0.optional = true
     requires.0.multiple = true
     requires.1.namespace = testNamespace2
     requires.1.name = testName2
     requires.1.range = [$version$, $version$]
     requires.1.greedy = false

     metaRequirements.0.namespace = testNamespace1
     metaRequirements.0.name = testName1
     metaRequirements.0.range = [1.2.3, 2)
     metaRequirements.0.greedy = true
     metaRequirements.0.optional = true
     metaRequirements.0.multiple = true
     metaRequirements.1.namespace = testNamespace2
     metaRequirements.1.name = testName2
     metaRequirements.1.range = $version$
     metaRequirements.1.greedy = false

### Property Advice

     properties.{#}.name = {propertyName}
     properties.{#}.value = {propertyValue}

Where {#} is an index for the property, {propertyName}, and {propertyValue} hold the name and value strings for the property.
For example:

     properties.0.name = testName1
     properties.0.value = testValue1
     properties.1.name = testName2
     properties.1.value = testValue2

### Update Descriptor Advice

The update descriptor advice allows to override the default update descriptor generated by p2. Typically this is useful if an IU has been renamed and automatic update detection is still desired.

     update.id = {id of IU}
     update.range = {range of the IU being updated}
     update.matchExp = {a match expression identifying the IU being updated}. (When this is specified the values of id and range are ignored)
     update.severity = {0|1}

### Touchpoint Instruction Advice

     instructions.{phase} = {raw actions}
     instructions.{phase}.import = {qualified action name} [,{qualified action name}]* (optional)

Where {phase} is a p2 installation phase (collect, configure, install, uninstall, unconfigure, etc). Note:

- The {raw actions} will be "appended" to the end of any instructions already being generated.
- The qualified action names for the IU's touchpoint type are implicitly imported. All other actions need to be imported.

For example:

     instructions.install = \
        ln(targetDir:@artifact,linkTarget:foo/lib.1.so,linkName:lib.so);\
        chmod(targetDir:@artifact,targetFile:lib/lib.so,permissions:755);
     instructions.install.import= \
        org.eclipse.equinox.p2.touchpoint.natives.ln,\
        org.eclipse.equinox.p2.touchpoint.natives.chmod

Additional information on touchpoint instructions and action syntax can be found here.

### Additional Installable Unit Advice

In addition to customizing attributes of the containing IU one can also author additional installable units that work with the container IU. Typically this mechanism is used to author an IU fragment that customizes the containing IU or one of its dependencies.

     iu.{#}.id = {identifier}
     iu.{#}.version = {version} (optional)

Where {#} is an index for the installable unit, so multiple installable units can be declared. A full range of IU customizations are supported including:

     id
     version
     singleton
     copyright
     licenses
     filter
     touchpoint
     update
     artifacts
     properties
     provides
     requires
     metaRequirements
     hostRequirements
     instructions

To illustrate all the various settings for these customizations here's a more complete example of: (unit.0) a minimal IU and (unit.1) a full featured IU:

     units.0.id = testid0
     units.0.version = 1.2.3
     units.1.id = testid1
     units.1.version = 1.2.4
     units.1.singleton = true
     units.1.copyright = testCopyright
     units.1.copyright.location = http://localhost/test
     units.1.filter = test=testFilter
     units.1.touchpoint.id = testTouchpointId
     units.1.touchpoint.version = 1.2.5
     units.1.update.id = testid1
     units.1.update.range = (1,2)
     units.1.update.severity = 1
     units.1.update.description = some description
     units.1.artifacts.0.id = testArtifact1
     units.1.artifacts.0.version = 1.2.6
     units.1.artifacts.0.classifier = testClassifier1
     units.1.artifacts.1.id = testArtifact2
     units.1.artifacts.1.version = 1.2.7
     units.1.artifacts.1.classifier = testClassifier2
     units.1.licenses.0 = testLicense
     units.1.licenses.0.location = http://localhost/license
     units.1.properties.0.name = testName1
     units.1.properties.0.value = testValue1
     units.1.properties.1.name = testName2
     units.1.properties.1.value = testValue2
     units.1.requires.0.namespace = testNamespace1
     units.1.requires.0.name = testName1
     units.1.requires.0.range = [1.2.3.$qualifier$, 2)
     units.1.requires.0.greedy = true
     units.1.requires.0.optional = true
     units.1.requires.0.multiple = true
     units.1.requires.1.namespace = testNamespace2
     units.1.requires.1.name = testName2
     units.1.requires.1.range = $version$
     units.1.requires.1.greedy = false
     units.1.requires.1.optional = false
     units.1.metaRequirements.0.namespace = testNamespace1
     units.1.metaRequirements.0.name = testName1
     units.1.metaRequirements.0.range = [1.2.3.$qualifier$, 2)
     units.1.metaRequirements.0.greedy = true
     units.1.metaRequirements.0.optional = true
     units.1.metaRequirements.0.multiple = true
     units.1.metaRequirements.1.namespace = testNamespace2
     units.1.metaRequirements.1.name = testName2
     units.1.metaRequirements.1.range = $version$
     units.1.metaRequirements.1.greedy = false
     units.1.metaRequirements.1.optional = false
     units.1.provides.0.namespace = testNamespace1
     units.1.provides.0.name = testName1
     units.1.provides.0.version = 1.2.3.$qualifier$
     units.1.provides.1.namespace = testNamespace2
     units.1.provides.1.name = testName2
     units.1.provides.1.version = $version$
     units.1.instructions.configure = addProgramArg(programArg:-startup); addProgramArg(programArg:@artifact);
     units.1.instructions.unconfigure = removeProgramArg(programArg:-startup); removeProgramArg(programArg:@artifact);)
     units.1.instructions.unconfigure.import = some.removeProgramArg
     units.1.hostRequirements.0.namespace = testNamespace1
     units.1.hostRequirements.0.name = testName1
     units.1.hostRequirements.0.range = [1.2.3.$qualifier$, 2)
     units.1.hostRequirements.0.greedy = true
     units.1.hostRequirements.0.optional = true
     units.1.hostRequirements.0.multiple = true

## Category Generation Using p2.inf

The p2 UI allows for hierarchical organization of installable units based on the concept of "categories" where the children of categories are what's installable. On occasion we might want to take finer grained control of the contents of a category and what it contains. For example we might want to support further categorization of a feature's contents to allow individual plug-ins to be installed instead of the more typical features.

To support this we can tag a feature as a category as follows:

      properties.1.name=org.eclipse.equinox.p2.type.category
      properties.1.value=true

Another possibility is to use "additional IU advice" to create a specialized category IU like this:

      units.1.id=my.product.category
      units.1.version=1.0.0
      units.1.provides.1.namespace=org.eclipse.equinox.p2.iu
      units.1.provides.1.name=my.product.category
      units.1.provides.1.version=1.0.0
      units.1.properties.1.name=org.eclipse.equinox.p2.type.category
      units.1.properties.1.value=true
      units.1.properties.2.name=org.eclipse.equinox.p2.name
      units.1.properties.2.value=My Category Name
      requires.1.namespace=org.eclipse.equinox.p2.iu
      requires.1.name=my.product
      requires.1.range=[1.0.0,1.0.0]
      requires.1.greedy=true