62. Manifest¶
As SolarNode plugins are OSGi bundles, which are Java JAR files, every plugin automatically includes
a META-INF/MANIFEST.MF
file as defined in the Java JAR File Specification. The
MANIFEST.MF
file is where OSGi metadata is included, turning the JAR into an OSGi bundle (plugin).
62.1 Example¶
Here is an example snippet from the SolarNode net.solarnetwork.common.jdt plugin:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Java Compiler Service (JDT)
Bundle-SymbolicName: net.solarnetwork.common.jdt
Bundle-Description: Java complier using Eclipse JDT.
Bundle-Version: 3.0.0
Bundle-Vendor: SolarNetwork
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Activator: net.solarnetwork.common.jdt.Activator
Export-Package:
net.solarnetwork.common.jdt;version="2.0.0"
Import-Package:
net.solarnetwork.service;version="[1.0,2.0)",
org.eclipse.jdt.core.compiler,
org.eclipse.jdt.internal.compiler,
org.osgi.framework;version="[1.5,2.0)",
org.slf4j;version="[1.7,2.0)",
org.springframework.context;version="[5.3,6.0)",
org.springframework.core.io;version="[5.3,6.0)",
org.springframework.util;version="[5.3,6.0)"
The rest of this document will describe this structure in more detail.
62.2 Versioning¶
In OSGi plugins are always versioned and and Java packages may be versioned. Versions follow Semantic Versioning rules, generally using this syntax:
major.minor.patch
In the manifest example you can see the plugin version 3.0.0
declared in the
Bundle-Version
attribute:
Bundle-Version: 3.0.0
The example also declares (exports) a net.solarnetwork.common.jdt
package for
other plugins to import (use) as version 2.0.0
, in the Export-Package
attribute:
Export-Package:
net.solarnetwork.common.jdt;version="2.0.0"
The example also uses (imports) a versioned package
net.solarnetwork.service
using a version range greater than or equal to 1.0
and less than
2.0
and an unversioned package org.eclipse.jdt.core.compiler
, in the Import-Package
attribute:
Import-Package:
net.solarnetwork.service;version="[1.0,2.0)",
org.eclipse.jdt.core.compiler,
Tip
Some plugins, and core Java system packages, do not declare package versions. You should declare package versions in your own plugins.
62.3 Version ranges¶
Some OSGi version attributes allow version ranges to be declared, such as the Import-Package
attribute. A version range is a comma-delimited lower,upper
specifier. Square brackets are used to
represent inclusive values and round brackets represent exclusive values. A value can be
omitted to reprsent an unbounded value. Here are some examples:
Range | Logic | Description |
---|---|---|
[1.0,2.0) |
1.0.0 ≤ x < 2.0.0 | Greater than or equal to 1.0.0 and less than 2.0.0 |
(1,3) |
1.0.0 < x < 3.0.0 | Greater than 1.0.0 and less than 3.0.0 |
[1.3.2,) |
1.3.2 ≤ x | Greater than or eequal to 1.3.2 |
1.3.2 |
1.3.2 ≤ x | Greater than or eequal to 1.3.2 (shorthand notation) |
Implied unbounded range
An inclusive lower, unbounded upper range can be specifeid using a shorthand
notation of just the lower bound, like 1.3.2
.
62.4 Required attributes¶
Each plugin must provide the following attributes:
Attribute | Example | Description |
---|---|---|
Bundle-ManifestVersion |
2 | declares the OSGi bundle manifest version; always 2 |
Bundle-Name |
Awesome Data Source | a concise human-readable name for the plugin |
Bundle-SymbolicName |
com.example.awesome | a machine-readable, universally unique identifier for the plugin |
Bundle-Version |
1.0.0 | the plugin version |
Bundle-RequiredExecutionEnvironment |
JavaSE-1.8 | a required OSGi execution environment |
62.5 Recommended attributes¶
Each plugin is recommended to provide the following attributes:
Attribute | Example | Description |
---|---|---|
Bundle-Description |
An awesome data source that collects awesome data. | a longer human-readable description of the plugin |
Bundle-Vendor |
ACME Corp | the name of the entity or organisation that authored the plugin |
62.6 Common attributes¶
Other common manifest attributes are:
Attribute | Example | Description |
---|---|---|
Bundle-Activator |
com.example.awesome.Activator | a fully-qualified Java class name that implements the org.osgi.framework.BundleActivator interface, to handle plugin lifecycle events; see Activator for more information |
Export-Package |
net.solarnetwork.common.jdt;version="2.0.0" | a package export list |
Import-Package |
net.solarnetwork.service;version="[1.0,2.0)" | a package dependency list |
62.7 Package dependencies¶
A plugin must declare the Java packages it directly uses in a Import-Package
attribute. This
attribute accpets a comma-delimited list of package specifications that take the basic form of:
PACKAGE;version="VERSION"
For example here is how the net.solarnetwork.service
package, versioned between 1.0
and 2.0
,
would be declared:
Import-Package: net.solarnetwork.service;version="[1.0,2.0)"
Direct package use means your plugin has code that imports a class from a given package. Classes in an imported package may import other packages indirectly; you do not need to import those packages as well. For example if you have code like this:
import net.solarnetwork.service.OptionalService;
Then you will need to import the net.solarnetwork.service
package.
Note
The SolarNode platform automatically imports core Java packages like java.*
so you do not need
to declare those.
Also note that in some scenarios a package used by a class in an imported package becomes a direct dependency. For example when you extend a class from an imported package and that class imports other packages. Those other packages may become direct dependencies that you also need to import.
62.7.1 Child package dependencies¶
If you import a package in your plugin, any child packages that may exist are not imported as well. You must import every individual package you need to use in your plugin.
For example to use both net.solarnetwork.service
and net.solarnetwork.service.support
you would
have an Import-Package
attribute like this:
Import-Package:
net.solarnetwork.service;version="[1.0,2.0)",
net.solarnetwork.service.support;version="[1.1,2.0)"
62.8 Package exports¶
A plugin can export any package it provides, making the resources within that package available to
other plugins to import and use. Declare exoprted packages with a Export-Package
attribute. This
attribute takes a comma-delimited list of versioned package specifications. Note that version
ranges are not supported: you must declare the exact version of the package you are exporting.
For example:
Export-Package: com.example.service;version="1.0.0"
Note
Exported packages should not be confused with services. Exported packages give other plugins access to the classes and any other resources within those packages, but do not provide services to the platform. You can use Blueprint to register services. Keep in mind that any service a plugin registers must exist within an exported package to be of any use.