diff --git a/bndtools.core/bndtools.shared.bndrun b/bndtools.core/bndtools.shared.bndrun index bfe23a4a04..b1ac245963 100644 --- a/bndtools.core/bndtools.shared.bndrun +++ b/bndtools.core/bndtools.shared.bndrun @@ -47,6 +47,7 @@ bnd.identity;id='org.bndtools.headless.build.manager',\ bnd.identity;id='org.bndtools.headless.build.plugin.ant',\ bnd.identity;id='org.bndtools.headless.build.plugin.gradle',\ + bnd.identity;id='org.bndtools.help',\ bnd.identity;id='org.bndtools.launch',\ bnd.identity;id='org.bndtools.remoteinstall',\ bnd.identity;id='org.bndtools.templates.template',\ diff --git a/bndtools.core/bndtools.shared.latest.bndrun b/bndtools.core/bndtools.shared.latest.bndrun index 43e9c32a34..c62588f34e 100644 --- a/bndtools.core/bndtools.shared.latest.bndrun +++ b/bndtools.core/bndtools.shared.latest.bndrun @@ -47,6 +47,7 @@ bnd.identity;id='org.bndtools.headless.build.manager',\ bnd.identity;id='org.bndtools.headless.build.plugin.ant',\ bnd.identity;id='org.bndtools.headless.build.plugin.gradle',\ + bnd.identity;id='org.bndtools.help',\ bnd.identity;id='org.bndtools.launch',\ bnd.identity;id='org.bndtools.remoteinstall',\ bnd.identity;id='org.bndtools.templates.template',\ diff --git a/org.bndtools.help/.gitignore b/org.bndtools.help/.gitignore new file mode 100644 index 0000000000..fa76fa8af6 --- /dev/null +++ b/org.bndtools.help/.gitignore @@ -0,0 +1,3 @@ +bin/ +bin_test/ +generated/ diff --git a/org.bndtools.help/.project b/org.bndtools.help/.project new file mode 100644 index 0000000000..9e1f85742d --- /dev/null +++ b/org.bndtools.help/.project @@ -0,0 +1,17 @@ + + + org.bndtools.help + + + + + + bndtools.core.bndbuilder + + + + + + bndtools.core.bndnature + + diff --git a/org.bndtools.help/_plugin.xml b/org.bndtools.help/_plugin.xml new file mode 100644 index 0000000000..f6e173659b --- /dev/null +++ b/org.bndtools.help/_plugin.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/org.bndtools.help/bnd.bnd b/org.bndtools.help/bnd.bnd new file mode 100644 index 0000000000..90f046984e --- /dev/null +++ b/org.bndtools.help/bnd.bnd @@ -0,0 +1,12 @@ +# Set javac settings from JDT prefs +-include: ${workspace}/cnf/includes/bndtools.bnd + +Bundle-SymbolicName: ${p};singleton:=true +Bundle-Name: Bndtools Help Documentation + +-resourceonly: true + +-includeresource: \ + {plugin.xml=_plugin.xml},\ + toc.xml=toc.xml,\ + docs/=docs/ diff --git a/org.bndtools.help/docs/chapters/110-introduction.html b/org.bndtools.help/docs/chapters/110-introduction.html new file mode 100644 index 0000000000..01255317c7 --- /dev/null +++ b/org.bndtools.help/docs/chapters/110-introduction.html @@ -0,0 +1,56 @@ + + + + +Introduction + + + +

Introduction

+

bnd is the Swiss army knife of OSGi, it is used for creating and working with OSGi bundles. +Its primary goal is take the pain out of developing bundles.

+

bnd consists of two major parts

+

Its primary function is generating OSGi meta data by analyzing Java classes. There are plugins for popular tools like Eclipse, Maven and Gradle.

+

The other part is a IDE/build tool independent model of a workspace with projects.

+

OSGi without bnd

+

With OSGi you are forced to provide additional metadata in the JAR's manifest to verify the consistency of your "class path". This metadata must be closely aligned with the class files in the bundle and the policies that a company has about versioning. Maintaining this metdata is an error prone chore because many aspects are redundant.

+

OSGi with bnd

+

bnd's raison d'etre is therefore to remove the chores and use the redundancy to create the manifest from the class files instead of maintaining it by hand. The core task is therefore to analyze the class files and find any dependencies. These dependencies are then merged with ''instructions'' supplied by the user. For example, adding a version to all imported packages from a specific library can be specified as:

+
Import-Package: com.library.*; version = 1.21
+
+ +

The OSGi manifest must explicitly mention a package, bnd allows the use of wildcards. bnd contains many more such conveniences. bnd roots are about 10 years old and bnd has therefore a large number of functions that remove such chores. These range from simplifying the use of OSGi Declarative Services, working with Spring and Blueprint, WAR and WAB files, version analysis, project dependencies, and much more.

+

Over time bnd started to appear in many different incarnations. It is an an ant task, a command line utility, and a bundle for Eclipse. Other projects have used bndlib to create a maven plugin, bndtools and Sigil both Eclipse IDEs, and others. By keeping the core library small and uncoupled (bnd has no external connections except Java 5), it is easy to embed the functionality in other projects.

+

Workflow

+

Traditionally, JAR files were made with the JDK jar tool, the jar ant task, or the Maven packager. All these tools share the same concept. The developer creates a directory image of the jar by copying files to a directory; this directory is then jarred. This model can be called the ''push'' model. Obviously this method works well.

+

bnd works differently, it uses the ''pull'' model. Instructions in the bnd file describe the contents of the desired JAR file without writing this structure to disk. The contents from the output can come from the class path or from anywhere in the file system. For example, the following instruction includes the designated packages in the JAR:

+

Private-Package: com.example.*

+

bnd can create a JAR from packages the sources, directories or other JAR files. You never have to copy files around, the instructions that Bnd receives are sufficient to retrieve the files from their original location, preprocessing or filtering when required.

+

The Jar is constructed from 3 different arguments:

+
Export-Package
+Private-Package
+Include-Resource
+
+ +

Private-Package and Export-Package contain ''instructions''. Instructions are patterns + attributes and directives, looking like normal OSGi attributes and directives. For example:

+
Export-Package: com.acme.*;version=1.2
+
+ +

Each instruction is applied to each package on the classpath in the definition order. That is, if an earlier instruction matches, the later instruction never gets a chance to do its work. If an instruction matches its attributes and properties are applied to the packages. The difference between the Private-Package argument and the Export-Package arguments is that the export version selects the packages for export. If the packages overlap between the two, the export wins.

+

An instruction can also be negative when it starts with a '!'. In that case the package is excluded from the selection. For example:

+
Export-Package: !com.acme.impl, com.acme.*;version=1.2
+
+ +

Note that the instructions are applied in order. If the ! instruction was at the end in the previous example, it would not have done its work because the com.acme.* would already have matched.

+

The Include-Resource argument can be used to copy resources from the file system in the JAR. This is useful for licenses, images, etc. The instructions in the argument can be a directory, a file, or an inline JAR. The default JAR path is the the root for a directory or the filename for a file. The path can be overridden. Instructions that are enclosed in curly braces, like {license.txt}, are pre-processed, expanding any macros in the file.

+

Once the JAR is created, the bnd program analyzes the classes and creates an import list with all the packages that are not contained in the jar but which are referred to. This import list is matched against the Import-Package instructions. Normally, the Import-Package argument is *; all referred packages will be imported. However, sometimes it is necessary to ignore an import or provide attributes on the import statement. For example, make the import optional or discard the import:

+
Import-Package: !com.acme.*, *;resolution:=optional
+
+ +

The arguments to bnd are normal given as a set of properties. Properties that begin with an upper case are copied to the manifest (possibly after processing). Lower case properties are used for macro variables but are not set as headers in the manifest.

+

After the JAR is created, the bnd program will verify the result. This will check the resulting manifest in painstaking detail.

+

The bnd program works on a higher level then traditional jarring; this might take some getting used to. However, it is much more elegant to think in packages than that it is to think in files. The fact that bnd understand the semantics of a bundle allows it to detect many errors and allows bundles to be created with almost no special information.

+

bnd will not create an output file if none of the resources is newer than an existing output file.

+

The program is available in several forms: command line, ant task, maven plugin, and an Eclipse plugin.

+ + diff --git a/org.bndtools.help/docs/chapters/120-install.html b/org.bndtools.help/docs/chapters/120-install.html new file mode 100644 index 0000000000..76d79a4943 --- /dev/null +++ b/org.bndtools.help/docs/chapters/120-install.html @@ -0,0 +1,61 @@ + + + + +How to install bnd + + + +

How to install bnd

+

bnd is not a single product, it is a library (bndlib) used in many different software build environments. It runs inside Maven, ant, gradle, Eclipse, sbt, and maybe one day in Intellij. To install bnd, you will have to install these tools.

+
+ +
+ +

Command Line

+

That said, there is also a command line version of bnd, providing an easy way to try out its many features. You can install bnd through brew on MacOS.

+

You can also run bnd command as executable jar, which can be downloaded from JFrog:

+
# Install bnd CLI
+curl -Lk -o ~/biz.aQute.bnd.jar \
+    https://bndtools.jfrog.io/artifactory/update-latest/biz/aQute/bnd/biz.aQute.bnd/7.2.1/biz.aQute.bnd-7.2.1.jar
+
+# create alias for easy use via 'bnd'
+alias bnd='java -jar ~/biz.aQute.bnd.jar'
+
+# display bnd version to verify installation
+bnd version
+
+# Run commands
+bnd <command>
+
+# Example
+bnd help
+
+ +

Libraries

+

The binaries are available on JFrog:

+ +

If you are a maven user, you can find many versions in central. The coordinates are:

+
    <dependency>
+        <groupId>biz.aQute.bnd</groupId>
+        <artifactId>biz.aQute.bndlib</artifactId>
+        <version>7.1.0</version>
+    </dependency>
+
+ +

Source Code

+

bnd is maintained at github. If you want to change the code, just clone it and modify it. In general we accept pull requests, and often even highly appreciate them.

+

Manual

+

The manual is also on github. If you see an improvement, do not hesitate to clone the repo and create a pull request. Improvements are bug corrections but we also like short articles about how to do do something with bnd.

+

Communication Settings

+

If you're behind a firewall that requires proxies or you use repositories that require authentication see -connection-settings.

+ + diff --git a/org.bndtools.help/docs/chapters/123-tour-workspace.html b/org.bndtools.help/docs/chapters/123-tour-workspace.html new file mode 100644 index 0000000000..6bc04f1c40 --- /dev/null +++ b/org.bndtools.help/docs/chapters/123-tour-workspace.html @@ -0,0 +1,132 @@ + + + + +Guided Tour Workspace & Projects + + + +

Guided Tour Workspace & Projects

+

The bnd workspace is a foundational concept in bnd, providing the structure and context in which OSGi projects are developed and built.

+

In the introduction we mentioned this as the second part of bnd:

+
+

The other part is a IDE/build tool independent model of a workspace with projects.

+
+

This guide provides a high-level overview of how to set up and use bndlib workspaces and projects. It is aimed at build engineers or developers responsible for configuring OSGi builds using bnd, and it focuses on the underlying concepts and mechanics that bndlib offers for automating build tasks.

+

Rather than teaching OSGi itself or prescribing a full build system, this guide demonstrates how bndlib operates under the hood—tool-agnostic and from the command line—using a sample workspace named com.acme.prime. While the bnd command-line interface is used for illustration, this is not the typical way bndlib is consumed in practice. Most real-world builds are orchestrated through tools like Gradle or IDEs like Bndtools.

+

Think of this guide as a conceptual tour that will help you understand how workspaces, properties, plugins, and projects come together in bndlib. The goal is to clarify the structure and extensibility of a bndlib-powered build environment, not to provide production-ready build instructions.

+

Since this section provides a tool independent view of bndlib, we use the bnd command line application to demonstrate the features. Though this is an excellent way to show the low level functionality (the porcelain in git terms), it is not the normal way bndlib is used. In general, a build tool like gradle, ant, make, or maven drives this process from the command line an IDE like bndtools handles the user interaction. So please, please, do not take this com.acme.prime as a guide how to create a build. However handy bnd is, it falls far short of a real build tool like for example gradle.

+

Workspace

+

A workspace is a directory with the following mandatory files/directories:

+
./
+    cnf/
+        build.bnd
+        ext/
+
+ +

That's all! So let's create one:

+
$ bnd add workspace com.acme.prime
+$ cd com.acme.prime
+$ ls
+cnf
+
+ +

The cnf directory is the 'magic' directory that makes a directory a workspace, just like the .git directory does for git.

+

In the cnf directory you find the following files:

+
$ ls cnf
+bnd.bnd         build.bnd       ext
+
+ +

The build.bnd is part of the magic to make something a workspace, it contains your workspace properties. The ext directory contains more properties. The bnd.bnd is the last piece of magic, it makes bndlib recognize the cnf directory as a project.

+

Naming

+

Why such a long name for the workspace? Wouldn't just tour suffice? Well, glad you asked. If you work with bnd(tools) for some time you will find that you will get many different workspaces since a workspace is another level of modularity. You can see a workspace as a cohesive set of bundles; just like any module it can import and export. Just like any other module, it imports and exports the thing it encapsulates. For example, a bundle imports and exports packages. In case of the workspace this is the bundle. A workspace imports and exports bundles through repositories.

+

A good module has cohesion; this means that its constituents have a rather strong relation. Since they also tend to come from the same organization they will have very similar bundle symbolic names. Since some of these bundles will escape in the wild it is always beneficial if you can quickly find the source of that bundle. Therefore naming the workspace with the shared prefix of the bundle symbolic names of its constituents is highly recommended.

+

That said, bndlib does not enforce this guideline in any way, unlike project names. You can name your workspace foo if you want to.

+

Properties

+

A workspace so created is quite empty. However, if we look in the cnf directory then we can see the build.bnd file. This file is 100% for you ... Any property, instruction, or header specified in here is available in anything you build in this workspace; all other bnd files will inherit everything from this properties file. In this file should add for example the headers Bundle-Vendor and Bundle-Copyright. However, using the macro language we can also add custom variables and macros that are useful across the workspace.

+

Plugins

+

An important aspect of the workspace is that it hosts plugins. A plugin is an extension to bndlib that gets loaded when the workspace is opened. Plugins provide a lot of different functions in bndlib. You can see the currently loaded plugins with bnd:

+
$ bnd plugins
+000 Workspace [com.acme.prime]
+001 java.util.concurrent.ThreadPoolExecutor@a4102b8[Running, ...]
+002 java.util.Random@11dc3715
+003 Maven [m2=...]
+004 Settings[/Users/aqute/.bnd/settings.json]
+005 bnd-cache
+006 ResourceRepositoryImpl [... ]
+007 aQute.bnd.osgi.Processor
+
+ +

The plugins you see are the built-in plugins of bnd itself, they always are available. However, the purpose of plugins is to extend the base functionality. As almost everything, the set of external plugins is managed through an instruction, which is a property in the Workspace.

+

Before bndlib reads the build.bnd file to read the workspace properties, it first reads all the files with a .bnd extension in the cnf/ext folder. The purpose of this folder is to manage setups for plugins. We can add additional plugins by their name. You can see a list of built-in plugins with the add plugin command:

+
$ bnd add plugin
+Type                           Description
+ant                            aQute.bnd.plugin.ant.AntPlugin
+blueprint                      aQute.lib.spring.SpringXMLType
+eclipse                        aQute.bnd.plugin.eclipse.EclipsePlugin
+filerepo                       aQute.lib.deployer.FileRepo
+git                            aQute.bnd.plugin.git.GitPlugin
+gradle                         aQute.bnd.plugin.gradle.GradlePlugin
+...
+
+ +

An interesting plugin is the Eclipse plugin that will prepare any projects for Eclipse. We could also add the git plugin that will make sure the proper .gitignore files are in place.

+
$ bnd add plugin eclipse
+$ bnd add plugin git
+$ bnd plugins
+...
+007 aQute.bnd.osgi.Processor
+008 EclipsePlugin
+009 GitPlugin
+
+ +

Since you likely need to maintain this build it is good to know how this is stored. If you look in the cnf/ext directory you should see an eclipse.bnd and a git.bnd file:

+
$ ls cnf/ext
+eclipse.bnd         git.bnd
+
+ +

The eclipse.bnd file contains the following:

+
$ more cnf/ext/eclipse.bnd
+#
+# Plugin eclipse setup
+#
+-plugin.eclipse = aQute.bnd.plugin.eclipse.EclipsePlugin
+
+ +

So how does this work? When the workspace is opened bndlib will first read all the bnd files in the cnf/ext directory in alphabetical order. After that, it will read the build.bnd file. The idea of the cnf/ext files is that they should not be touched by you, the build.bnd file is, however, all yours. You can override any previous setting in the build.bnd file since it is read last.

+

As you can see, the eclipse.bnd file defines the property -plugin.eclipse. In most cases that a value should be settable in different places, bndlib uses merged properties. When bndlib loads the plugins, it actually gets the property -plugin, merged with any other property that has a key that starts with -plugin. (ordered alphabetically). This allows you to add to a merged property anywhere in the many places in bndlib where you can set properties.

+

So now we can try to build the workspace:

+
$ bnd build
+No Projects
+
+ +

Which makes some sense ...

+

Project

+

An empty workspace is not so useful, let's add a project.

+
$ bnd add project com.acme.prime.hello
+$ ls -a com.acme.prime.hello/
+.               .gitignore      bin_test        src
+..              .project        bnd.bnd         test
+.classpath      bin             generated
+
+ +

This classic layout defines separate source folders for the main code and the test code. The generated directory is a temporary directory, it contains the artifacts produced by this build.

+

Setup

+

Changing the Layout

+

This is a classical Eclipse layout, with a separate src and test folder. However, this is not baked into bndlib, it is possible to, for example, use the maven layout with the src/main/java, src/test/java, and target directories. We can try this out with the maven plugin.

+
$ bnd add plugin maven
+$ more cnf/ext/maven.bnd
+-plugin.maven = aQute.bnd.plugin.maven.MavenPlugin
+
+-outputmask = ${@bsn}-${versionmask;===S;${@version}}.jar
+
+src=src/main/java
+bin=target/classes
+testsrc=src/test/java
+testbin=target/test-classes
+target-dir=target
+
+ +

The maven plugin adds a number of properties that are recognized by bndlib and used appropriately.

+ + diff --git a/org.bndtools.help/docs/chapters/125-tour-features.html b/org.bndtools.help/docs/chapters/125-tour-features.html new file mode 100644 index 0000000000..c97c44bef2 --- /dev/null +++ b/org.bndtools.help/docs/chapters/125-tour-features.html @@ -0,0 +1,408 @@ + + + + +bnd / bndlib Features and JAR Wrapping Techniques + + + +

bnd / bndlib Features and JAR Wrapping Techniques

+

This guide is about the first part of bnd mentioned in the introduction:

+
+

Its primary function is generating OSGi meta data by analyzing Java classes.

+
+

While most developers interact with OSGi through user-friendly tools like bndtools or Gradle plugins, the real power of bnd lies in its underlying library: bndlib. This library is the engine that automates the generation of OSGi metadata, wraps third-party JARs, and provides powerful build-time analysis and transformation of bundles.

+

This guide is intended for build engineers and advanced users who need precise control over bundle construction—especially when dealing with legacy or non-OSGi JARs. If you’re new to OSGi or just getting started, we recommend beginning with a higher-level tutorial or IDE-based tooling. bndlib relates to OSGi like the ASM byte code manipulation library relates to Java. Sometimes incredibly useful but in general something you do not want to touch, and obviously not the way to learn Java.

+

Here, we’ll explore core bndlib features using the command-line bnd tool to manipulate and inspect JARs, understand manifests, control import/export behavior, manage versions, and use macros to keep your builds clean and DRY. While bnd can be a sharp instrument, it becomes invaluable when conventional tools fall short.

+

Warning: Low-Level API Ahead

+

First a word of warning: the fact that bndlib provides a function is in no way an advertisement to use that function. bndlib grew up together with the OSGi specifications and has been used to build the Reference Implementations (RI) and Test Compatibility Kits (TCK). Though this has a lot of benefits for you, the disadvantage is that it also has to support all the bad parts of the specifications, and even sometimes must be able to create erroneous situations so we could create test cases. And we also had to handle the situations caused by the mess of non-modular bundles out there.

+

So to make it crystal clear: the fact that a function is in bndlib does not mean it is intended to be used. This section contains a whole bunch of things you wish you never had to touch, and if you do OSGi properly, you will only see a tiny fraction of bndlib. That said, when the unprepared JARs hit the OSGi framework, it is nice to have bndlib as backup.

+

This tour uses the bnd command line bnd to demonstrate much of the inner details of bndlib.

+

bnd became the Swiss army knife to manipulate JARs and gained a lot of function you should never attempt to use. However, this chapter will give you an overview of what is in bnd.

+

bnd has lots of commands to try out aspects of bndlib. The install section shows how to install bnd.

+

Wrapping

+

A common use of bnd is to wrap a JAR file; there are still too many files out there that have no OSGi metadata.This lack of metadata makes them kind of useless as a bundle since it will be fully isolated from the other bundles. In OSGi, you must explicitly indicate what packages should be imported and what packages should be exported, by default everything is private. Though this can be quite frustrating sometimes, a rather strong argument can be made for the long term benefits of this strategy.

+

The OSGi metadata is stored in the manifest of the JAR file. The manifest is a like a properties file stored in META-INF/MANIFEST.MF in the JAR file. The manifest format is specified by Sun/Oracle. Though the manifest is a text file and human readable it has a number of quirks that makes it hard to edit for humans. So even though it is text, the intention of the manifest was never to be done by hand, bnd like tools were always the intention. Tools can provide many useful defaults, handle expansions, and verify consistency,

+

So let's use bnd to wrap the javax.activation.jar file. Let's download it:

+
$ mkdir jar
+$ bnd copy https://repo.maven.apache.org/maven2/javax/activation/activation/1.1.1/activation-1.1.1.jar \
+    jar/javax.activation-1.1.1.jar
+
+ +

bnd provides a convenience function to print out the contents of a JAR. The --uses option shows the packages and what other packages they use.

+
$ bnd print --uses jar/javax.activation-1.1.1.jar 
+[USES]
+com.sun.activation.registries            []
+com.sun.activation.viewers               [javax.activation]
+javax.activation                         [com.sun.activation.registries]
+
+ +

Simplistic

+

In the simplistic case our goal is to provide a manifest that makes all the packages in the source JAR available to the other bundles (exports) and that imports anything the classes in the JAR require from the external world (imports). bnd is controlled by a bnd file. This file is a standard Java properties file. In this properties file we can provide headers, instructions, and macros to bnd. In general, a header starts with an upper case, and an instruction with a minus sign ('-'). The format of the headers and instructions is defined by the OSGi specifications. The headers specifically try to follow the structure of an OSGi header. Since exports are defined with the Export-Package header and imports are defined by the Import-Package header we can create a bnd file that looks very much like the desired manifest, except for the instruction that defines our class path. We could also use the URL directly on the classpath but this would download the JAR everytime we ran bnd. So javax.activation.bnd should look like:

+
-classpath:     jar/javax.activation-1.1.1.jar
+Export-Package: *
+
+ +

Properties Format

+

The casing of the headers is important, even though OSGi headers are case insensitive. That is Export-Package is not the same for bnd as Export-package.

+

The properties format we use in bnd is darned flexibile. A header is recognized when you start the line with a header name (a word without spaces) and then:

+ +

Though lines can be as long as you want, it is better for your brains to keep them short. You can break a line with a backslash ('\') followed by a newline ('\n'). Be careful, the newline must follow the backslash or you will get whatever comes after the backslash in the header. Some examples that all set the variable foo to 3:

+
foo             =   3
+foo:3
+foo 3
+foo \
+3
+
+ +

Since bnd files are property files, you cannot repeat a property. Later properties will completely overwrite earlier ones and there is no order between properties.

+

Notes on backslashes in .bnd files: Be aware that Java properties parsing silently drops single backslashes (or more precisely odd numbers of consecutive backslashes). In the past, this was a common source of confusion, but since bnd 7.2.0, a warning is issued when such cases are detected.

+

For example consider this .bnd file:

+
a: 42
+a0: ${a}
+a1: \${a}
+a2: \\${a}
+
+ +

This produces the following output:

+
a: 42
+a0: 42
+a1: 42
+a2: ${a}
+
+ +

Notice that a0 and a1 resolve to the same value because the single backslash in a1 is silently dropped by Java’s property parser.

+

Running bnd

+

We can now wrap the source JAR with the following command:

+
$ bnd javax.activation.bnd
+
+ +

bnd has many commands, you can find out more about them with thebnd help [sub] command. In this case we rely on bnd detecting a bnd file and doing the right thing. bnd is also prepared to show the manifest of any bundle, so let's take a look at the bundle we just generated:

+
$ bnd javax.activation.jar
+[MANIFEST javax.activation]
+Bnd-LastModified                         1407229057278                           
+Bundle-ManifestVersion                   2                                       
+Bundle-Name                              javax.activation                   
+Bundle-SymbolicName                      javax.activation                   
+Bundle-Version                           0                                       
+Created-By                               1.8.0 (Oracle Corporation)              
+Export-Package                           com.sun.activation.registries;version="0.0.0",
+                                         com.sun.activation.viewers;uses:="javax.activation";version="0.0.0",
+                                         javax.activation;version="0.0.0"
+Manifest-Version                         1.0                                     
+Require-Capability                       osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.4))"
+Tool                                     Bnd-2.4.0.201408050759
+
+ +

Output

+

When we create the JAR, we can also specify the output file. By default, bnd will store JAR under the same name as the bnd file, but then with a .jar extension. You can override the default from the command line:

+
$ mkdir bundle
+$ bnd do --output bundle javax.activation.bnd
+$ ls bundle
+javax.activation.jar
+
+ +

You can either specify a directory or a file name. However, you can also specify the output in the bnd file itself:

+
-output:        bundle
+
+ +

The Manifest

+

It is clear that bnd has been busy. It detected 3 packages (com.sun.activation.registries, com.sun.activation.viewers, and javax.activation) and since we exported all, they appear in the manifest as exports. Observant readers will have noticed that we used wildcards ('*'). The OSGi specifications are not so generous, every package must be explicitly listed so that the manifest contains all the information required to process a bundle. This, again, has many long term macro advantages. It's however bnd's goal in life to provide the convenience in this model and that is the reason that bnd supports wildcards in virtual any situation where they are usable. A wildcard requires a domain to be effective, you can only select something out of a set, its domain. In the case of Export-Package, its domain is the class path. This class path is set by the -classpath instruction. In this case the activation jar.

+

Export Package

+

Currently our package is exported at version 0.0.0. This is not a very useful version, we therefore need to version the exported packages. Why? Well, this is the contract of modularity. To get the benefits of privacy (the privilege to change whenever we feel the need) comes the cost of compatibility for the parts we share. If you export a package, you intend it to be used by others. These others are an uncontrollable bunch that will use your revision (the actual artifact with a given digest, i.e. the instance of the program) but will expect updates in the future with new functionality and bug fixes.

+

Since a software program is an ephemeral product that changes over time these others do not become dependent on the revision, nope, they become dependent on the program. This creates two problems.

+ +

The answer to these two questions is given to us by semantic versioning, a prescriptive syntax for versions. Though semantic versions work for bundles, they really shine for packages. The basic idea is that when you compile against a version, this version is recorded in the OSGi metadata as an range on the imported package. The floor of this range is the version in the revision use to compile against, the ceiling indicates the first version that would not be compatible anymore. For example, [1.2,2) indicates that any version that is larger or equal than 1.2 and less than 2 is compatible. Therefore, 1.5 would be compatible. Since OSGi supports version ranges on the Import-Package header it will be able to control what revisions get linked and how.

+

Such a version scheme of course only works if you agree how to use the version syntax, this should explain the 'semantic' in semantic versioning. Therefore, the bnd/OSGi versions have a strictly defined syntax:

+ +

Long story, but it is at the heart of what we're trying to achieve: evolving large systems in a anti-fragile way.

+

Back to the exported packages. We can add the version to the export-package by decorating the Export-Package header:

+
-classpath:     jar/javax.activation-1.1.1.jar
+Export-Package: *;version=1.1.1
+
+ +

Let's take another look:

+
$ bnd javax.activation.bnd
+$ bnd javax.activation.jar
+[MANIFEST javax.activation]
+...
+Export-Package                           com.sun.activation.registries;version="1.1.1",
+                                         com.sun.activation.viewers;uses:="javax.activation";version="1.1.1",
+                                         javax.activation;version="1.1.1"
+...
+
+ +

Looking at the manifest we can see the uses directive; this directive is the primary reason you should use bnd. To prevent wiring the wrong bundles together, the OSGi Framework must know which packages use what other packages in their API, this list is reflected in the uses constraints. It allows the OSGi Framework to handle multiple versions of the same package in one VM and not create Class Cast Exceptions ... Very powerful but it is impossible to maintain this list by hand and it would be prohibitively expensive in runtime.

+

Private Package

+

An exported package is a commitment to any future users out there. This commitment will restrict your freedom to make changes since users can get pretty nasty if you make something that will not work with their existing software. In contrast, a package that is not exported is private; since no external user can have knowledge about this package we have complete freedom to do whatever we want in a future revision without getting hollering users on the phone.

+

In our example javax.activation JAR we should therefore not export the com.sun.* packages since they are actually private. The Private-Package header has the same syntax as the Export-Package header but will not export the packages, it will keep them hidden in the bundle. Unlike the Export-Package header, it is not necessary to decorate the packages with a version since nobody can depend on them.

+
-classpath:     jar/javax.activation-1.1.1.jar
+Export-Package: javax.activation;version=1.1.1
+Private-Package: com.sun.activation.*
+
+$ bnd javax.activation.bnd
+$ bnd javax.activation.jar
+[MANIFEST javax.activation]
+...
+Export-Package          javax.activation;version="1.1.1"
+Private-Package         com.sun.activation.registries,
+                        com.sun.activation.viewers
+...
+
+ +

The Private-Package has no meaning to OSGi, if you want to not have this header in your manifest then you can also use -private-package instead.

+

Bundle Version

+

The Bundle-Version header obviously provides the version. Default it will use version 0, so we should override it. We could just add the 1.1.1 version from our source JAR, however, this would make it impossible to to distinguish the different variations we might make over time. A good tool is to use the ${tstamp} macro for the qualifier. The qualifier is the last part of the version. A macro provides a textual replacement, bnd has hundreds of macros (including access to Javascript) and you can define your own. The ${tstamp} macro provides a time stamp.

+
-classpath:     jar/javax.activation-1.1.1.jar
+Export-Package: javax.activation;version=1.1.1
+Private-Package: com.sun.activation.*
+Bundle-Version: 1.1.1.${tstamp}
+
+ +

DNRY or the Benefit of Macros

+

The 'Do Not Repeat Yourself' mantra encodes one of the more important lessons of software engineering. You should always strive to define a 'thing' or a piece of knowledge in only one place. In our little example, we actually repeat ourselves with the version 1.1.1:

+ +

bnd has a macro processor on board that is a life saver if you are addicted to DNRY (we are). This macro processor has access to all properties in the bnd file, including headers and instructions. Therefore ${Bundle-Version} refers to whatever value the Bundle Version is set to. However, in this case the Bundle Version also contains the time stamp in the qualifier, which we do not need in the other places. That is, we do not want the output file name to contain the qualifier.

+

bnd also contains a large number of built-in macros that provide common utilities. The ${versionmask;mask;version} is for example such a utility for picking out the parts of a version, bumping it, as well as normalizing it. Normalizing (making sure all parts are present, leading zeros removed, etc.) is crucial to keep things workable.

+

We can try out the macro from the command line, the bnd command has a macro sub command:

+
$ bnd macro "version;===;1.2.3.q" => 1.2.3
+$ bnd macro "version;+00;1.2.3.q" => 2.0.0
+$ bnd macro "version;+00;0"       => 1.0.0
+$ bnd macro "version;=;1.2.3.q"   => 1
+
+ +

To reuse the Bundle Version in the class path, the output, and the export package:

+
-classpath:     jar/javax.activation-${versionmask;===;${Bundle-Version}}.jar
+
+Export-Package: javax.activation;version=${versionmask;===;${Bundle-Version}}
+Private-Package: com.sun.activation.*
+Bundle-Version: 1.1.1.${tstamp}
+
+ +

This of course looks awkward and hardly DNRY. A better solution is to create an intermediate variable. Variables are always lower case (if they started with an upper case, they would end up in the manifest). Variables can be referred to with the macro syntax of ${}.

+
v:               1.1.1
+
+-classpath:      jar/javax.activation-${v}.jar
+-output:         bundle
+
+Bundle-Version:  ${v}.${tstamp}
+Export-Package:  javax.activation;version=${v}
+Private-Package: com.sun.activation.*
+
+ +

Description

+

Maven Central is quickly moving towards a million revisions organized in 200.000 programs. It should be clear that we need to organize this huge pile of software. One way is to make sure you document your programs appropriately. It is highly recommended to have a short one paragraph description in each bundle. Adding a description to our bundle is easy:

+
v:               1.1.1
+
+-classpath:      jar/javax.activation-${v}.jar
+-output:         bundle
+
+Bundle-Description: \
+    A wrapped version of javax.activation ${v} JAR from Oracle. \
+    This bundle is downloaded from maven and wrapped by bnd.
+Bundle-Version:  ${v}.${tstamp}
+Export-Package:  javax.activation;version=${v}
+Private-Package: com.sun.activation.*
+
+ +

For longer descriptions you can continue on the next line with a backslash ('\') followed by a newline. Unlike the manifest, it does not has to start with a space though indenting the text for the next lines is usually a good practice. You cannot use newlines or other markup in the Bundle-Description.

+

That said, a good Bundle-Description is a single paragraph with a few short sentences.

+

Include Resources

+

The Bundle-Description is an excellent way to provide a short description, but what about a longer description with examples of usage, caveats, configuration requirements, etc? It would be nice to include a readme file in the bundle that indexing sites could use. You can achieve this effect by including a readme.md file in the root of your bundle.

+

In bnd it is possible to include any resource from anywhere in the file system (actually, any URL as well).

+
-includeresource: readme.md
+
+ +

The resource is of course not always in the proper place, it is therefore possible to make the output name different from the file path:

+
-includeresource: readme.md=doc/readme.md
+
+ +

In this case, the readme could benefit from the bnd macro support. For example, it could then contain the actual version of the artifact or use any of the other macros available. Preprocessing can be indicated by enclosing the clause with curly braces ('{' and '}').

+
-includeresource: {readme.md=doc/readme.md}
+
+ +

Another option is to encode the text for the readme in the bnd file using the literal option (though this is not such a good idea for any decent readme file since it is hard to use newlines):

+
-includeresource: readme.md;literal=${unescape;#JAF\nThis is the Java Activation Framework}
+
+ +

The -includeresource instruction is quite powerful, there are many more options to recurse directories, filter, etc. See -includeresource.

+

Import Package

+

So far, we've ignored the imported packages because the javax.activation JAR only depends on java.; java. packages are not imported, the OSGi Framework will always provide access to them. Let's add another JAR, the javax.mail jar that uses javax.activation. This JAR is already a bundle, which is really good. Except for this exercise, so we copy and strip the OSGi metadata

+
$ bnd copy --strip https://repo.maven.apache.org/maven2/com/sun/mail/javax.mail/1.5.2/javax.mail-1.5.2.jar \
+   > jar/javax.mail-1.5.2.jar
+$ bnd print --uses jar/javax.mail-1.5.2.jar 
+[USES]
+com.sun.mail.auth          [javax.crypto, ... ]
+com.sun.mail.handlers      [javax.activation, ... ]
+com.sun.mail.iap           [com.sun.mail.util, ... ]
+com.sun.mail.imap          [com.sun.mail.imap.protocol, ...]
+com.sun.mail.imap.protocol [com.sun.mail.iap, ... ]
+com.sun.mail.pop3          [javax.mail, ... ]
+com.sun.mail.smtp          [com.sun.mail.util, ... ]
+com.sun.mail.util          [javax.mail,  ... ]
+com.sun.mail.util.logging  [javax.mail, ...]
+javax.mail                 [javax.mail.event, ... ]
+javax.mail.event           [javax.mail]
+javax.mail.internet        [javax.mail, ... ]
+javax.mail.search          [javax.mail.internet, javax.mail]
+javax.mail.util            [javax.mail.internet, javax.activation]
+
+ +

The javax.mail bundle leverages the Java Activation Framework (JAF) embedded in our previous javax.activation bundle. One of the most useful features in bnd is that it can analyze the class files to find the package dependencies and turn them into an Import-Package header. If bnd finds the exported packages with a version on the class path then it will automatically use the exported versions to calculate the import version range. That is, if the package is exported as 1.1.1, then bnd will import it in general as [1.1,2).

+

So lets wrap the javax.mail package, add to javax.mail.bnd:

+
v:          1.5.2
+
+-classpath: \
+    jar/javax.activation-1.1.1.jar, \
+    jar/javax.mail-${v}.jar
+
+Bundle-Version: ${v}
+Bundle-Description: \
+  An OSGi wrapped version of the javax.mail library downloaded from maven.
+Export-Package: javax.mail.*
+Private-Package: com.sun.mail.*
+
+ +

bnd contains a special -i/--impexp option to print the imports and exports of a bundle. So lets make the bundle and see:

+
$ bnd javax.mail.bnd
+$ bnd print -i javax.mail.jar
+[IMPEXP]
+Import-Package
+  javax.activation                       
+  javax.crypto                           
+  javax.crypto.spec                      
+  javax.mail.event                       {version=[1.5,2)}
+  javax.mail.search                      {version=[1.5,2)}
+  javax.mail.util                        {version=[1.5,2)}
+  javax.net                              
+  javax.net.ssl                          
+  javax.security.auth.callback           
+  javax.security.auth.x500               
+  javax.security.sasl                    
+  javax.xml.transform                    
+  javax.xml.transform.stream             
+Export-Package
+  javax.mail                             {version=1.5}
+  javax.mail.event                       {version=1.5, imported-as=[1.5,2)}
+  javax.mail.internet                    {version=1.5}
+  javax.mail.search                      {version=1.5, imported-as=[1.5,2)}
+  javax.mail.util                        {version=1.5, imported-as=[1.5,2)}
+
+ +

First, we notice that there are quite a few imports that have no import range. This is not good but unfortunately Java's VM package versions are more or less absent and are clearly not semantically versioned. A correctly setup system ensures that the correct execution environment is used.

+

However, we also have in this list javax.activation, for this package we do have an export, the problem is that we included the original JAR on the class path and not the bundle we generated.

+
v:          1.5.2
+
+-classpath: \
+    bundle/javax.activation.jar, \
+    jar/javax.mail-${v}.jar
+
+Bundle-Version: ${v}
+Bundle-Description: \
+  An OSGi wrapped version of the javax.mail library downloaded from maven.
+Export-Package: javax.mail.*
+Private-Package: com.sun.mail.*
+
+ +

And now build + print:

+
$ bnd javax.mail.bnd; bnd print -i javax.mail.jar
+[IMPEXP]
+Import-Package
+  javax.activation                       {version=[1.1,2)}
+  javax.crypto                           
+  ...
+
+ +

Yes! Now the javax.activation package is imported with a range of [1.1,2). You now may wonder why not [1.1.1,2)? Well, the reason is that changes in the micro part of the version should not make a difference in API. If you include the micro part in the import range then it turns out that the overall system becomes very volatile, small changes become large quickly. Ignoring the micro part in the import range is like a bit of oil in the engine ... However, if you feel uncomfortable with this lubricant then it is possible to override this.

+

Imports

+

We got the Import-Package header in the manifest but we never specified it. The reason is that bnd has a default Import-Package set to '*'. There is a very good reason for this, it works almost exactly as it should work. Any time you feel the desire to muck around with the imports you should realize that you're not doing the right thing. That said, it is the unfortunate truth that sometimes doing the least worst thing is the best option ...

+

Assume we want to provide a version range on some of the imported packages because these packages could also be provided by bundles, they do not have to come from the JVM. For this, we can add the following header that will decorate the javax.net.ssl package:

+
Import-Package: javax.net.*;version=1.1, *
+
+ +

You can decorate any package, including packages specified with a wildcard. The domain of the Import-Package is all packaged that are referred to by any class inside the bundle. If there are for example imports

+

Remove Headers

+

The removeheaders header uses a selector expression. A selector expression consists of a number of comma separated clauses. A clause contains a name (which can be wildcarded) and some optional instructions. A selector is always applied to a domain, in the case of -removeheaders the domain is all the headers in the manifest. The clauses in the selector are applied one by one in their declaration order to the domain. If a clause matches a member of the domain then the member is removed from the set, and the next member is again matched against the first clause. A suffix of ':i' indicates a case insensitive match.

+

This ordering is important because selector clauses can use negation. When a clause starts with an exclamation mark ('!') then a matching member is further ignored. Therefore, the following selector will never match the Bundle-Name, the first clause already threw any header that starts with Bundle- out:

+
-removeheaders: !Bundle-*, Bundle-Name:i
+
+ +

The Require-Capability header ensures that the runtime has at least a Java 1.4 VM by requiring an OSGi execution environment. bnd calculates this requirement based on the compiler version used to compile the classes in the JAR. We can override this requirement or disable it with the -noee=true instruction.

+

Includes

+

We now have 2 files: javax.activation.bnd and javax.mail.bnd. If we would like to add some more descriptive headers like Bundle-Vendor, Bundle-DocURL, and Bundle-Copyright then we would have to add them to both files, another case of DNRY. Since this is quite common, we can use includes.

+
-include: common.bnd
+
+ +

In common.bnd we can then place:

+
Bundle-Vendor: Oracle (wrapped by bnd)
+Bundle-Copyright: (c) Oracle, All Rights Reserved
+
+ +

These headers are then automatically placed in the manifests of our target bundles.

+

A common mistake with the -include instruction is that it is repeated several times. Since bnd files are property files, only one of them survives. However, the -include instruction accepts multiple files/URLs to both property files or manifest files. You can also indicate that it is ok to not have a certain file by prefixing it with a minus sign ('-').

+
-include common.bnd, -other.bnd
+
+ +

Always use Unix like paths, using the forward slash ('/') as file separator, also on Windows. It is highly recommended to always use relative paths since any absolute references makes your builds unportable.

+

Sub bnd Files

+

In our progression towards wrapping javax.activation and javax.mail we have created an unmanaged ordering; we can only build javax.mail once the javax.activation is created. For this reason, bnd can also create a control file that steers sub bnd files. The control file can also contain common properties, though these can be overridden by the sub files. Place the following content in javax.bnd:

+
Bundle-Vendor:       Oracle (wrapped by bnd)
+Bundle-Copyright:    (c) Oracle, All Rights Reserved
+-output:             bundle
+-sub: \
+    javax.activation.bnd, \
+    javax.mail.bnd
+
+ +

We can now build the jars with a simple command:

+
$ rm bundle/*
+$ bnd javax.bnd
+$ ls bundle
+javax.activation.jar    javax.mail.jar
+
+ +

Merging

+

The basic model of bnd is to collect packages from the classpath and assemble them in a bundle. This pull model is quite different from the more common push model in builds where it is harder to include packages from other projects. However, bnd's model makes it quite easy to create a bundle out of multiple JARs. So lets add a new bnd file that merges javax activation and mail.

+

Actually, javax.activation and javax.mail are really bad citizens in an OSGi world. They use class loading hacks all over the place that make a mockery out of modularity. Part of the problem is that they really require certain private directories to be available from the client's class loader. In those cases it is sometimes necessary to make sure the layout of the bundles is exactly the same as the source bundles.

+

The best way to achieve this is to unroll the source bundles in the target bundle. You can unroll a JAR by prefixing it with a commercial at sign ('@') in an include resource operation. Lets get started on a javax.mail.all.bnd file:

+
-includeresource:   \
+    @jar/javax.activation.jar, \
+    @jar/javax.mail.jar
+
+ +

This instruction combines the two JARs into one.

+

Alternative Wrap

+

Errors & Warnings

+

Failing

+

Settings

+

System Commands

+

Tips

+

There are some common pitfalls that can be prevented by following the tips:

+ + + diff --git a/org.bndtools.help/docs/chapters/130-concepts.html b/org.bndtools.help/docs/chapters/130-concepts.html new file mode 100644 index 0000000000..1ec6007e63 --- /dev/null +++ b/org.bndtools.help/docs/chapters/130-concepts.html @@ -0,0 +1,48 @@ + + + + +Concepts + + + +

Concepts

+

One of the more surprising things we've learned about modularity in the last decade is how much of a fractal pattern it actually is. All the way from CPU machine instructions all the way up to a large distributed system you can see the pattern of encapsulation to keep as much details as possible confined to the internals of the module. Strangely enough, as an industry we seem to have a hard time learning the lessons from the lower layers where we over time learned the rules to the layers above.

+

Java was developed the early 90's as a state of the art language based on Object Oriented concepts. It did apply the rules of modularity on the method and class level and pioneered with providing a higher level module with their concept of packages. However, our software industry did their utmost to ignore this concept, helped by the fact that it did have some real shortcomings.

+

The key shortcoming was that it was hard to keep classes private since they required public visibility when they crossed the package boundary. This collided with the granularity of the package, in general you needed to break an application in many different packages to stay sane as a developer; with the consequence that a lot of private code was forced to become public.

+

Java did provide a higher level module: the JAR. However, this was a concept outside the language, it was only visible in runtime to be used by the class loaders. Interestingly, it was then used in runtime security but it was kept outside the language that still desperately tried to front a single name space. Problems showed up as class cast exceptions, package private access violations in the same package, and getting the wrong class. It is amazing how brittle the class path model of Java really is.

+

In search for a model that would allow the management of hundreds of thousands of devices running Java the OSGi decided to leverage the JAR but turn it in to a proper module by adding encapsulation. Since in modularity a module tends to export/import entities that have a lower granularity (classes export/import methods, packages import/export classes), the OSGi solution was to export/import packages.

+

Package imports/exports was a much maligned choice because the maligners did not understand that some of the lessons learned from object oriented programming, where the class is the module, also applied to the other kinds of modules. The greatest problem with Object Oriented was that direct object references created highly coupled systems that were very brittle. Direct references aggregate many constraints that are only important for a specific implementation. This problem was not fully solved until we got Java interfaces. Java interfaces allow a user of that interface and an implementer of that interface to only couple on the relevant details necessary for the collaboration; any implementation details on either side of the interface are not constraining the other side in any way.

+

What the maligners do not see is that we face the exact same problem when we turn JAR into modules. The maven model only supports direct references between modules and they aggregate implementation constraints in the same way as object references did. The solution the OSGi came up with is to treat a package as a specification, just like a Java interface specifies the behavior of an implementation class.

+

In this way a bundle (the OSGi JAR module) could provide an implementation for a (specification) package and other bundles could consume this implementation. Again, this is similar to the Java interface for classes.

+

In the Java world we learned rather slowly that interfaces are great but that you have this pesky problem of how to get an instance for that interface if you should not be coupled to a specific implementation? Java created a a number of quite horrendous factory models for almost each subsystem, a factory model that too often bled into the actual collaborative API. For example, the javax.persistence package does not only contain the classes to work with JPA, it also contains a surprisingly large API to manage the life cycle of the provider. Factories also heavily abused class loaders for a purpose they were clearly not designed for. In Java 6 Sun tried to stop the hemorrhaging with the Service loader but forgot that class loaders are not designed for this purpose and baked them right into the API.

+

Spring brought dependency injection to the masses that allowed the consumers and providers to stay away from each other but it then introduced a massive coupling in the XML that contained too many details about the provider implementations since it specified the provider class names.

+

The solution OSGi came up with in 1998 was to use a service broker. A broker makes sure that consumers and providers were bound together once they are available. This is the only true modular model that allows all implementation details to remain private inside the module.

+

+

A the consequence of this model is that services, an implementation object implementing a Java interface from a specification package, cannot be assumed to be always there. Where Spring calculates the dependencies of its beans to initialize a system in the right order, a broker negotiates when a service is available since it does know any of its implementation details. One of those implementation details is when that service will be available. The broker is therefore dynamic, it can react to changing circumstances, another even more both maligned and misunderstood OSGi feature.

+

The hardest part of OSGi is to look at it with a clean slate. The core model is surprisingly simple, elegant, and extremely powerful. The hard part is that it tends to conflict (as it should!) with all the bad habits in existing code bases that grew up thinking class loaders were simple extension mechanisms.

+

Bundles

+

So to summarize, a bundle is a JAR that imports and exports a set of packages. These imports and exports are bound to other bundles when they are resolved, allowing multiple versions of the same package. Once a bundle is started, it can then communicate with the external world at its own discretion; it can also get and register services to collaborate with other bundles. The following picture depicts the model of an OSGi application:

+

+

The symbols used are defined in the OSGi specifications. The rectangle with rounded corners is a bundle, the triangle is a service (it always points in the dependency direction, i.e. the Reporter bundle depends on the sensor service to be there. Input and output is depicted with the corresponding flow chart symbol.

+

In a perfect OSGi world, packages are just a minor detail. Until then, we also need some way to show package imports and package exports. In the OSGi specification, we use an open rectangle for imported packages and and black rectangle for exported packages. Private packages are depicted with a grey rectangle, see:

+

+

Components

+

There is often a confusion of terminology, like, is a bundle a component? We are guilty of not always using the terminology consistent. However, in the past few years it has become very clear that the OSGi declarative services provide a programming model that should have been incorporated in the OSGi framework from the beginning. DS allows you to make any object active with a simple annotation. This object can automatically be registered as a service. If there are dependencies on other services then you can easily specify those dependencies with an annotation on a set method.

+

In DS, the implementation class is called the component and in this document we follow this lead. Therefore, in general a bundle consists of a number of components.

+

The Workspace

+

The bndlib workspace is an encapsulation of a set of cohesive projects, where a project exports zero or more bundles via repositories. A repository provides access to set of bundles exported by some means, likely from other workspaces. A repository can be on the local file system or a remote system like Maven central.

+

Projects can depend on other projects in the workspace or import bundles from the repositories. This is depicted in the following figure.

+

+

A workspace is a single directory, just like a git workspace it encompasses all its sub directories. Though the name of the workspace directory is free to choose, it is highly recommended to use a naming strategy. In practice you will create many different workspaces and having a naming strategy will significantly simplify the handling of these workspaces.

+

On the same root level in the workspace as the cnf directory, bndlib expects the projects. Yes, projects must reside in the root level. The reason is again, simplicity. We will later discuss how the bundle's symbolic name is derived from the project's directory name. Since projects can depend on each other, bndlib maintains a workspace repository of projects that it derives from the top level directories. Some people desperately want to use hierarchies of projects (often because that is how they used to work before). However, even people patching bndlib to make it hierarchical admit that the simple linear model is actually working quite well. The reason it works so well is that a workspace is not supposed to hold every single bundle that your organization produces. It is intended to be a cohesive set of between 10-20 up to a couple of hundred projects.

+

Configuration

+

Bnd uses Java properties files (often with extension .bnd) for configuration purposes. Those usually contain headers or instructions. The files are read with java.util.Properties.load(Reader) with UTF-8 encoding and therefore support either of the following key value separators

+
    +
  1. = (default separator)
  2. +
  3. : (separator also used in MANIFEST.MF files)
  4. +
  5. <white space character>
  6. +
+

In general any <white space> characters directly preceding or succeeding the separator are stripped.

+ + diff --git a/org.bndtools.help/docs/chapters/135-history.html b/org.bndtools.help/docs/chapters/135-history.html new file mode 100644 index 0000000000..16b23a5386 --- /dev/null +++ b/org.bndtools.help/docs/chapters/135-history.html @@ -0,0 +1,42 @@ + + + + +Background + + + +

Background

+

OSGi is arguably one of the best specifications in the Java world. It is a no compromise specification for a component framework that is based on what we today know are the best practices. It extends the type safety first model of Java to hold true over time when the modules morph into sometimes unrecognizable shapes. It provides a solid foundation to build applications that can run anywhere, the original promise of Java; offering these impressive features while remaining as simple as possible, albeit no simpler.

+

For some, the previous paragraph may come as a surprise because OSGi has had its share of people complaining about it. Surprisingly, the biggest complaint is often the Class Not Found Exception, which is always a perfect sign that people try to push a round peg in a too small square hole, and with all their might. You only see those exceptions when you're not doing engineering but when you are hacking. If you run head on into the walls that OSGi installs and it is giving you a headache, then just look around and find the elegant and easy to use doors: services.

+

Though this is all true, I do not claim that OSGi is trivial to use; triviality has a way to clash with large system that must evolve over many years. The software profession is a brutal industry that lures us with the siren song of a 'few hours work' to devour us while trying to make gigantic hairballs. As Fred Brooks already said so many years ago in his seminal book 'The Mythical Man Month', there is no silver bullet. Even OSGi will require hard work to build evolvable systems. And though we cannot make building complex systems easy, bnd can at least make it easier (and considerably more fun).

+

A Bit of History

+

When we started building the OSGi specifications around 1998 it became clear we needed metadata to describe the bundles. We chose the manifest since this was already a well defined resource in the JAR, why invent the wheel? Actually, it was Anselm Baird, a Sun employee at the time, who had come up with this idea in his Java Embedded Server (JES). Basically, the manifest was a property file with benefits. We still consider this choice for embedded metadata an excellent idea. Looking at Maven where the metadata is separated over a surprising number of files. It is clear that the reduction in the number of files and potential errors caused by out-of-sync metadata is quite large. My favorite example of this additional complexity is when the SHA1 files necessary in Maven were also signed, an easy mistake but induced by unnecessary complexity. An OSGi bundle is a completely self described artifact.

+

Transient Dependencies

+

So who got bnd started? Well, when we wrote our bundles in the dawn of the new millenium we quickly discovered that transient dependencies, well, eh, sucked. Several of us had great experience in Object Oriented design, and though objects clearly had become mainstream they frustratingly had not provided the level of reusability that some had dreamed of. As Brian Foote shows, we thought we were building shiny castles but in the end built a big ball of mud. Where our predecessors of the structured programming era always hammered on low coupling and high cohesion we had ignored their wise lessons and got ourselves tangled up in a nice mess. Trying to reuse a class too often dragged in more unwanted stuff than the cat does in the whole year.

+

The advantage of Java was that it had found an elegant solution to the scourge of transient dependencies: Java interfaces. An interface elegantly broke transitive dependencies while maintaining type safety at the cost of an indirection. A cost anyone should gladly bear for hairballs are quite distasteful. Surprisingly, while Java offered us this elegant solution to break transitive dependencies, most people in our industry were blindly committing themselves to the same route, just on another level, which actually would make the consequences even worse.

+

What we discovered was that we could use the idea of interfaces in an object oriented environment also for modules. An interface is an instance of contract based programming and we found out that we could use the same between modules. The idea behind the OSGi service is that you do not let modules directly interact but that you use reified conduits between the modules so that you keep the modules, which are implementations, unconnected. What better concept in Java to express this contract between modules is there but the concept of a package?

+

Packages

+

Originally devised as the Java modules, Java packages are heavily underappreciated in the Java world. Even highly expert users sometimes only appreciate the namescoping of the package, brushing over any accessibility issues arising out of the use of multiple classloaders. They are wrong, a package is a perfect module. That said, it is a perfect encapsulation to describe the contract that governs the collaboration between modules. An interface has a too small granularity for such a collaboration contract since it often requires additional interfaces like listeners and also helper classes. Packages, although they are too fine grained for deployment modules, are eminently suitable to define a contract to given the collaboration between deployment modules.

+

So we had come up with the surprisingly well fitting dependency model: 'Look Ma, No Coupling!' But then using it became quite painful because it required a lot of tedious house keeping, tracking which packages you were using, of what version. Just bluntly expressing your dependency on an implementation sometimes felt as attractive as the next shot of heroin for a junkie. Now, housekeeping and chores in general are quite low on the list of reasons to give meaning to live for most software developers, and we were no exception. Not only are we in general horrible at chores, we tend to make an amazing amount of mistakes doing them. Which, in general is not good software engineering. Fortunately, we largely live in a virtual world where it is easy to let the computer do the chores. And this is the raison d'etre of bnd: take the chores out of OSGi and focus on the fun parts. And maybe even more important, 'Do Not Repeat Yourself'.

+

BTool

+

The early version of bnd was called btool and was incepted at Ericsson, where it was used to automate the generation of the manifest in the ebox project. Then, in 2001, btool was used to automate the build process of the specifications, the reference implementations, and the test suites at the OSGi Alliance. One day there was a bit of confusion about the pedigree of the btool, and it was showing its age; it was time for a rewrite and bnd was born.

+

The name came from bundle, then removing the vowels, and cutting it to three characters to reduce the typing on the command line. The pronunciation: we actually have no clue, whatever your preference is. B AND D, bind, whatever. You want to write it as bnd, Bnd, or BND, be our guest. We prefer to write it like bnd since we love the symmetry.

+

Over the years bnd gained a lot of power because we needed a tool at the OSGi Alliance that could not just create good bundles, it also was heavily used in the test cases that required bad bundles. Of course this was an excellent test range for bnd and this synergy is still true today.

+

Eclipse

+

In 2003, Eclipse adopted the OSGi specifications, which led to extensive discussions within both communities. For those focused on OSGi, the importance of package-level dependencies was already well established, while for the Eclipse community—coming from a background of direct, transitive module dependencies—the approach was less familiar. The outcome of these differences can still be seen in the existence of Require-Bundle and Fragment-Host.

+

Beyond this, there were also differing perspectives on how bundles (referred to as “plugins” in Eclipse terminology) should be developed. Eclipse introduced tools such as PDE and later p2, which became central to their ecosystem. In contrast, the bnd experience emphasized that the OSGi manifest should not be maintained manually. Much like editing class files directly, manually editing manifests is error-prone. Although the manifest format is human-readable, it was never intended to be written by hand outside of exceptional circumstances.

+

One design decision in OSGi was to keep the runtime as lightweight as possible, which was particularly important for embedded systems. This meant avoiding constructs that would complicate runtime behavior. For example, while wildcarded package exports could simplify authoring, they would require the framework at runtime to scan all classes to determine available packages—an inefficient and error-prone process. Similarly, the manifest inevitably contains both source and derived information, which can lead to redundancy if managed manually.

+

The PDE approach, however, is based on a “manifest-first” model. In this approach, the manifest is not just a description of the build result but actively drives the build process. For instance, if a bundle is required in the manifest, PDE automatically adds it to the build classpath. Likewise, when a package is imported, PDE locates a bundle that exports that package and places it on the classpath, assuming a unique provider can be found in the target platform.

+

In the meantime since 2024 Eclipse PDE now also offers an approach to automatically generate the Manifest, using bndlib under the hood.

+

Inside the OSGi Alliance

+

Inside the OSGi Alliance we were in a bind (pun intended) because PDE was not suitable for our own build. We used bnd in ant (it was also an ant plugin) but we missed the joy of Eclipse. This caused bnd to develop a split personality. Originally it was a JAR generator based on a small recipe but for our build we needed project & workspace concepts. We toyed with the idea to split it into a bld and a bnd tool but in the end even we committed the sin against modularity of low cohesion and kept these two tools in one out of laziness.

+

Obviously we also developed PDE envy because Eclipse was actually awfully nice except for it. After toying with the idea of using the Eclipse metadata (.classpath) and finding out that this was only possible if we included the complete Eclipse IDE in an offline build, we embarked on developing an Eclipse plugin. Just not a good idea. So we reversed the model, and developed a library that had its own internal, uncoupled, model of a build. You see, the problem is that most build environments are quite pedantic and strongly optimized for their primary goal. Ant, maven, gradle, et. al. are just not easy to use inside an IDE because they are very stream driven: start, process, stop. In this model there is very little incentive to optimize incremental building and event notifications for important changes. An IDE is the reverse, it is start, build, build, build, ..., build, build, stop. For performance, it is crucial to optimize the building out of incremental changes to keep the IDE responsive. It is also crucial to send out events when important things happen. So we decided to pursue the middle ground: a model of projects and workspaces that was as uncoupled of the real world as possible but providing the hooks to use it in all popular build tools, either command line tools or IDEs. This is rather well captured in the expression: "The one tool that bnd's them all".

+

bndtools

+

Then one day we heard that Neil Bartlett also had started a plugin called bndtools. He had used the open source library of bnd and started to work on creating a pleasant to use friendly environment. Interestingly, he had created a continuous builder for bnd so that every save operation automatically build the bundles, something we had considered in our plugin but had been too afraid to do out of performance fear. Neil, however, was developing a lot of stuff that was already in bnd, he only used the JAR packager and manifest generator. After beating him up, which even took a special trip to the UK where we worked for 8 hours in a hotel lounge, he surrendered and thus our long term fruitful collaboration was born.

+

Currently bnd(tools) is managed through a Github organization called bndtools and has its home site at https://bndtools.org. It is split in a number of repositories: bndtools, bnd, bndtools.rt and a number of associated support repositories. Though the collaboration between bndtools and bnd is awfully close, we are fanatic about separating the projects, our goal is still to allow Jetbrains to use bnd in IntelliJ without forcing them to eat any Eclipsisms. And it is always fun when hear someone claiming to successfully integrate bndlib in a product or tool, raving how uncoupled it was.

+

Manual

+

What you are now reading is the manual of bnd, which is the result of a tremendous amount of work, and will be a work in progress for a long time to be. Though much of bnd's development was indirectly supported by the OSGi Alliance it is and always will be an open source project. This gave the authors the license to scratch their itches and not worry too much about documenting the nifty things they developed to scratch. Though the most important aspects were documented, it was sparse and not overly well organized. Though we always hoped someone with a gift for documenting would come along, fall in love with bnd, and write the perfect documentation, this somehow failed. After 16 years, we find it is time to take up this task ourselves, still praying that we will get support from bnd's surprisingly large (to some) group of users, don't hesitate. This is the reason this manual is a github repositories. Contributing is trivial, clone the bndtools/bnd.manual repo, edit the markdown text (you can even do this on the github web), save it, and create a pull request. Don't (always) ask what bnd can do for you, ask what you can do for bnd's users ...

+

Not sure why we wrote such a long introduction, the facebook generation seems have an attention span of 5 lines, so we are probably among ourselves dear reader, congratulations on your stamina!

+ + diff --git a/org.bndtools.help/docs/chapters/140-best-practices.html b/org.bndtools.help/docs/chapters/140-best-practices.html new file mode 100644 index 0000000000..327d1f6c15 --- /dev/null +++ b/org.bndtools.help/docs/chapters/140-best-practices.html @@ -0,0 +1,32 @@ + + + + +Best practices + + + +

Best practices

+

Workspaces

+

The idea of a workspace is that it is cohesive. It contains a set of shared bundles and some of those bundles are exported to a repository. Other bundles are imported from repositories. This is the basic model of modularity.

+

This strongly implies that you should NOT share cnf between workspace, just like you should not share private fields from classes nor private classes from packages. So the idea is that your organizations have a number of workspaces that contain the code that has a strong relation. For example a product, your company service APIs, or shared base libraries. Since all these projects are in one workspace you get a lot of ease of use like refactoring and immediate feedback.

+

That said, there is often a desire to have some of the information, like the repositories in a shared place because you do not want to maintain it multiple times. Since bnd is completely based on inherited properties this is not that hard. The top of the properties are coming from the cnf/build.bnd file. Since this is a bnd file, you can actually include another bnd file there. Since this can be included via a URL, you can refer it to a file on your git repository. For convenience, you could make it refer to master but a better way is to make it refer to an actual commit. The reason is that if you checkout your project 5 years from now, it is unlikely that your build will be ok with the latest version of the included bnd file.

+
build.bnd:
+
+-include: https://examplegit.com/foo/bar/master/shared/shared.bnd
+
+ +

A more defined way to handle this long term versioning problem is to use git modules. They have a bad name but as far as I understand their bad name is because people don’t like that they are not automatically updated, which is exactly what you want when you want to build your project 5 years from now. Git modules require an explicit command to upgrade it to the latest or another version. The parent git repository stores the commit at which it is linked. With git modules you could make a subdirectory in cnf and then include a shared file from there:

+
cnf
+    shared/
+        .git/
+        shared.bnd
+    build.bnd
+
+build.bnd:
+-include shared/shared.bnd
+
+ +

So to summarize, share workspaces, not projects. Use continuous integration that publishes your bundles to a repository that is shared with all. Share one bnd file with a git module.

+ + diff --git a/org.bndtools.help/docs/chapters/150-build.html b/org.bndtools.help/docs/chapters/150-build.html new file mode 100644 index 0000000000..f0cc9a67cd --- /dev/null +++ b/org.bndtools.help/docs/chapters/150-build.html @@ -0,0 +1,197 @@ + + + + +Build + + + +

Build

+

This chapter lays out the rules of the file system for bnd projects. It discusses the workspace layout and the projects layout as well as the properties.

+

Workspace

+

A Workspace is a single directory with all its sub-directories and their files, similar to a git workspace. The core idea of the workspace is that it is easy to move around, that is, it allows the use of relative file names. It also prevents a lot of potential problems that occur when you allow projects to be anywhere on the file system. KISS!

+

Workspaces should be named according to the bundle symbolic names of its projects. Using such a naming strategy will simplify finding the correct namespace given a bundle symbolic name.

+

A bndlib workspace is a valid workspace when it contains a cnf file. If this is a text file, its content is read and interpreted as a path to the cnf directory (which can again be a path to a cnf directory, ad infinitum). The retrieved path is trimmed after which it is resolved relative to its parent directory.

+

However, the advised model is to use a directory with a cnf/build.bnd file. The purpose of the cnf directory is to provide a place for shared information. Though this includes bndlib setup information, it also can be used to define for example shared licensing, copyright, and vendor headers for your organization.

+

The cnf/ext directory

+

The cnf directory can have an ext directory. Files in this directory are added to the properties +of the workspace. They can have the following extensions:

+ +

Automatically registering repositories

+

Files with .pmvn or .pobr will be automatically registered as a Repository and show up in the Repository browser (means, no Plugin configuration needed). This is a convenience shortcut to add a repository with almost no configuration.

+

Example /cnf/ext/central.pmvn file:

+
# name = My Maven Central Repo
+# releaseUrl = https://repo.maven.apache.org/maven2/
+# tags = resolve
+biz.aQute.bnd:biz.aQute.bndlib:7.0.0
+biz.aQute.bnd:aQute.libg:7.0.0
+
+ +

The ext directory is a convenient way to add add reusable components. See template fragments how they can be used to manage workspaces. When files change in this directory the workspace will be reloaded.

+

The cnf/cache directory

+

To cache some intermediate files, bndlib will create a cnf/cache/ directory, this file should not be under source control. E.g. in Git it should be defined in the .gitignore file.

+

Folder structure

+

Overall, this gives us the following layout for a workspace:

+
com.acme.prime/                     workspace
+  cnf/                              configuration/setup
+    ext/                            extensions
+      maven.bnd                     maven setup extension
+    build.bnd                       organization setup
+    plugins/                        directory for plugins
+    cache/                          bnd cache directory, should not be saved in an scm
+  com.acme.prime.speaker/           project directory
+
+ +

The root of the workspace is generally used to hold other files. For example the .git directory for Git, or gradle and ant files for continuous integration. However, designers that add functionality to the workspace should strive to minimize the clutter in the root. For example, the bnd gradle support adds a few files to the root but these link to a cnf/gradle directory for their actual content.

+

Other directories in the workspace represent projects. The name of the project is the bundle symbolic name of the bundle that it produces (or the prefix of the bundle symbolic name when it produces multiple bundles).

+

Workspace Properties

+

Properties are used for headers, macros, and instructions in bndlib, they are quite fundamental. To simplify maintenance, bndlib provides an elaborate mechanism to provide these properties from different places and inherit them. The workspace resides at the top of this inheritance chain (ok, after the built-in defaults).

+

When a workspace is created, it will first read in the properties in the .bnd files in the cnf/ext directory. These are called the extension files since they in general setup plugins and other extensions. The order in which they are read is the lexical sorting order of their file names.

+

Target build directory

+

The target-dir defines where the build process places the build output artifacts. By default this folder is named generated.

+

Avoiding target-dir conflicts between different build tools

+

In the default setup of the workspace, the gradle build tool & eclipse share the same output directories. In general, this means you always have to clean in each tool and in the case of Eclipse stop the incremental builder (otherwise eclipse will start rebuilding the whole workspace when you do a gradle clean build).

+

All the output directories are defined in macros. In general, the ${target-dir} is the main output directory and the ${bin} and ${testbin} are placed inside this directory. So by redefining ${target-dir} in cnf/build.bnd we can redirect all output.

+

bnd has a macro ${driver} that indicates which build tool (a.k.a. the driver) is used. We can then use this as follows, to use a separate output directory for each build tool (e.g. eclipse, gradle, maven):

+

``` +target-dir generated${if;${driver;eclipse};;/${driver}} +bin ${target-dir}/classes +testbin ${target-dir}/test-classes +````

+

This example configuration, placed in cnf/build.bnd means:

+ +

Extension Files

+

Extension files allow you to separate configuration concerns. Its primary purpose is to allow third party extensions. These extensions can then put their properties in one place. The contents of these files should therefore not be touched so that a new version can override them. Each extension file is read as a bnd file, this means that full power of bndlib is available. The bnd command line tool has facilities to add and remove files from this directory.

+

For example, the Maven plugin that is built-in to bndlib has an extension file called maven.bnd which looks as follows:

+
#
+# Plugin maven setup
+#
+-plugin.maven = aQute.bnd.plugin.maven.MavenPlugin
+
+
+#
+# Change disk layout to fit maven
+#
+
+-outputmask = ${@bsn}-${versionmask;===S;${@version}}.jar
+src=src/main/java
+bin=target/classes
+testsrc=src/test/java
+testbin=target/test-classes
+target-dir=target
+
+ +

We will not explain this plugin here (you can find it in the plugin sections), it only illustrates here how it is possible to setup the environment for a specific optional functionality like a plugin.

+

If you create local extension files then you should use a prefix to identify this is your file, like:

+
com.acme-local.bnd
+
+ +

It is possible to use file links to maintain these files in one place when you have many workspaces.

+

Extension File loading mechanism and order

+

Extension files will be loaded in alphabetical order. If a files defines a property that was already defined in another previously loaded file or the build.bnd, the property will be assigned a namespace. -plugin in /cnf/ext/test.bnd will become -plugin.test. Please note that this mechanism is just a best guess courtesy and has its limits. If -plugin.test was already defined previously, the old value will be overwritten.

+

Local customizations

+

After reading the extension files, bndlib reads the cnf/build.bnd file, this file is supposed to hold the organization specific properties. Out of the box, this file comes empty, ready to be filled by you.

+

Workspace Plugins

+

A plugin is a piece of code that runs inside bnd. The workspace provides a number of standard built-in plugins like an Executor, a Randum number generator, itself, etc. Additional plugins can be added with the -plugin.* instructions.

+

Project Properties

+

There are a number of built in properties that are set by bnd:

+

|-----------------+-----------------------------------------------------------------| +| Property name | Description | +|-----------------|:----------------------------------------------------------------| +|project | Name of the project. This is the name of the bnd file without | +| | the .bnd extension. If this name is bnd.bnd, then the directory | +| | name is used. | +|-----------------+-----------------------------------------------------------------| +|project.file | Absolute path of the main bnd file. | +|-----------------+-----------------------------------------------------------------| +|project.name | Just the name part of the file path | +|-----------------+-----------------------------------------------------------------| +|project.dir | The absolute path of the directory in which the bnd file resides. | +|-----------------+-----------------------------------------------------------------|

+

Run instructions

+

Run instructions are used to start OSGi tests and OSGi runs.

+

|-runbundles |LIST SPEC |Additional bundles that will be installed and started when the framework is launched. This property is normally part of the project's bnd.bnd file.| +|-runvm |PROPERTIES |Properties given to the VM before launching. This property is normally set in the cnf/build.bnd file and only in rare cases overridden in the bnd.bnd file.| +|-runproperties |PROPERTIES |Properties given to the framework when launching. Usually project specific.| +|-runsystempackages|PACKAGES |A declaration like Import-Package that specifies additional system packages to import from the class path. Usually given in the cnf/build.bnd file.| +|-runpath |LIST SPEC |A path description of artifacts that must be on the classpath of the to be launched framework. Usually given in the cnf/build.bnd file. This path should contain the framework. Any packages that a bundle on the -runpath should specify should be listed in the export attribute.| +|-runtrace |true|false |Trace the startup of the framework to the console. Usually used during testing and development so project specific.| +|-runframework |none|services|NONE indicates that a mini built in framework should be used. SERVICES indicates that the META-INF/services model must be followed for the org.osgi.framework.launch.FrameworkFactory class. Project specific.| +|-testpath |LIST SPEC |A path used to specify the test plugin.|

+

Launching

+

Launching is needed when the project's run action or test action is executed. The project creates a Project Launcher. A Project Launcher must launch a new VM and set up this VM correctly. The VM is launched with the following information:

+ +

An example of a launcher set is:

+
-runvm:   -Xmn100M, -Xms500M, -Xmx500M
+-runpath: \
+    org.apache.felix.framework; version=3.0, \
+    junit.osgi;export="junit.framework;version=3.8"
+-runtrace: true
+-runproperties: launch=42, trace.xyz=true
+-runbundles: org.apache.felix.configadmin,\
+    org.apache.felix.log,\
+    org.apache.felix.scr,\
+    org.apache.felix.http.jetty,\
+    org.apache.felix.metatype,\
+    org.apache.felix.webconsole
+
+ +

Debugging the launcher is greatly simplified with the -runtrace property set to true. This provides a lot of feedback what the launcher is doing.

+

Access to arguments

+

When the Framework is started the Launcher will register itself as a service of type java.lang.Object with the property launcher.arguments to provide access the arguments handed to the launcher. After all Bundles have been installed and started the ServiceRegistration will be updated with the property launcher.ready=true.

+

Access to main thread

+

In certain cases it is necessary to grab the main thread after launching. The default launcher will launch all the bundles and then wait for any of those bundles to register a Runnable service with a service property main.thread=true. If such service is registered, the launcher will call the run method and exit when this method returns.

+

Timeout

+

The launcher will timeout after an hour. There is currently no way to override this timeout.

+

Mini Framework

+

The bnd launcher contains a mini framework that implements the bare bones of an OSGi framework. The purpose of this mini framework is to allow tests and runs that want to launch their own framework. A launch that wants to take advantage of this can launch with the following property:

+
-runframework: none
+
+ +

Ant

+

In Ant, the following task provides the run facility.

+
<target name="run" depends="compile">
+    <bnd command="run" exceptions="true" basedir="${project}" />
+</target>
+
+ +

These targets provide commands for ant run.

+

Testing

+

Testing is in principle the same as launching, it actually uses the launcher. Testing commences with the test action in the project. This creates a Project Tester. bnd carries a default Project Tester but this can be overridden.

+

The basic model of the default Project Tester plugin is to look for bundles that have a Test-Cases manifest header after launching. The value of this header is a comma separated list of JUnit test case class names. For example:

+
Test-Cases: test.LaunchTest, test.OtherTest
+
+ +

Maintaining this list can be cumbersome and for that reason the ${classes} macro can be used to calculate its contents:

+
Test-Cases: ${classes;extending;junit.framework.TestCase;concrete}
+
+ +

See classes macro for more information.

+

Ant

+
<target name="test" depends="compile">
+    <bnd command="test" exceptions="true" basedir="${project}" />
+</target>
+
+ +

Overriding the plugins

+

Both the Project Launcher and Project Tester are plugins. Defaults are provided by bnd itself (bnd carries a mini cache repo that is expanded in the cnf directory), it is possible to add new launchers and testers as needed.

+

Launcher or tester plugins are found on the -runpath or the -testpath properties, respectively. To detect a plugin, bnd will look for an appropriate manifest header. The header value is a class name. Bnd will then instantiate the class and use it as a launcher/tester. The classes must extend an abstract base class. Each plugin has access to the Project object, containing all the details of the project.

+

|Plugin |Manifest header|Base Class |Where searched| +|------------------------------------------------------------------| +|Project Launcher |Launcher-Plugin|ProjectLauncher|-runpath| +|Project Tester |Tester-Plugin |ProjectLauncher|-testpath|

+

The plugin gets complete control and can implement many different strategies.

+ + diff --git a/org.bndtools.help/docs/chapters/155-project-setup.html b/org.bndtools.help/docs/chapters/155-project-setup.html new file mode 100644 index 0000000000..429d7f23f3 --- /dev/null +++ b/org.bndtools.help/docs/chapters/155-project-setup.html @@ -0,0 +1,12 @@ + + + + +Project Setup + + + +

Project Setup

+ + + diff --git a/org.bndtools.help/docs/chapters/160-jars.html b/org.bndtools.help/docs/chapters/160-jars.html new file mode 100644 index 0000000000..b55137c628 --- /dev/null +++ b/org.bndtools.help/docs/chapters/160-jars.html @@ -0,0 +1,132 @@ + + + + +Generating JARs + + + +

Generating JARs

+

This is about generating OSGi JARs - one of the main tasks of bnd.

+

This is a simple example of wrapping a jar with bnd (wrapping means: taking a non-OSGi jar and use bnd to add OSGi meta data to its MANIFEST.MF to get a proper OSGi .jar).

+

The basic idea is to create a recipe (a .bnd file) that collects the different resources in the right way to create the new output .jar including the OSGi meta data in MANIFEST.MF.

+

For example, you want to wrap the WebSocket server from https://github.com/TooTallNate/Java-WebSocket/releases/tag/Java-WebSocket-1.3.4. Download the binary (Java-WebSocket-1.3.4.jar) and the sources in Java-WebSocket-1.3.4-sources.jar.

+

Project

+

Once you have these files, create a folder e.g. mkdir wrappers and add bnd.bnd file in the project to create the org.websocket.jar bundle.

+
# bnd.bnd
+# Wrapped version of Github project TooTallNate/Java-WebSocket
+Bundle-SymbolicName: org.websocket
+Bundle-DocURL: https://github.com/TooTallNate/Java-WebSocket
+Bundle-License: https://github.com/TooTallNate/Java-WebSocket/blob/8ef67b46ecc927d5521849dcc2d85d10f9789c20/LICENSE
+Bundle-Description: This repository contains a barebones \
+ WebSocket server and client implementation written \
+ in 100% Java. The underlying classes are implemented \
+ using the Java ServerSocketChannel and SocketChannel \
+ classes, which allows for a non-blocking event-driven model \
+ (similar to the WebSocket API for web browsers). \
+ Implemented WebSocket protocol versions are: Hixie 75, \
+ Hixie 76, Hybi 10, and Hybi 17
+
+# version taken from the downloaded file above
+Bundle-Version: 1.3.4
+
+-includeresource: @Java-WebSocket-1.3.4.jar, OSGI-OPT/src=@Java-WebSocket-1.3.4-sources.jar
+-exportcontents: org.java_websocket
+
+ +

Either use the bndtools Eclipse plugin or the bnd CLI to process the bnd.bnd file and let bnd create the .jar. In case of bnd CLI the command is:

+
bnd bnd.bnd
+
+ +

Manifest

+

Applying this recipe above gives the following META-INF/MANIFEST.MF in a JAR named /generated/org.websocket.jar:

+
Manifest-Version: 1.0
+Bnd-LastModified: 1338190175969
+Bundle-Description: This repository contains a barebones WebSocket serve
+ r and client implementation written in 100% Java. The underlying classe
+ s are implemented using the Java ServerSocketChannel and SocketChannel 
+ classes, which allows for a non-blocking event-driven model (similar to
+ the WebSocket API for web browsers). Implemented WebSocket protocol ve
+ rsions are: Hixie 75, Hixie 76, Hybi 10, and Hybi 17
+Bundle-DocURL: https://github.com/TooTallNate/Java-WebSocket
+Bundle-License: https://github.com/TooTallNate/Java-WebSocket/blob/8ef67
+ b46ecc927d5521849dcc2d85d10f9789c20/LICENSE
+Bundle-ManifestVersion: 2
+Bundle-Name: org.websocket
+Bundle-SymbolicName: org.websocket
+Bundle-Version: 1.3.4
+Export-Package: org.java_websocket;version="1.3.4";uses:="javax.net.ss
+l"
+Import-Package: javax.net.ssl
+Private-Package: org.java_websocket.client,org.java_websocket.drafts,o
+rg.java_websocket.exceptions,org.java_websocket.framing,org.java_webs
+ocket.handshake,org.java_websocket.server,org.java_websocket.util
+Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.5))"
+
+ +

You notice that the .bnd file and the MANIFEST look similar but the bnd instructions caused bnd to generate headers like Export-Package and Import-Package. bnd did that by analysing the .class files inside Java-WebSocket-1.3.4.jar (e.g. by looking at all the import statements classes, methods, method parameters and return types).

+

Note: The documentation headers like Bundle-Description are optional but very important, just spent the minute to document them since you'll be grateful later.

+

If the target project does not have a version, makeup a version and maintain it. Notice that in general the recipe will only be used once for each version, it is normally not used in continuous integration builds. However, you normally use it to convert the next version of the project. Crisp versioning is important.

+

The -includeresource statement unrolls the jars we downloaded in the root of the JAR and in OSGI-OPT. Since the source code is in the src directory in the WebSocket-src.zip file, we put it in the new JAR under OSGI-OPT/src. This convention is supported by all IDEs to give you direct access to the bundle's source code. Since the binary and the source are kept together, you always have the correct source code available, and usually automatically. It is so convenient that once you're used to this it is hard to imagine a life without source code.

+

The binaries and sources are not in the final jar but bnd does not yet know what needs to be exported. This can be indicated with the -exportcontents instruction. It has the same syntax as Export-Package but does not copy from the classpath, it only applies the instruction to the content of the final JAR.

+

OSGi Header Attribute and Directive Ordering

+

When bnd processes OSGi manifest headers, it automatically ensures consistent ordering of attributes and directives within header clauses. This ordering is applied to OSGi syntax headers such as Export-Package, Import-Package, Require-Capability, Provide-Capability, and others.

+

Ordering Rules

+

Bnd applies the following ordering rules to attributes and directives within OSGi header clauses:

+
    +
  1. Attributes come before directives - All attributes (keys without a trailing colon) are placed before directives (keys with a trailing colon)
  2. +
  3. Alphabetical sorting within groups - Within the attribute group and directive group, keys are sorted alphabetically (case-insensitive)
  4. +
+

Example

+

Given an input header like:

+
Export-Package: com.example.api;uses:="com.example.internal";version=1.0.0;mandatory:="version";provider=acme
+
+ +

Bnd will reorder it to:

+
Export-Package: com.example.api;provider=acme;version=1.0.0;mandatory:="version";uses:="com.example.internal"
+
+ +

Notice how: +- Attributes (provider, version) come first, sorted alphabetically +- Directives (mandatory:, uses:) come second, sorted alphabetically

+

Benefits

+

This consistent ordering provides several benefits:

+ +

Affected Headers

+

This ordering is applied to all headers defined in Constants.OSGI_SYNTAX_HEADERS, which includes: +- Export-Package +- Import-Package +- Require-Capability +- Provide-Capability +- Bundle-SymbolicName +- Fragment-Host +- And other OSGi-defined headers that use the clause syntax

+

Extra entries on the Classpath

+

One of the great features of bnd is to use export version from other versions to generate the import ranges. This feature requires that the other JARs are on the classpath. In bndtools you can use the -buildpath. However, you always add entries on the class path per bnd descriptor with the -classpath instruction:

+
-classpath: dependency.jar, other.jar
+
+ +

Wrapper project

+

The easiest way to build these wrappers is to create a project in bndtools called wrappers and create a main bnd.bnd with the following content:

+
-sub: *.bnd
+
+ +

The create a bnd.bnd descriptor for each wrapper you need to build. e.g.

+ +

When the main bnd.bnd is processed bnd creates a jar for each sub- .bnd file. +E.g.

+
bnd bnd.bnd
+
+ +

creates a /generated/websocket.jar and /generated/someotherlib.jar.

+

All headers

+

All headers are listed on the Headers index

+ + diff --git a/org.bndtools.help/docs/chapters/170-versioning.html b/org.bndtools.help/docs/chapters/170-versioning.html new file mode 100644 index 0000000000..d5beba31cb --- /dev/null +++ b/org.bndtools.help/docs/chapters/170-versioning.html @@ -0,0 +1,165 @@ + + + + +Versioning + + + +

Versioning

+

Versioning is probably the most painful part of developing real software. Where toys and prototypes can be developed ignoring evolution, real software requires a migration path to an unknown future.

+

The OSGi has defined a versioning policy that is described in the Semantic Versioning whitepaper. bnd fully supports this model and provides many shortcuts. The goal of bnd is remove any manual work from versioning bundles as well as packages.

+

The key concept to version in OSGi is the ''package''. Bundles are an ''aggregate'' and therefore must move as fast as the fastest moving exported packages they contain. For example, if a bundle contains two exported packages foo and bar and foo is not changed but bar has a major change, then the bundle version needs to also have a major change. This requires an unnecessary update for a bundle that only depended on foo. Aggregating dependencies increases the fan out of the transitive dependencies. The result is that systems can only evolve when everything is updated simultaneously. The result is that the system as a whole becomes brittle.

+

In contrast, versioning the packages and using Import-Package, bundles can be refactored and versioned independently.

+

Best Practices

+ +

Versions in OSGi

+

A version in OSGi has 4 parts:

+

major 1 + minor 1.1 + micro 1.1.1 + qualifier 1.1.1.qualifier

+

To survive versioning, one must have a ''version policy''. A version policy puts semantics on the version numbers. The ''recommended'' policy in OSGi is changing the part when there is:

+

major a breaking change + minor a backward compatible changes + micro a bug fix (no API change) + qualifier a new build

+

In OSGi, the decision was taken to have a single export version. The import statement allows a version range to be set. For example:

+
Export-Package: com.acme.foo; version=1.0.2
+Import-Package: com.acme.bar; version="[1,2)"
+
+ +

The semantic versioning white paper introduces two terms that are orthogonal to the imports and exports as well as implementing or delegating:

+ +

Provide and consume is orthogonal to implementing an interface and delegating. For example, the Configuration Admin service has the ConfigurationAdmin interface that is implemented by the Provider of an API but the ConfigurationListener interface is implemented by the Consumer of the API.

+

The reason for the providers and consumer terms is that version policies are different. A change in an API almost always affects the provider but with careful API design it is often possible to make a change backward compatible for consumers.

+

In bnd, whenever you have to provide an import range, you can use modifiers to create a range out of a single version:

+ +

Versioning Packages

+

If you have a package that is containing implementation code that is supposed to be directly used by the consumers then this is a ''library''. +A library package is not an API that can be implemented by other bundles, it is the implementation. Then the versioning of library packages is relatively straightforward: Any change that breaks a consumer of that package must increment the major version number. For example, if the popular ASM library would add a method to the MethodVisitor class then it must increment the major version number of the org.objectweb.asm package because all existing consumers of this library would then be broken.

+

If however a package contains an API that is provided and consumed by others the situation is more complex. In such a case, the provider should export the API package and the consumers should import it.

+

bnd explicitly allows the inclusion of packages that come from other projects. It is just good practice to include an API package in your bundle if you are the provider of that API. However, this means that maintaining the version of the package in the manifest is ''wrong'', it would have to be maintained in several places, which is very error prone.

+

For this reason, bnd provides a way to store the version of the package together with the package itself. One with annotations and one without when annotations are not possible.

+

The @Version annotation is placed on the package. Since Java 5 it is possible to create a package-info.java file that can be used to annotate packages:

+
package-info.java:
+    @org.osgi.annotation.versioning.Version.Version("1.2.0")
+    package com.example;
+
+ +

A non-annotation based alternative is the packageinfo file. When bnd scans the Java archives it will look in each package for this packageinfo file. The format of this file is very simple:

+
packageinfo:
+    version 1.2.0
+
+ +

If you now export the package (from any bundle that has the package on its class path), it will be properly versioned.

+
bnd.bnd:
+    Export-Package: com.example.*
+
+ +

The resulting manifest will look like:

+
Manifest:
+    Export-Package: com.example; version=1.2.0
+
+ +

If you export a package from another bundle, bnd will also look in the manifest of that other bundle for a version.

+

Using packageinfo (or the @Version annotation) is highly recommended.

+

When Package Version Differ

+

The package version for package p can come from the following places (in order of increasing priority):

+ +

The bnd warning means that bnd finds multiple definitions of the version for p and they are not the same. So I assume you set the version in the manifest of the bundle under construction and in one of those other places. The best is to remove the version from your bnd.bnd file. The by far absolute best way is to only set the version of the package in the package directory (either packageinfo or package-info.java with an annotation).

+

Import Version Policy

+

If you import a package bnd will look at the exported version of that package. This version is not directly suitable for the import because it is usually too specific, it needs a policy to convert this export version to an import version.

+

An importer that provides the functionality of an API package is much closer tied to that package than a client. The whitepaper recommends binding to the major.minor part of the version for a provider. That is, any change in the minor part of the version breaks the compatibility. This makes sense, the provider of an API must implement the contract and is therefore not backward compatible for any change in the API. A consumer of the API only has to be bound to the major part because it is much more relaxed for the backward compatibility.

+

For example, a new method is added to an interface that is implemented by the provider of the API. Old clients have no visibility of this method because when they compiled it did not exist. However, the provider of the API must be modified to implement this method otherwise more modern clients would break.

+

This asymmetry creates the need for two version policies:

+
-provider-policy :    ${range;[==,=+)}
+-consumer-policy :    ${range;[==,+)}
+
+ +

The given values are the defaults. The value of the version policy will be used calculate the import based on the exported package. The ${range} macro provides a convenient shortcut to do this using a version mask.

+

For example, a bundle that implements the OSGi Event Admin service can use the following bnd file:

+
bnd.bnd:
+    Private-Package: com.example.impl.event
+
+ +

The resulting manifest would look like:

+
Manifest:
+    Import-Package:  org.osgi.service.event; version="[1.1,2)", ...
+    ...
+
+ +

How does bnd know if a bundle is a provider or a consumer of a specific package?

+

Well, the default is the consumer policy but this can be overridden with the provide:=true directive that works on the Import-Package clauses as well as on the Export-Package clauses.

+

The provide: directive indicates to bnd that the given package contains API that is provided by this bundle. The (strongly) recommended way is to put the provide:=true directive on the Export-Package header, even if the package comes from another bundle. This way the bundle contains a copy of the package that is by default imported with the proper provider policy range.

+

Also see -consumerpolicy, -providerpolicy and range.

+

For example, an implementation of the OSGi Event Admin specification could use the following bnd file:

+
bnd.bnd:
+    Export-Package:  org.osgi.service.event; provide:=true
+    Private-Package: com.example.impl.event
+
+ +

The resulting manifest would look like:

+
Manifest:
+    Export-Package:  org.osgi.service.event; version=1.1
+    Import-Package:  org.osgi.service.event; version="[1.1,1.2)", ...
+    ...
+
+ +

If for some reason it is not desirable to export the API package in the implementation bundle, then the provide: directive can also be applied on the Import-Package header:

+
bnd.bnd
+    Import-Package: org.osgi.service.event; provide:=true, *
+    Private-Package: com.example.impl.event
+
+ +

The resulting manifest would look like:

+
Manifest:
+    Import-Package:  org.osgi.service.event; version="[1.1,1.2)", ...
+    ...
+
+ +

Substitution

+

A key aspect of OSGi is that a package can be both imported and exported. The reason is that this feature allows a framework more leeway during resolving without creating multiple unconnected class spaces.

+

After the bundle has been created and analyzed bnd will see if an exported package is eligible for import. An export is automatically imported when the following are true:

+ +

If a package is imported it will use the version as defined by the version policy.

+

With the -nosubstitution: true instruction, this behavior can be disabled globally.

+

Versioning Bundles

+

Versioning bundles usually requires bumping the version every time it is placed in a repository. When package versioning is used, the bundle version is only important for tracking an artifact.

+

Why does bnd use only major and minor version component in import-package headers?

+

The micro is left out because it generates a lot of unnecessary releases, this is similar to the maven release process. If you connect everything 100%, you cannot move anything unless all its dependencies are moved at the same time. We actually tried in the OSGi build to use micro version changes for default methods in Java 8 but found that it just creates an enormous ripple through effect in the build. Not depending on the micro version is a lubricant that does not kill any bundle out there that depends on you.

+

This should not be a problem because a micro version is a deployment issue since the semantic versioning should be used for APIs and a micro change is not visible in the API.

+

That said, this is bnd so obviously you can override it. You can override the default version policy is:

+
-provider-policy = ${range;[==,=+)}
+-consumer-policy = ${range;[==,+)}
+
+ +

Just set '===' instead of '==' for the floor version in your pom.xml in the section and you should be ok.

+
<configuration>
+    <_provider-policy>${range;[===,=+)}</_provider-policy>
+    <_consumer-policy>${range;[===,+)}</_consumer-policy>
+</configuration>
+
+ + diff --git a/org.bndtools.help/docs/chapters/180-baselining.html b/org.bndtools.help/docs/chapters/180-baselining.html new file mode 100644 index 0000000000..ed5b3b0a1b --- /dev/null +++ b/org.bndtools.help/docs/chapters/180-baselining.html @@ -0,0 +1,55 @@ + + + + +Baselining + + + +

Baselining

+

Baselining compares a bundle with another bundle, the baseline, to find mistakes in the semantic versioning. For example, there is a binary incompatible change in the new bundle but the version has not been bumped. Baselining can be run from the command line (see bnd help baseline) or it can be run as part of a project build.

+

APIs are compared for backward compatibility using the semantic versioning rules defined in this chapter. Baselining is aware of the @ConsumerType and @ProviderType rules. Proper versions are calculated and suggested.

+

Setting Up a Project for Baselining

+

During the build, bnd will check the -baseline instruction at the end of the build when the JAR is ready. This instruction is a selector on the symbolic name of the building bundle. If it matches, the baselining is started with one exception: by default, the bundle/package version must be 1.0.0 or above. If the version is less (i.e. major version being 0) no baselining errors are reported, the purpose is to allow the primordial baseline to be established without errors.

+

To enable baselining for versions in the range [0.1.0, 1.0.0), use the -baselineincludezeromajor instruction:

+
-baselineincludezeromajor: true
+
+ +

This will enable baseline error reporting for packages with major version 0 (except for 0.0.x versions which are still excluded).

+

By default the baseline is a bundle from one of the repositories with the same symbolic name as the building bundle and the highest possible version. However, it is possible to specify the version or to baseline against a file.

+

It is recommended to enable baselining per project since not all project requires baselining. For example, baselining is overkill for a project that is always compiled with all its dependencies and thus has no external dependencies. The recommended practice is therefore to add the following instruction to a project that requires baselining (usually API bundles):

+
-baseline: *
+
+ +

The default baseline is the bundle with the highest version in the baseline repository. The selector can specify a version or a file attribute when the default baseline is not applicable.

+ +

The baseline bundle is looked up in the baseline repository. The baseline repository is by default the release repository unless overridden by the -baselinerepo instruction. The release repository is set with the -releaserepo instruction.

+

Only bundles that are not staging are considered for the baseline, this means that it is possible to release the current bundle and compare against the previous version until the bundle is released and becomes master.

+

By default the bundle and baseline are compared (diffed) and then analyzed for semantic version violations. Certain headers always change because they contain time or digest information. Most of these headers are already automatically ignored but the -diffignore instruction can add more ignorance. You can use the +-diffpackages instruction to specify the names of exported packages to be baseline compared. The default is to baseline compare all exported packages.

+

Maven Support

+

There is a dedicated Maven plugin for baselining.

+

Example baselining Project Instructions

+
  Bundle-Version: 1.0.2
+  -baseline: *
+  -baselinerepo: Released
+
+ +

In this example, the last version in the Released repository for the project's bsn is supposed to be the previous version. Make sure you do not always release staging versions to this repository since this will create false changes. During a development cycle, the baseline version must remain constant until the current development bundle is released, at which points it becomes the baseline of the next cycle.

+

Since an error is raised when the baselining detects a semantic version violation it is possible to release a snapshot in a build only when there is a correctly baselined bundle built.

+

@BaselineIgnore - Fine grained control

+

Occasionally, scenarios arise where a language construct or change is not accounted for in bnd (bnd developers are humans too), or where a developer wants to overrule the strict opinion of the baseline logic for whatever reason (not recommended but it does happen) for instance in the grey areas of binary compatibility.

+

Instead of forcing developers to make a choice between disabling baseline (in order to avoid build warnings or failures) and keeping it enabled it's important to know that there is fine grained control available using bnd's @aQute.bnd.annotation.baseline.BaselineIgnore annotation.

+

The value of the @BaselineIgnore annotation is a valid OSGi version string.

+

e.g.

+
@BaselineIgnore("2.4.12")
+public Foo getFoo();
+
+ +

When the @BaselineIgnore annotation is applied to a baselined element, the baseliner will ignore the annotated element when baselining against a baseline package whose version is less than the specified version. This means the annotated element will not produce a baselining mismatch. The correct baseline information about the element will be in the baseline report, but the element will not cause baselining to fail. When baselining against a baseline package whose version is greater than or equal to the specified version, this annotation is ignored and the annotated element will be included in the baselining.

+

The annotation should be used in a scope that is as narrow as possible by applying it to the most specific member causing the baseline issue.

+ + diff --git a/org.bndtools.help/docs/chapters/200-components.html b/org.bndtools.help/docs/chapters/200-components.html new file mode 100644 index 0000000000..ac06e697b8 --- /dev/null +++ b/org.bndtools.help/docs/chapters/200-components.html @@ -0,0 +1,320 @@ + + + + +Service Components + + + +

Service Components

+

The Service-Component header is compatible with the standard OSGi header syntax. Any element in the list that does not have attributes must have a resource in the JAR and is copied as is to the manifest. However, simple components can also be defined inline, and it is even possible to pickup annotations.

+

The syntax for these component definitions is:

+
component ::= <name> ( ';' parameter ) *
+parameter ::= provide | reference | multiple | optional
+            | reference | properties | factory | servicefactory
+            | immediate | enabled | implementation
+            | activate | deactivate | modified | configuration-policy
+            | version | designate
+
+reference ::= <name> '=' <interface-class>
+               ( '(' <target-filter> ')')? cardinality?
+cardinality ::= '?' | '*' | '+' | '~'
+provide  ::= 'provide:=' LIST
+multiple  ::= 'multiple:=' LIST
+optional  ::= 'optional:=' LIST
+dynamic   ::= 'dynamic:=' LIST
+designate  ::= ( 'designate' | 'designateFactory' ) CLASS
+factory   ::= 'factory:=' true | false
+servicefactory := 'servicefactory:=' true | false
+immediate ::= 'immediate:=' true | false
+enabled   ::= 'enabled:=' true | false
+configuration-policy ::= "configuration-policy:='
+     ( 'optional' | 'require' | 'ignore' )
+activate  ::= 'activate:=' METHOD
+modified  ::= 'modified:=' METHOD
+deactivate::= 'deactivate:=' METHOD
+implementation::= 'implementation:=' <implementation-class>
+properties::= 'properties:=' key '=' value
+              ( ',' key '=' value ) *
+key       ::= NAME (( '@' | ':' ) type )?
+value     ::= value ( '|' value )*
+
+ +

If the name of the component maps to a resource, or ends in XML, or there are attributes set, then that clause is copied to the output Service-Component header.

+

If the name can be expanded to one or more classes that have component annotations (they must be inside the JAR), then each of those classes is analyzed for its component annotations. These annotations are then merged with the attributes from the header, where the header attributes override annotations. The expansion uses the normal wildcard rules. For example, biz.aQute.components.* will search for component annotated classes in the biz.aQute.components package or one of its descendants. The classes must be present in the JAR. If no classes with annotations can be found for the name then it is assumed to be name or implementation class name without annotations.

+

The name of the component is also the implementation class (unless overridden by the implementation: directive). It is then followed with a number of references and directives. A reference defines a name that can be used with the locateService method from the ComponentContext class. If the name starts with a lower case character, it is assume to be a bean property. In that case the reference is augmented with a set<Name> and unset<Name> method according to the standard bean rules. Bnd will interpret the header, read the annotations if possible, and create the corresponding resources in the output jar under the name OSGI-INF/<id>.xml.

+

Annotations are only recognized on the component class, super classes are not inspected for the components.

+

Component Class Requirements

+

For a class to be a valid DS component, it must meet the following requirements:

+

Constructor Requirements

+

A DS component class must have either: +- A public no-argument constructor (this is the default constructor if no other constructors are declared), OR +- A public constructor annotated with @Activate for constructor injection

+

If your component class has a constructor with parameters but no @Activate annotation, bnd will generate an error:

+
The DS component class {className} must be publicly accessible and have either a public no-arg constructor or a public constructor annotated with @Activate. Non-public classes, including public inner classes enclosed in non-public classes, are not supported.
+
+ +

Examples of valid components:

+
// Valid: Implicit public no-arg constructor
+@Component
+public class MyComponent {
+    // Implicit public no-arg constructor
+}
+
+// Valid: Explicit public no-arg constructor
+@Component
+public class MyComponent {
+    public MyComponent() {
+        // initialization
+    }
+}
+
+// Valid: Constructor injection with @Activate
+@Component
+public class MyComponent {
+    private final BundleContext context;
+
+    @Activate
+    public MyComponent(BundleContext context) {
+        this.context = context;
+    }
+}
+
+// Valid: Multiple constructors with public no-arg
+@Component
+public class MyComponent {
+    public MyComponent() {
+        // default constructor
+    }
+
+    // This constructor is ignored by DS
+    public MyComponent(String config) {
+        // some other constructor
+    }
+}
+
+ +

Examples of invalid components:

+
// Invalid: No public no-arg constructor and no @Activate
+@Component
+public class MyComponent {
+    public MyComponent(BundleContext context) {
+        // ERROR: needs @Activate annotation
+    }
+}
+
+// Invalid: Package-private class (constructor not public)
+@Component
+class MyComponent {
+    // ERROR: class must be public
+}
+
+ +

Inner Class Requirements

+

If you use inner classes as components, they must be declared as static. Non-static inner classes require an instance of the outer class to be instantiated, which DS cannot provide.

+

Valid:

+
@Component
+public class OuterComponent {
+
+    @Component
+    public static class InnerComponent {
+        // Valid: static inner class
+    }
+}
+
+ +

Invalid:

+
@Component
+public class OuterComponent {
+
+    @Component
+    public class InnerComponent {
+        // ERROR: non-static inner class cannot be instantiated by DS
+    }
+}
+
+ +

The supported annotations in the aQute.bnd.annotations.component package are:

+

||!Component|| +Annotated the class, indicates this class is required to be a component. It has the following properties:

+

|| provide||Class[]||Service interfaces, the default is all directly implemented interfaces|| +||name ||String||Name of the component|| +||factory ||Boolean||Factory component|| +||servicefactory||Boolean||Service Factory|| +||immediate||Boolean||Immediate activation|| +||designate||CLASS||Designate a class as a [[MetaType]] interface used for configurations for unitary configurations, see [[#metatype]]. This changes the default of the configurationPolicy to require.|| +||designateFactory||CLASS||Designate a class as a [[MetaType]] interface used for configurations for factory configurations, see [[#metatype]]. This changes the default of the configurationPolicy to require.|| +||configurationPolicy||OPTIONAL, REQUIRE, IGNORE||Configuration Policy|| +||enabled||Boolean||Enabled component|| +||properties||String[]||Properties specified as an array of key=value. The property type can be specified in the key as name:Integer. The value can contain multiple values, the parts must then be separated by a vertical bar ('|') or a line feed (\n), for example properties = {"primes:Integer==1|2|3|5|7|11"}.||

+

||!Reference|| +On a method. Indicates this method is the activate method. It has the following attributes

+

||name||String||Name of the reference. Default this is the name of the method without set on it.|| +||service||Class||The service type, default is the argument type of the method. The unset method is derived from this name. I.e. setXX will have an unsetXX method to unset the reference.|| +||type||Character||Standard cardinality type '?', '*', '+','~'|| +||target||String||A filter expression applied to the properties of the target service|| +||unbind||String||Optional name of the unbind method. By default this is the same name as the bind method name but with set/add replaced with unset/remove. E.g. setFoo() bind method becomes unsetFoo() unbind method.||

+

@Reference automatically sets the bind method. The unbind method is set by using a derived name from the bind method or providing it with the name of the unbind method. The following name patterns are supported:

+

||!bind||!unbind|| +||setX ||unsetX|| +||addX ||removeX|| +||xxxX ||unxxxX|| +For example:

+
@Reference
+protected void setFoo(LogService l) { ... }
+protected void unsetFoo(LogService l) { ... }
+
+ +

If you want to override this, use

+
@Reference(unbind="IRefuseToCallMyMethodUnFoo");
+protected void foo(LogService l) {}
+protected void IRefuseToCallMyMethodUnFoo(LogService l) {}
+
+ +

Unfortunately Java has no method references so it is not type safe.A non existent @UnReference annotation is not very useful because that still requires linking it up symbolically to the associated @Reference.

+

||!Activate, Modified, and Deactivate|| +The life cycle methods. These annotations have no properties.

+

Assume the JAR contains the following class:

+
package com.acme;
+import org.osgi.service.event.*;
+import org.osgi.service.log.*;
+import aQute.bnd.annotation.component.*;
+
+@Component
+public class AnnotatedComponent implements EventHandler {
+  LogService log;
+
+  @Reference
+  void setLog(LogService log) { this.log=log; }
+
+  public void handleEvent(Event event) {
+    log.log(LogService.LOG_INFO, event.getTopic());
+  }
+}
+
+ +

The only thing necessary to register the Declarative Service component is to add the following Service-Component header:

+
Service-Component: com.acme.*
+
+ +

This header will look for annotations in all com.acme sub-packages for an annotated component. The resulting XML will look like:

+

OSGI-INF/com.acme.AnnotatedComponent.xml:

+
<?xml version='1.0' encoding='utf-8'?>
+<component name='com.acme.AnnotatedComponent'>
+  <implementation class='com.acme.AnnotatedComponent'/>
+  <service>
+    <provide interface='org.osgi.service.event.EventHandler'/>
+  </service>
+  <reference name='log'
+    interface='org.osgi.service.log.LogService'
+    bind='setLog'
+    unbind='unsetLog'/>
+</component>
+
+ +

The following example shows a component that is bound to the log service via the setLog method without annotations:

+
Service-Component=aQute.tutorial.component.World;
+  log=org.osgi.service.log.LogService
+
+ +

The Service Component Runtime (SCR) offers a variety of options on the reference. Some options like the target can be used by adding the target filter after the interface name (this likely requires putting quotes around the interface name+filter).

+

References can be suffixed with the following characters to indicate their cardinality:

+
Char          Cardinality    Policy
+?             0..1           dynamic
+*             0..n           dynamic
++             1..n           dynamic
+~             0..1           static
+              1              static
+
+ +

For a more complex example:

+
Service-Component=aQute.tutorial.component.World;
+  log=org.osgi.service.log.LogService?;
+  http=org.osgi.service.http.HttpService;
+  PROCESSORS="xierpa.service.processor.Processor(priority>1)+";
+  properties:="wazaabi=true"
+
+ +

The previous example will result in the following service component in the resource OSGI-INF/aQute.tutorial.component.World.xml:

+
<?xml version="1.0" encoding="utf-8" ?>
+<component name="aQute.tutorial.component.World">
+  <implementation class="aQute.tutorial.component.World" />
+  <reference name="log"
+    interface="org.osgi.service.log.LogService"
+    cardinality="0..1"
+    bind="setLog"
+    unbind="unsetLog"
+    policy="dynamic" />
+  <reference name="http"
+    interface="org.osgi.service.http.HttpService"
+    bind="setHttp"
+    unbind="unsetHttp" />
+  <reference name="PROCESSORS"
+    interface="xierpa.service.processor.Processor"
+    cardinality="1..n"
+    policy="dynamic"
+    target="(&(priority>=1)(link=false))" />
+</component>
+
+ +

The description also supports the immediate, enabled, factory, target, servicefactory, configuration-policy, activate, deactivate, and modified attributes. Refer to the Declarative Services definition for their semantics.

+

If any feature of the V1.1 namespace is used, then bnd will declare the namespace in the component element. A specific namespace version can be set with the version directive. This detection only works when components are used.

+

Bnd also supports setting the policy and cardinality through the following directives:

+
multiple:= LIST    names of references that have x..n
+optional:= LIST    names of references that have 0..x
+dynamic:=  LIST    names of references that are dynamic
+
+ +

Components and Metatype

+

The Service Component Runtime works closely together with the Configuration Admin to allow the components to be controlled through configuration. Configuration Admin knows two types of configuration:

+ +

A unitary configuration can be set and changed but there is at most one of them. A Factory configuration can be used to create multiple instances of the same component. A component has a configuration policy that defines when no configuration is set.

+ +

A related standard is the Metatype standard. The Metatype Service provides a repository of property descriptors. Bundles can provide these descriptors in their bundles in the OSGI-INF/metatype directory. There are tools, like the Felix Webconsole, that can provide an editing window for a configuration that is typed with a metatype description.

+

In practice, this is a powerful model that provides a lot of configurability for your components with easy editing but getting it all right is not trivial. To make this easier, bnd has made it ease to use configurations.

+

In this model, configurations are declared in an interface. For example, the following interface defines a simple message:

+
interface Config {
+  String message(); // message to give
+}
+
+ +

To create a component that can work with this config, we need to designate that interface as the configuration interface for a component.

+
@Component(designate=Config.class)
+public class BasicComponent {
+    Config config;
+
+    @Activate void activate(Map<String,Object> props) {
+       config = Configurable.createConfig(props);
+       System.out.println("Hi " + config.message());
+    }
+
+    @Deactivate void deactivate() {
+       System.out.println("Bye " + config.message());
+    }
+}
+
+ +

This is an immediate component because it does not implement a service interface. It also requires a configuration because we have not specified this explicitly. When you use designate (or designateFactory) the default becomes require. This means that your component will only be created when there is actually configuration for it set.

+

To run this component, make sure you have the Felix Webconsole running and the MetaType service installed. In the Webconsole, you can click on +'''Configuration''', your component should be listed on this page. By Clicking on the component with the name '''Basic Component Config''' you get an editor window.

+

The editor is aware of the proper types, it uses the [[MetaType]] standard to describe the properties. bnd uses the type information on the interface as well as the optional Metadata annotations to create a rich description that allows the web console to provide a good editor.

+

You can fill in the message in the ''Message'' field. If you save the editor, your component prints the message with "Hi" in front of it. Deleting the configuration will print the message with "Bye".

+

If you change the message, you will see that the component is first deactivated and then reactivated again. This is the only possibility for the SCR because the component has not implemented a modified method. Adding the following method will change this, now changes to the configuration are signaled to the component and the component can continue to work. This is more complicated then recycling the component but it can create a more optimized system.

+
@Modified
+void modified( Map<String,Object> props) {
+  // reuse activate method
+  activate(props);
+}
+
+ +

It is also possible to take advantage of the configuration factories. In this model

+

An example, that implements a simple socket server on a configurable port and returns a message when a telnet session is opened to that port can be found on Github.

+ + diff --git a/org.bndtools.help/docs/chapters/210-metatype.html b/org.bndtools.help/docs/chapters/210-metatype.html new file mode 100644 index 0000000000..bdac990024 --- /dev/null +++ b/org.bndtools.help/docs/chapters/210-metatype.html @@ -0,0 +1,219 @@ + + + + +Metatype + + + +

Metatype

+

The OSGi Metatype specification provides a language to describe configuration information in an XML file. However, XML is cumbersome to use and eXtreMeLy error prone, and refactoring often finds it hard to change references in XML text files. Especially with DS components managing the relations can be complex, see Components

+

For this reason, bnd provides annotations to define the XML based on a ''configuration'' interface. For example, the following interface defines a simple metatype:

+
  package com.acme;
+  import aQute.bnd.annotation.metatype.*;
+
+  @Meta.OCD interface Config {
+    int port();
+  }
+
+ +

To turn this into an XML file, the bnd file must contain:

+
  -metatype: *
+
+ +

The wild card will search through the whole bundle but it is possible to limit this to a restricted set of packages to speed up the processing. For example:

+
  -metatype: *Metatype*, com.libs.metatypes
+
+ +

If the previous Config interface is present in the output, the output will also contain an XML file at OSGI-INF/metatype/com.acme.Config.xml. This file will look as follows:

+
  <metatype:MetaData 
+    xmlns:metatype='http://www.osgi.org/xmlns/metatype/v1.1.0'>
+    <OCD 
+      name='Config' 
+      id='aQute.metatype.samples.Config' 
+      localization='aQute.metatype.samples.Config'>
+      <AD 
+        name='Port' 
+        id='port' 
+        cardinality='0' 
+        required='true' 
+        type='Integer'/>
+    </OCD>
+    <Designate pid='aQute.metatype.samples.Config'>
+      <Object ocdref='aQute.metatype.samples.Config'/>
+    </Designate>
+  </metatype:MetaData>
+
+ +

bnd leverages the rich type information the Java class files contain. It inspects the returns types and from this it automatically calculates the AD type as well as the cardinality. For example, a method like:

+
   List<Integer> ints()
+
+ +

Provides an AD of:

+
    <AD 
+      name='Ints' 
+      id='ints' 
+      cardinality='-2147483648' 
+      required='true' 
+      type='Integer'/>
+
+ +

Naming

+

bnd attempts to make the names of the OCD and AD human readable by un-camel-casing the id. This means that it uses the upper cases in the id to decide where to use spaces. It also attempts to replace '_' characters with spaces and removes '$'. If the result is not what is wanted, the name can always be explicitly set with the AD.name() field.

+

The id of the properties is by default derived from the method name. The name space of methods is restricted by the Java language both in character set as well as by the reserved keywords. Therefore, bnd mangles the name of the method to allow the method name to be adapted to common practices in proeprty names.

+ +

For example:

+
  @OCD
+  interface Config {
+    String _password(); // .password - will not be registered as a service
+    String $new();      // new - keyword
+  }
+
+ +

@Meta.OCD

+

The OCD annotation is necessary to know that an interface is a Metatype interface. It should be used preferably without any parameters (they all have good defaults). However, each default is possible to override. The following table discusses the fields:

+

|name|String|A human readable name of the component, can be localized if it starts with a % sign. The default is a string derived from the id where _, $, or camel casing is used to provide spaces.| +|id|String|The id of the OCD, this will also be used for the pid of the Designate element.| +|localization|String|The localization id of the metatype. This refers to a properties file in the OSGI-INF/i10l/.properties file that can be augmented with locale information.| +|description|String|A human readable description that can be localized. Default is empty.| +|factory|String|Will treat this OCD as intended to be for a factory configuration. The default is false|

+

@Meta.AD

+

The AD is an optional annotation on methods of a OCD interface. The annotation makes it possible to override the defaults and provide extra information.

+

|name|String|A human readable name of the attribute, can be localized if it starts with a % sign. The default is a string derived from the method name where , $, or camel casing is used to provide spaces.| +|id|String|The id of the attribute. By default this is the name of the method| +|description|String|A human readable description that can be localized. Default is empty.| +|type|String|The type of the attribute. This must be one of the types defined in the Metatype specification. By default the type will be derived from the return type of the method. If no applicable type can be found then the String type is used as final default.| +|cardinality|int|The cardinality of the attribute. If this is negative its absolute indicates maximum number of elements in a Vector. If it is positive it indicates the maximum number of values in an array. Zero indicates a scalar. If not provided, bnd will calculate the cardinality based on the return type. Collections will have a negative large value and arrays have a positive large value.| +|min|String|The minimum value allowed for this attribute. There is no default.| +|max|String|The maximum value allowed for this attribute. There is no default.| +|deflt|String|The default initial value. The default for this is an empty String| +|required|boolean|Indicates if this attribute is required. The default is that attributes are required.| +|optionLabels|String[]|Labels for any values specified in optionValues. The default value is unset if there are no optionValues are defined. If these are defined, then the labels are calculated from the values by making , $ into spaces and providing spaces between camel cased words in the values.| +|optionValues|String[]|Optional values. If this field is not set and the return type is an enum type then the values are calculated from the enum members.|

+

Runtime conversions

+

The type support the OSGi Metatype specification is limited to the primitives and strings. So what happens when you use another type? During the build phase, bnd will revert to a 'String' Metatype type. This means that those special types are going to be strings in the dictionary. However, the aQute.bnd.annotation.metatype package contains a helper class that simplifies the usage of properties in runtime.

+

It has a @createConfigurable(Class<T> c, Map<?,?> props). This method returns an object that implements the given configuration interface. The implementation of these methods uses the properties to provide a value. That is, calling the method abc() on this interface will attempt to find the property "abc". It will then use the actual return type of the method to do conversion from the type in the properties to the return type. This takes generic information into account when present.

+

For example:

+
  @Meta.OCD
+  interface Config {
+    URI[] uris();
+  }
+
+  public void updated( Map<String,Object> props) {
+    config = Configurable.createConfigurable(Config.class,props);
+    for ( URI URI : config.uris() ) {
+      ...
+    }
+  }
+
+ +

The Metatype specification does not support URIs, so how does this work? Lets first look at the AD:

+
    <AD 
+     name='uris' 
+     id='uris' 
+     cardinality='2147483647' 
+     required='true' 
+     type='String'/>
+
+ +

Any editor will therefore put an array of strings (String[]) in the properties. When the proxy gets the string, it will therefore have to convert from the String[] -> URI[]. In this case, the URI has a String constructor and is used to do the conversion from String to URI. The converter can handle general array to collection, collection to array, and as indicated, any conversion to an object that has a String constructor.

+

For convenience there are a number of built int conversions provided that cannot leverage the String constructor:

+ +

Example

+

The following example shows a very simple metatype configuration interface:

+
  package aQute.metatype.samples;
+  import aQute.bnd.annotation.metatype.Meta.*;
+  @OCD
+  public interface Config {
+    int port();
+  }
+
+ +

If the bnd.bnd file contains:

+
  -metatype: *
+
+ +

Then bnd will detect this class as a Metatype and it generates the following XML in `OSGi-INF/metatype/aQute.metatype.samples.Config.xml

+
  <?xml version='1.0'?>
+  <metatype:MetaData 
+     xmlns:metatype='http://www.osgi.org/xmlns/metatype/v1.1.0'>
+    <OCD 
+      name='Config' 
+      id='aQute.metatype.samples.Config'   
+      localization='aQute.metatype.samples.Config'>
+      <AD 
+        name='Port' 
+        id='port' 
+        cardinality='0' 
+        required='true' 
+        type='Integer'/>
+    </OCD>
+    <Designate pid='aQute.metatype.samples.Config'>
+      <Object ocdref='aQute.metatype.samples.Config'/>
+    </Designate>
+  </metatype:MetaData>
+
+ +

As usual, XML does an outstanding job in obfuscating the interesting parts. If you're using the Apache Felix Webconsole (and if not, why not?) then you can edit this metatype on the web.

+

This metatype can now be used in a simple example that prints the port number:

+
  package aQute.metatype.samples;
+  import java.util.*;
+  import org.osgi.service.cm.*;
+  import aQute.bnd.annotation.component.*;
+  import aQute.bnd.annotation.metatype.*;
+
+  @Component(properties="service.pid=aQute.metatype.samples.Config")
+  public class Echo implements ManagedService {
+
+    public void updated(Dictionary properties) 
+      throws ConfigurationException {
+      if ( properties != null ) {
+        Config config = Configurable.createConfigurable(
+          Config.class, properties);
+        System.out.println(config.port());
+      }
+    }
+  }
+
+ +

The editor can get quite rich with the metatype information.

+

This information came from the following Meta interface:

+
  interface SampleConfig {
+    String _secret();
+    String $new();
+    String name();
+    enum X { A, B, C; }
+    X x();
+    int birthYear();
+    URI uri();
+    URI[] uris();
+    Collection<URI> curis();
+    Collection<Integer> ints(); // fails on webconsole
+  } 
+
+ +

Though this is a big savings over normal fudging with properties, it gets better. The metatyping is fully integrated with DS. In this example, we're using DS to register the Managed Service but this is not necessary because DS will automatically use the name of a component as the PID. So with a component life can be as easy as:

+
  @Component(designate=Config.class)
+  public class Echo2 {  
+    @Activate
+    void activate(Map<?,?> properties) throws ConfigurationException {
+      Config config = Configurable.createConfigurable(
+         Config.class, properties);
+      System.out.println(config.port());
+    }
+  }
+
+ +

No more strings. Components and metatypes are extensively explained in Components.

+

Also see the articles on Service Components and Debugging.

+ + diff --git a/org.bndtools.help/docs/chapters/220-contracts.html b/org.bndtools.help/docs/chapters/220-contracts.html new file mode 100644 index 0000000000..aa96c22749 --- /dev/null +++ b/org.bndtools.help/docs/chapters/220-contracts.html @@ -0,0 +1,69 @@ + + + + +Contracts + + + +

Contracts

+

The OSGi has a very elegant package version model there are still many that think this is too much work. They do not want to be bothered by the niceties of semantic versions and just want to use, let's say, Servlet 3.0. For those people (seemingly not interested in minimizing dependencies) the OSGi Alliance came up with Portable Java Contracts. A contract allows you to:

+ +

This very common pattern is called the Capability/Requirement (C/R) model in OSGi, it underlies all of its dependency concepts like Import/Export package and others; it forms the foundation of the OSGi Bundle Repository. If you ever want to know what is happening deep down inside a framework than look at the Wiring API and you see the requirements and capabilities in their most fundamental form. +You can find more information about the Portable Contracts in this blogpost.

+

Capabilities declare a set of properties that describe something that a bundle can provide. A Requirement in a bundle has a filter that must match a capability before this bundle can be resolved. To prevent requirements matching completely unrelated capabilities they must both be defined in the same namespace,, where the namespace then defines the semantics of the properties. Using the C/R model we were able to describe most of the OSGi dependencies with surprisingly few additional concepts. For a modern OSGi resolver there is very little difference between the Import-Package and Require-Bundle headers.

+

So how do those contracts work? Well, the bundle that provides the API for the contract has a contract capability. What this means is that it provides a Provide-Capability clause in the osgi.contract namespace, for example:

+
Bundle P:
+  Provide-Capability: 
+     osgi.contract;
+      osgi.contract=JavaServlet;
+      uses:="javax.servlet,javax.servlet.http";
+      version:Version="3.0"
+  Export-Package: javax.servlet, javax.servlet.http
+
+ +

This contract defines two properties, the contract name (by convention this is the namespace name as property key) and the version. A bundle that wants to rely on this API can add the following requirement to its manifest: +Bundle R:

+
  Require-Capability: osgi.contract;
+    filter:="(&(osgi.contract=JavaServlet)(version=3.0))"
+  Import-Package: javax.servlet, javax.servlet.http
+
+ +

Experienced OSGi users should have cringed at these versionless packages, cringing becomes a gut-reaction at the sight of versionless packages. However, in this case it actually cannot harm. The previous example will ensure that Bundle P will be the class loader for the Bundle R for packages javax.servlet, javax.servlet.http. The magic is in the uses: directive, if the Require-Capability in bundle R is resolved to the Provide-Capability in bundle P then bundle R must import these packages from bundle P.

+

bnd has support for this. First bnd can make it easier to create the Provide Capability header since the involved packages are in the Export-Package as well as in the Provide-Capability headers. The do-no-repeat-yourself mantra dictated an ${exports} macro. The ${exports} macro is replaced by the exported packages of the bundle, for example:

+

Bundle P:

+
  Provide-Capability: \
+    osgi.contract;\
+      osgi.contract=JavaServlet;\
+      uses:="${exports}";\
+      version:Version="3.0"
+  Export-Package: javax.servlet, javax.servlet.http
+
+ +

Furthermore there is the -define-contract instruction which can be applied in order to define a contract which is not available on the build path.

+

That said, the most extensive help you get from bnd is for requiring contracts. Providing a contract is not so cumbersome, after all you're the provider so you have all the knowledge and the interest in providing metadata. Consuming a contract is less interesting and it is much harder to get the metadata right. In a similar vein, bnd analyzes your classes to find out the dependencies to create the Import-Package statement, doing this by hand is really hard (as other OSGi developing environments can testify!).

+

So to activate the use of contracts, add the -contract instruction:

+
bnd.bnd:
+  -contract: *
+
+ +

This instruction will give bnd permission to scan the build path for contracts, i.e. Provide-Capability clauses in the osgi.contract namespace. These declared contracts cause a corresponding requirement in the bundle when the bundle imports packages listed in the uses clause. In the example with Bundle R, bnd will automatically insert the Require-Capability header and remove any versions on the imported packages.

+

Sometimes the wildcard for the -contract instruction can be used to limit the contracts that are considered. Sometimes you want a specific contract but not others. Other times you want to skip a specific contract. The following example skips the 'JavaServlet' contract: +bnd.bnd:

+
  -contract: !JavaServlet,*
+
+ +

Further reading

+ + + diff --git a/org.bndtools.help/docs/chapters/230-manifest-annotations.html b/org.bndtools.help/docs/chapters/230-manifest-annotations.html new file mode 100644 index 0000000000..534e5fc5b8 --- /dev/null +++ b/org.bndtools.help/docs/chapters/230-manifest-annotations.html @@ -0,0 +1,273 @@ + + + + +Bundle Annotations + + + +

Bundle Annotations

+

Manifest headers are challenging to keep in sync with the code in the bundle. It often takes several attempts to get all the details correct.

+

One of the goals of bnd is to eliminate such issues by relying on Java's type system to express the semantics of OSGi metadata.

+

To address this bnd pioneered manifest annotations which evolved into OSGi's bundle annotations. A bundle annotation is used to express metadata that cannot otherwise be derived from code.

+

A bundle annotation is applied to a type or package and when processed by bnd will cause the generation of corresponding manifest headers (and header clauses). Generating manifest headers from type safe structures is far less likely to result in errors, simplifies the developers life and is more conducive to code refactoring which won't result in information loss.

+

The following example shows the preferred way to handle package versioning by applying the @Export and @Version bundle annotations to com/acme/package-info.java.

+
@Export
+@Version("1.3.4")
+package com.acme;
+
+ +

which results in the manifest header:

+
Export-Package: com.acme;version="1.3.4"
+
+ +

META-INF/services Annotations

+

Some developers do not want to rely on the additional dependency of bnd/OSGi annotations. For this reason, it is possible to also apply the annotations textually in comments to the files in the META-INF/services. +This trick avoids a compile time dependency. These Service Loader files have the name of a Service Loader service and contain the names of the implementation classes. One fully qualified name per line.

+

To make these annotations in the comments more readable, it is possible to import the fully qualified name of the annotation.

+
META-INF/services/com.example.ServiceType:
+
+   #import aQute.bnd.annotation.spi.ServiceProvider
+   #@ServiceProvider(resolution:=optional)
+   com.example.impl.Impl2
+   #@ServiceProvider(attribute:List<String>="a=1, b=2")
+   com.example.impl.Impl1
+
+ +

The processing is identical to the normal class based annotation processing. The #class macro will be set to the implementation class. The #value will be set in all cases to the service type unless overridden.

+

This behavior can be controlled with the -metainf-services instruction. Default is annotation which processes the textual annotations above, while the other convenience strategy auto automatically creates Provide-Capability headers for services without any textual annotations.

+
+ +

While the above is a compromise, clearly using the real class annotation is far superior:

+ +

The analysis of these files happens after the analyzer plugins have been run. These plugins can add files if so desired.

+

Since the annotations & imports happen in the comments, it is not possible to diagnose any errors. If the comment does not match its regular expression, it will be silently ignored.

+

@Requirement & @Capability Annotations

+

Though Java class files contain enough information to find code dependencies, there are many dependencies that are indirect. OSGi extenders for instance are often a requirement to make a bundle function correctly but often client bundles have no code dependency on the extender. For example, Declarative Services (DS) went out of its way to allow components to be Plain Old Java Objects (POJO). The result is that resolving a closure of bundles starting from a DS client bundle would not drag in the Service Component Runtime (SCR), resulting in a satisfied but rather idle closure.

+

The solution was to describe the requirement for the runtime SCR dependency using Requirements and Capabilities. But again, writing these complex clauses in the manifest by hand is both error prone and painful.

+

The @Requirement and @Capability annotations were designed to address this issue. These annotations can be used to create custom bundle annotations, described later on. Let's discuss the DS example.

+

Recent DS specifications require implementations to provide the following capability:

+
Provide-Capability: osgi.extender;
+    osgi.extender="osgi.component";
+    version:Version="1.4.0";
+    uses:="org.osgi.service.component"
+
+ +

While this provides a capability that can be required, we need a requirement to be generated from client code that uses DS. Enter recent versions of DS annotations which are meta-annotated with @RequireServiceComponentRuntime, a custom bundle annotation which is specified as:

+
@Requirement(
+    namespace = ExtenderNamespace.EXTENDER_NAMESPACE,
+    name = ComponentConstants.COMPONENT_CAPABILITY_NAME,
+    version = ComponentConstants.COMPONENT_SPECIFICATION_VERSION)
+@Retention(RetentionPolicy.CLASS)   
+public @interface RequireServiceComponentRuntime { }
+
+ +

If you inspect the source code for @Component you'll find it is meta-annotated with @RequireServiceComponentRuntime. When you write a DS component using @Component as follows

+
@Component
+class Foo { ... }
+
+ +

and because of the inherent bundle annotations it holds, the following manifest clause is generated

+
Require-Capability: \
+    osgi.extender; \
+    filter:="(&(osgi.extender=osgi.component)(version>=1.4.0)(!(version>=2.0.0)))"
+
+ +

The invisible link created between user code and the indirect requirement is a powerful mechanism that enables automatic validation of a bundle closure.

+

The actual requirement filter: directive is constructed from an AND of the filter(), name(), and version() annotation methods. All fields are optional. The name field will create an assertion that the given namespace equals the value of the name() annotation method. For example, if the namespace is com.example.foo and the name() method has the value bar then the filter is (com.example.foo=bar). If a version is specified, it will be expanded to a filtered version-range expression. The convention of using the namespace name as the property key is commonly used in OSGi specification. For example, the filter (osgi.wiring.package=com.example.foo) is the filter for an Import-Package com.example.foo while osgi.wiring.package is the namespace for the packages.

+

For example:

+
@Requirement(namespace = "NAMESPACE", name="NAME", version="1.2.3", filter="(foo=${#foo})")
+@Retention(RetentionPolicy.CLASS)
+public @interface RequireSomething {
+    int foo();
+}
+
+@RequireSomething(foo=3)
+class Foo {...}
+
+ +

This will generate a manifest Require-Capability header of:

+
Require-Capability: \
+    NAMESPACE; \
+    filter:="(&(foo=3)(NAMESPACE=NAME)(version>=1.2.3)(!(version>=2.0.0)))"
+
+ +

Arbitrary Manifest Headers

+

Bundle annotations aren't just about package versioning or requirements and capabilities. They are about lifting metadata out of our code to avoid, among other things, error prone duplication of information. A common example is the bundle activator. Bundle Activators are require to be described in a manifest header. This association is not visible to refactoring tools and as such can easily end up out of sync.

+

The @Header annotation exists to address this problem.

+
package com.acme;
+
+@Header(name = Constants.BUNDLE_ACTIVATOR, value = "${@class}")
+public Activator implements BundleActivator { ... }
+
+ +

results in the manifest header:

+

Bundle-Activator: com.acme.Activator

+

Macros

+

You'll note the string ${@class} used in the above example. String fields in bundle annotations are processed through bnd's macro processor. This macro processor provides access to all default and builder macros. More info on bnd macros can be found in the macros chapter.

+

Bnd also provides access to certain key properties of the current processing state.

+ +

The @Header example above used the macro ${@class} which lifted the @class property holding the class name of the activator into the header to avoid having to duplicate it. This also means that refactoring the activator won't cause the manifest to get out of sync.

+

In the case that a bundle annotation is used as a meta annotation then the methods on the annotated annotation are available as macros as well with a name prefixed with #. That is, if the annotated annotation has a method foo(), then the macro ${#foo} can be used to refer to its value. See Accessor Properties for more details.

+

Custom Bundle Annotations

+

Certain bundle annotations have a second important use. We know that if applied to a type or package bundle annotations result in a clause in the manifest. However, many can be used as meta-annotations to a second annotation. The second annotation is considered a custom bundle annotation. The custom bundle annotation results in a manifest clause only when applied to a type or package.

+

This makes it possible to create an annotation for a subsystem. For example, an annotation @ASL_2_0 that sets the Bundle-License header to the Apache Software License version 2.0.

+
@BundleLicense(
+    name = "https://www.opensource.org/licenses/apache2.0.php",
+    link = "https://www.apache.org/licenses/LICENSE-2.0.html",
+    description = "Apache Software License 2.0")
+@interface ASL_2_0 {}
+
+// takes effect when applied to a type
+
+@ASL_2_0
+class Foo { ... }
+
+ +

Adding Attributes and Directives

+

When creating custom bundle annotations a common requirement is to make them parameterizable such that the values of the custom bundle annotation feed into the header clauses resulting from the bundle annotation applied to it (remember; a custom bundle annotation is meta-annotated with a bundle annotation**.)

+

OSGi specifies two annotations, @Attribute and @Directive, for this purpose. Any methods of the custom bundle annotation annotated with @Attribute or @Directive will result in those becoming additional attributes or directives respectively of the resulting header clause when a value is supplied.

+

Note: When bnd processes OSGi headers, it automatically ensures consistent ordering of attributes and directives within header clauses, with attributes appearing before directives and both groups sorted alphabetically. See OSGi Header Attribute and Directive Ordering for more details.

+
@Attribute
+

@Attribute allows you to add new or update existing attributes from the bundle annotation.

+
@Capability(namespace = "foo.namespace")
+@interface Extended {
+    @Attribute("foo.attribute") // this attribute enhances the @Capability
+    String value();
+}
+
+// usage
+
+@Extended("bar")
+class Foo {}
+
+ +

which results in the manifest header:

+

Provide-Capability: foo.namespace;foo.attribute=bar

+
@Directive
+

@Directive behaves similarly; with some caveats. You can add new or update existing directives for namespaces not defined by OSGi specifications.

+
@Capability(namespace = "foo.namespace")
+@interface Extended {
+    @Directive("foo.directive")
+    String value();
+}
+
+// usage
+
+@Extended("bar")
+class Foo {}
+
+ +

results in the manifest header:

+

Provide-Capability: foo.namespace;foo.directive:=bar

+

However, namespaces defined by OSGi specifications will be validated and will not accept directives which are not part of the spec unless they are prefixed with x-.

+
@Capability(namespace = "osgi.extender", name = "bar", version = "1.0.0")
+@interface Extended {
+    @Directive("foo")
+    String value();
+}
+
+// usage
+
+@Extended("bar")
+public class Foo {}
+
+ +

will result in an error:

+

Unknown directive 'foo:' for namespace 'osgi.extender' in 'Provide-Capability'. Allowed directives are [effective:,uses:], and 'x-*'.

+

It should be noted that it's possible to elide such errors using bnd's -fixupmessages instruction.

+

This next example however:

+
@Capability(namespace = "osgi.extender", name = "bar", version = "1.0.0")
+@interface Extended {
+    @Directive("x-foo")
+    String value();
+}
+
+// usage
+
+@Extended("bar")
+public class Foo {}
+
+ +

results in the manifest header:

+

Provide-Capability: osgi.extender;osgi.extender=bar;version:Version="1.0.0";x-foo:=bar

+

It should be noted that default values for methods annotated with @Attribute and @Directive are deemed to be for documentation purposes only and will not be emitted into resulting headers.

+

Accessor Properties

+

For more customisation options see chapter on Accessor Properties.

+

Where to find Bundle Annotations

+

OSGi bundle annotations can be found in the osgi.annotation (e.g. org.osgi:osgi.annotation:7.0.0) bundle.

+
<dependency>
+  <groupId>org.osgi</groupId>
+  <artifactId>osgi.annotation</artifactId>
+  <version>7.0.0</version>
+</dependency>
+
+ +

Bnd bundle annotations can be found in the biz.aQute.bnd.annotations (e.g. biz.aQute.bnd:biz.aQute.bnd.annotation:5.0.0) bundle.

+
<dependency>
+  <groupId>biz.aQute.bnd</groupId>
+  <artifactId>biz.aQute.bnd.annotation</artifactId>
+  <version>${bnd.version}</version>
+</dependency>
+
+ +

List of Bundle Annotations

+

OSGi Bundle Annotations:

+ +

Bnd Bundle Annotations:

+ + + diff --git a/org.bndtools.help/docs/chapters/235-accessor-properties.html b/org.bndtools.help/docs/chapters/235-accessor-properties.html new file mode 100644 index 0000000000..906adf7a17 --- /dev/null +++ b/org.bndtools.help/docs/chapters/235-accessor-properties.html @@ -0,0 +1,176 @@ + + + + +Accessor Properties + + + +

Accessor Properties

+

When working with custom bundle annotations one may find that @Attribute and @Directive have limitations in scenarios where multiple bundle annotations are added to a single custom bundle annotation because there are no discriminators expressing which bundle annotation to associate the attribute or directive; and it's likely that associating these with all bundle annotations produces unexpected or even incorrect results. Bnd provides a solution which takes advantage of its macro support during annotation processing.

+

Accessor Properties

+

When an annotation is meta-annotated with a bundle annotation the values and defaults of the host are loaded as properties, prefixed with #, into the macro processing scope. The effect is that these values are accessible using a macro pattern (like ${}).

+
@Capability(
+    name = "${#name}", // <-- accesses the hosts 'name()' value
+    namespace = "osgi.cdi.extension",
+    version = "${#version}"  // <-- accesses the hosts 'version()' value
+)
+@Requirement(
+    name = "osgi.cdi",
+    namespace = "osgi.implementation",
+    version = "1.0.0")
+@interface CDIExtension {
+    String name();
+    String version();
+}
+
+ +

Annotation methods may return several different types and they are converted to strings according to the following table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Return typeConversion
boolean, byte, char, double, float, int, long, shortString.valueOf()
java.lang.ClassClass.getName()
java.lang.EnumEnum.name()
java.lang.Stringas is (commas should be escaped with \)
array type whose component type is one of the preceding typesjoined by comma (,)
type satisfying Class.isAnnotation()omitted from available accessor properties
array type whose component type satisfies Class.isAnnotation()omitted from available accessor properties
+

It should be noted that if the resulting strings contain macro characters these will be interpreted by bnd's macro engine. This may produce unexpected results due to potentially nested macros. In this scenario steps must be taken to either escape these characters or that nesting is done to allow bnd to successfully process the result.

+

The annotated type as default

+

The return type Class<?> is particularly useful when it comes to making your code friendly to refactoring.

+
@Capability(
+    filter = "objectClass:List<String>='${#value}'",
+    namespace = "osgi.service",
+)
+@interface MyService {
+    Class<?>[] value();
+}
+
+// applied as
+
+@MyService(Bar.class)
+class Bar { ... }
+
+ +

What if you want the default to be the annotated class itself? Bnd made this possible by using a type which was unlikely to be a real argument. The type selected was java.lang.annotation.Targetbecause it is guaranteed to be accessible, is unlikely to be a real argument, will not require an additional dependency, and it's nomenclature proved the most expressive for the use case.

+
@Capability(
+    filter = "objectClass:List<String>='${#value}'",
+    namespace = "osgi.service",
+)
+@interface MyService {
+    Class<?>[] value() default Target.class;
+}
+
+// applied as
+
+@MyService
+class Bar { ... }
+
+ +

Instances of java.lang.annotation.Target.class found in the return value of Class<?> or Class<?>[] methods will be replaced by the annotated type prior to string conversion.

+

Cardinality

+

In order to control the cardinality of requirements generated by custom bundle annotations a convenience enum aQute.bnd.annotation.Cardinality is available as a method return type. The default value should be Cardinality.DEFAULT ensuring that if not set no directive will be emitted.

+
@Requirement(
+    attribute = {
+        aQute.bnd.annotation.Constants.CARDINALITY_MACRO
+    },
+    namespace = "osgi.service",
+)
+@interface RequireMyService {
+    Cardinality cardinality() default Cardinality.DEFAULT;
+}
+
+// applied as
+
+@RequireMyService(cardinality = Cardinality.MULTIPLE)
+class Bar { ... }
+
+ +

Note: It is recommended to use the macro constant aQute.bnd.annotation.Constants.CARDINALITY_MACRO crafted specifically for handling the cardinality directive. It should also be noted that during macro processing the enum name() will be converted to lower case.

+

Resolution

+

In order to control the resolution of requirements generated by custom bundle annotations a convenience enum aQute.bnd.annotation.Resolution is available as method return type. The default value should be Resolution.DEFAULT ensuring that if not set no directive will be emitted.

+
@Requirement(
+    attribute = {
+        aQute.bnd.annotation.Constants.RESOLUTION_MACRO
+    },
+    namespace = "osgi.service",
+)
+@interface RequireMyService {
+    Resolution resolution() default Resolution.DEFAULT;
+}
+
+// applied as
+
+@RequireMyService(resolution = Resolution.OPTIONAL)
+class Bar { ... }
+
+ +

Note: It is recommended to use the macro constant aQute.bnd.annotation.Constants.RESOLUTION_MACRO crafted specifically for handling the resolution directive. It should also be noted that during macro processing the enum name() will be converted to lower case.

+

Effective

+

In order to control the effective time of a requirement generated by custom bundle annotations a method called effective with a return type of String can be used in conjunction with the macro constant aQute.bnd.annotation.Constants.EFFECTIVE_MACRO. The default value should be the empty string ("") ensuring that if not set no directive will be emitted.

+
@Requirement(
+    attribute = {
+        aQute.bnd.annotation.Constants.EFFECTIVE_MACRO
+    },
+    namespace = "osgi.service",
+)
+@interface RequireMyService {
+    String effective() default "";
+}
+
+// applied as
+
+@RequireMyService(effective = "active")
+class Bar { ... }
+
+ +

Uses

+

In order to control the uses constraints of a requirement generated by custom bundle annotations a method called uses with a return type of Class<?>[] can be used in conjunction with the macro constant aQute.bnd.annotation.Constants.USES_MACRO. The default value should be an empty array ({}) ensuring that if not set the directive will not be emitted.

+
@Requirement(
+    attribute = {
+        aQute.bnd.annotation.Constants.USES_MACRO
+    },
+    namespace = "osgi.service",
+)
+@interface RequireMyService {
+    Class<?>[] uses() default {};
+}
+
+// applied as
+
+@RequireMyService(uses = {com.acme.Foo.class, org.bar.Bar.class})
+class Bar { ... }
+
+ +

+ + diff --git a/org.bndtools.help/docs/chapters/240-spi-annotations.html b/org.bndtools.help/docs/chapters/240-spi-annotations.html new file mode 100644 index 0000000000..65eab77917 --- /dev/null +++ b/org.bndtools.help/docs/chapters/240-spi-annotations.html @@ -0,0 +1,56 @@ + + + + +SPI Annotations + + + +

SPI Annotations

+

Writing Java libraries which support OSGi does not typically require more than generating proper OSGi metadata. bnd helps accomplish with minimal effort on the part of developers. One issue that remains somewhat complex is properly handling the use of the Java SPI such that it works seamlessly in OSGi and avoiding the need for custom code to accomplish a similar goal. OSGi defines the Service Loader Mediator Specification but applying it requires a significant amount of manifest metadata.

+

SPI Annotations

+

bnd defines a set of SPI annotations which provide a simple solution for developers who wish to maintain OSGi friendly libraries.

+

@ServiceConsumer

+

The Java SPI use cases are broken into two groups; providers and consumers. The @aQute.bnd.annotation.spi.ServiceConsumer annotation is used in consumer code to express a requirement on an SPI service type adding the appropriate OSGi metadata to the manifest.

+
@ServiceConsumer(
+    value = JsonProvider.class
+)
+public abstract class JsonProvider {
+    public static JsonProvider provider() {
+        for (JsonProvider provider : ServiceLoader.load(JsonProvider.class)) {
+            return provider;
+        }
+        throw new JsonException("provider not found");
+    }
+    ...
+}
+
+ +

@ServiceConsumer also grants the developer control in defining many facets of the generated OSGi requirements such as cardinality, effective time and resolution.

+

@ServiceProvider

+

The provider side is supported by the @aQute.bnd.annotation.spi.ServiceProvider annotation. It is used to express a capability for a given SPI service type adding all the appropriate OSGi manifest metadata.

+
@ServiceProvider(JsonProvider.class)
+public class JsonProviderImpl extends JsonProvider {
+    ...
+}
+
+ +

@ServiceProvider also grants the developer control in defining many facets of the generated OSGi requirements and capabilities such as additional attributes and directives (attributes becoming service properties), cardinality, effective time, resolution, and package uses.

+

OSGi Services

+

The @ServiceProvider annotation will automatically result in publishing OSGi services for each provider discovered. Any attributes (excluding directives) specified on the annotation will be automatically added as OSGi service properties.

+
@ServiceProvider(
+    value = JsonProvider.class,
+    attribute = {
+        "colors:List<String>='blue,green,red'"
+    }
+)
+public class JsonProviderImpl extends JsonProvider {
+    ...
+}
+
+ +

An osgi.service capability is also generated for each provider type.

+

Service Descriptor Files

+

An additional feature provided by bnd is the ability to manage the service descriptor files (a.k.a. META-INF/services/*) automatically for any osgi.serviceloader capabilities it finds having the register: directive containing a provider's fully qualified class name. The register: directive is automatically generated from all instances of @ServiceProvider.

+ + diff --git a/org.bndtools.help/docs/chapters/250-resolving.html b/org.bndtools.help/docs/chapters/250-resolving.html new file mode 100644 index 0000000000..ad80c97ce6 --- /dev/null +++ b/org.bndtools.help/docs/chapters/250-resolving.html @@ -0,0 +1,314 @@ + + + + +Resolving Dependencies + + + +

Resolving Dependencies

+

OSGi's Best Kept Secret

+

This Application Note is about resolving in OSGi. The OSGi Framework has always used a resolver to wire a given set of bundles together, ensuring that only valid wires are made. However, the same OSGi resolver can also be used to select a set of bundles from a much larger set. This application note discusses this secondary usage.

+

The resolver model is based on technology developed in OSGi since 2006 with RFC-0112 Bundle Repository. This RFC laid out a model that was gradually implemented in the OSGi specifications and for which many tools were developed. Resolving automates a task that is mostly done manually today.

+

What Problem is Being (Re)Solved?

+

The pain that the resolver solves is well known to anybody that builds application from modules, the so called assembly process. All developers know the dreadful feeling of having to drag in more and more dependencies to get rid of Class Not Found errors when the application starts (or after running for an hour). For many, Maven was a significant improvement because it made this process so much easier because dependencies in Maven are transitive. If you depend on some artefact, then this artefact drags in its own dependencies to the runtime.

+

Unfortunately, the Maven dependency model has limitations for a number of reasons. Though it undeniably has become easier to get a result, the result is often littered with unnecessary or wrong artefacts. Often application developers have no real understanding what is in their runtime.

+

These are the causes:

+ +

The result is that all too often the class path of the final application is littered with never used byte codes and/or overlapping packages that came from artefacts with different versions. If the customer could see the mess the average class path is they would run away screaming.

+

Establishing the perfect class path for an application is a process for which the human mind is extremely badly suited and the transitive model of Maven has too many sharp edges. The resolver provides an alternative model that focuses on looking at the whole solution space instead of having to live with the (sometimes arbitrary) decisions of developers or of deeply nested transitive dependencies.

+

Principles

+

image

+

The design of the resolving model is quite simple. It consists of the following entities:

+ +

Resolving in this App note is therefore the process of constructing an application out of resources. Resolving takes a list of initial requirements, a description of the system capabilities, and one or more repositories. It will use the list of initial requirements to find resources in the repository that provide the required capabilities. Clearly, these resources have their own requirements, retrieving applicable resources is therefore a recursive process. A resolver will find either a solution consisting of a set of resources where all requirements are satisfied or that there is no solution.

+

It is important to realise that a resource and its capabilities and requirements are descriptions. They provide a formal representation of an external artefact. Since these formal representations can be read by a computer, we can calculate a closure of resources that, when installed together, have only resources where all their mandatory requirements are satisfied by the resources in the closure.

+

Core Namespaces

+

Although the OSGi specifications started out with a set of headers that each had their own semantics, over time the specification migrated fully to the more simple and formal model of Resources, Capabilities, and Requirements. Since the function of the legacy headers were still needed, it was necessary to map these legacy headers to the formal model. This resulted in a number of OSGi core namespaces.

+ +

Each namespace defines the names of the properties and their semantics. For the OSGi namespaces, there are classes like org.osgi.framework.namespace.IdentityNamespace that contain the details of a namespace.

+

Example Resource Model

+

To make the model more clear let's take a closer look to a simple bundle com.example.bundle that exports package com.example.pe and imports a package com.example.pi. When the bundle is installed it will require that some other bundle, or the framework, provides package com.example.pi. We can describe this bundle then as follows:

+
 Resource for bundle com.example.bundle
+   capabilities:
+     osgi.wiring.identity;  osgi.wiring.identity=com.example.bundle
+     osgi.wiring.bundle;    osgi.wiring.bundle=com.example.bundle
+     osgi.wiring.host;      osgi.wiring.host=com.example.bundle
+     osgi.wiring.package;   osgi.wiring.package=com.example.pe
+   requirements:
+     osgi.ee;               filter:="(&(osgi.ee=JavaSE)(version=1.8))"
+     osgi.wiring.package;   filter:='(osgi.wiring.package=com.example.pi)'
+
+ +

Who Wants to Provide That Gibberish???

+

Clearly, an Export-Package: com.example.pe is a bit easier to read than the corresponding capability, let alone the filter in the requirement. This is especially true when the versions are taken into account, with the assertion of the version range the filters become quite unreadable. Clearly, if this had to be maintained by human developers then a model like Maven would be far superior. Fortunately, almost all of the metadata that is needed to make this work does not require much extra work from the developer. For example, the bnd tool that is available in Maven, Gradle, Eclipse, Intellij and others can easily analyse a JAR file and automatically generate the requirements and capabilities based on the source code.

+

In certain cases it is necessary to provide requirements and capabilities that bnd cannot infer. However, Manifest annotations support in bnd can be used to define an annotation that will add parameterised requirements to the resource.

+

Really, when you use an adequately appointed toolchain (like Bndtools) none of this gibberish is visible to normal developers unless they have a special case. The gibberish is left to the tools that prefer gibberish over natural language.

+

How to Write Resolvable Bundles

+

For a bundle to be a good citizen in a resolution it suffices to follow the standard rules of good software engineering. However, since there is so much software out there that does not follow these rules, a short summary.

+ +

To see the requirements and capabilities of a bundle Bndtools has a special Resolution view. This shows the requirements and capabilities of a selected JAR file or a bnd.bnd file.

+

+

This view uses a number of icons to represent the requirements/capabilities. You can hover over them to see further details.

+ +

Developers that are keen on developing good bundles should pay close attention to this pane.

+

Resolving

+

Resolving

+

The previous diagram adds the resolver to the earlier diagram of the basic model. It adds the following entities:

+ +

An important variable in the resolving process is effective which defines the effectiveness under which the resolve operation is performed. The resolver will only look at requirements that it deems effective. The default effectiveness is resolve. The effectiveness active is a convention commonly used for situations that do not need to be resolved by the OSGi framework but are relevant in using the resolver for assembling applications.

+

Repositories

+

A repository is a collection of resources. This could be Maven Central or it could be a single bundle. That said, neither is a good idea in practice. The repository is the scope of the resolution. Only resources in the repository can be selected. Although the naive idea is to make the scope as large as possible to let the computer do the work, it is much better to curate the repository.

+

There are many reasons why you need a curated repository but basically it comes down is the GIGO principle: garbage is garbage out. Another reason is running time. The resolver gets overwhelmed quickly when there are too many alternatives for a requirement. Resolving is an NP complete problem and this means that the resolution time quickly becomes very long when a lot of alternatives need to be examined.

+

Available Repositories

+

The bnd toolchain provides OSGi Repository access for many popular repository formats.

+ +

Since bnd has an extensive library to parse bundles and generate the resources it is relatively easy to parse bundles in other ways. For example, there is a Maven plugin that can generate an OSGi index.

+

Managing Repositories

+

A repository generally represents a release of a software product. Many developers publish an OSGi Repository XML to allow the resolver access to the metadata of their bundles, for example Knopflerfish produces an OSGi XML Repository with all their bundles.

+

This model is in contrast with Maven Central and most other Maven repositories. These repositories are designed to contain everything that was ever released. An OSGi repository is more the content of a specific release. Since it generally only contains a specific release, it will disallow the resolver to use any unwanted resources.

+

Workspace Repository

+

A natural repository is the bnd workspace since a workspace is a collection of related projects. Since these projects are build together it is trivial to keep them compatible. The metadata burden can be mitigated by sharing metadata between these related projects. For example, in bnd all bundles share the same version. Although this might sometimes release unchanged bundles under a newer version, the only cost is a bit of disk space. A small price to pay for an otherwise very error prone manual process. The Gradle build can release to a Nexus repository and automatically generate an index that can be used as repository.

+

Resolving in Bndtools

+

By far the best way to get experience with the resolver is using the bnd's bndrun files. Bndtools provides a friendly user interface that makes it easy to use the OSGi Resolver in an interactive way.

+

A bndrun describes the runtime configuration for an application. This can either be a standalone executable JAR or an application that should be hosted in a container like a Java EE server or Karaf. In this app note, the target is an executable JAR unless otherwise noted.

+

If you double click on the bndrun file, it opens a Run pane.

+

Run pane>

+

Even though most lists are hidden, the pane is already quite overwhelming. So let's go through the GUI and explain it one by one.

+

Core Runtime

+

Remember that a resolution is for a specific system, in our case an executable JAR. In the Core Runtime pane we specify the OSGi framework that will be used as well as the execution environment. The execution environment is from a list of Java VM versions and OSGi specifications.

+

+

The execution environment is used to calculate the system capabilities. That is, the system is treated as a single resource that provides the capabilities of the Framework as well as the capabilities of the OSGi defined execution environments. The system resource is always included in the resolution but can of course never be downloaded, it is the target environment.

+

Browse Repos

+

The Browse Repos is a list of the resources that are found in the active repositories. A search field makes it easy to find specific resources. For example, if you type in gogo it will list all Gogo bundles.

+

+

One or more resources from the Browse Repos list can be selected and then dragged to the Run Requirements list to the left. This adds an identity requirement to the set of initial requirements. You can also drag a resource to the Run Blacklist and Run Bundles lists.

+

Run Requirements

+

This is the main list to watch. It contains the set of initial requirements given to the resolver. The GUI makes it possible to add identity requirements and remove listed requirements. The easiest way is to use drag and drop form the Browse Repos list but it is also possible to use the green +, which opens a dialog from which bundles can be added directly from the selected repositories.

+

Run Requirements

+

Additional Components

+

There are some more panes that are useful but they will be handled in diagnosing problems. For reference, a short introduction to these panes.

+ +

Resolving

+

Taking the initial requirement it is possible to resolve by clicking on the Resolve button. This will show a rather large dialog window with the resolution.

+

Resolution

+

This dialog window is divided in three main parts:

+ +

If some of the listed optional resources are desired then they can be selected. Pressing the Update and Resolve button will restart the resolver but now with the selected optional resources as mandatory.

+

If the Finish button is pressed then the current required resources list is converted to the list of Run Bundles. You can inspect them at the right bottom of the bndrun editor window.

+

+

After a successful resolve you can either Run, Debug, or Export the bndrun file.

+

Debugging Resolving

+

So far the ideal process of happy resolves and satisfied bundles has been described. It is now necessary to leave this rosy world and descend into the world of failed resolves. Unfortunately, the provided diagnostic information when a resolve fails is quite low.

+

When a resolve fails it returns a cause but more often than not this is not the real cause. This is not some shortcoming from the current resolver but a fundamental logical problem. The simplest form of a resolution is if you have for example 3 numbers 1,4,8. You need to find the numbers that sum to 10 using only addition and subtraction. If you try out all the combination then you find that no combination works. A failure report could be that -3 is not available because the last tried permutation was 1+4+8. Clearly, before that permutation many other numbers were missing as well, the missing -3 just happened to be the last one ...

+

That said, there are a number of scenarios where the resolver does give a hint where the problem is.

+

Missing Requirement false

+

This rather obscure message indicates that the resolver tries to include a api bundle that was made unresolvable.

+

The api bundle may have a special Require-Capability header such as:

+
 Require-Capability: \
+  compile-only
+
+ +

This header creates a requirement that cannot be satisfied. There is nothing special with compile-only, it is just an unused namespace. It could also have been foo-bar.

+

In the resolver, you will see the following error chain:

+
 Unable to resolve <<INITIAL>> version=null:
+    missing requirement osgi.enroute.examples.resolver.missingapi.provider
+ ->  Unable to resolve osgi.enroute.examples.resolver.missingapi.provider version=1.0.0.201710041250:
+    missing requirement osgi.enroute.examples.resolver.missingapi.api; version=[1.0.0,1.1.0)
+ ->  Unable to resolve osgi.enroute.examples.resolver.missingapi.api version=1.0.0.201710041249:
+    missing requirement false]]
+
+ +

Note: Unfortunately, the output is blurred by a misguided attempt to make the output more concise. Because of this, the distinction between a bundle and a package is not very clear. Sadly you can only see the difference between a requirement for a bundle and a package by looking at the version. If this is a range then it is a package and if it is a version with a timestamp it is a bundle. (This works most of the time.) This is a bug in bnd and should be corrected.

+

As indicated, you really need to understand that the diagnostic is just the last path the resolver took. The osgi.enroute.examples.resolver.missingapi.provider bundle tries to find a provider for the package osgi.enroute.examples.resolver.missingapi.api and has found the osgi.enroute.examples.resolver.missingapi.api bundle. However, this API bundle has the impossible to satisfy compile-only requirement.

+

That said, it is better to look at the Missing Requirements list since this reports quite nicely what is missing.

+

+

The icon and the text more clearly indicate that it cannot resolve the osgi.enroute.examples.resolver.missingapi.api bundle due to the compile-only requirement.

+

Exporting the API package from the provider bundle will correct this case.

+

Compendium Bundle

+

Many developers compile against the compendium bundle to get the OSGi service API packages. Although compiling against an API bundle has advantages, using the compendium bundle in runtime is evil. Since the compendium bundle aggregates a large number of API packages it will have the tendency to unnecessarily constrain the versions of different APIs. That is, it blocks you from using newer APIs.

+

To make bundles that should not be used at runtime not resolvable there is the Run Blacklist list on the bndrun editor. This list contains bundles that should never be included in a resolution.

+

For example, we create a bundle that implements the Wire Admin service.

+
 public class MyService implements WireAdmin {
+      ...
+ }
+
+ +

This will cause a requirement for an exported package org.osgi.service.wireadmin. We therefore add the OSGi compendium bundle to the -buildpath. This then compiles fine.

+

However, the resolve will then drag in the OSGi compendium bundle.

+

image

+

If we look at the reasons when we select the compendium bundle we see that also the Configuration Admin imports from the compendium even though it actually might provide a higher version. (This maybe understandable but a really bad practice.)

+

+

To get rid of the compendium bundle we can drag and drop it to the Run Blacklist window. Any requirement in the Run Blacklist list will automatically exclude all bundles that are selected by that requirement.

+

You Are Sure There Is a Provider!

+

Sometimes the resolver can complain about a missing requirement but you are sure that it is in the repository. The first thing is to try to isolate the problem. Almost any problem can be solved if you remove the redundant parts. Quite often developers are trying to debug this situation in a complex large bndrun file and then get overwhelmed.

+

Just create a new bndrun file and only add the bundle you think should provide the resource to the Run Requires list, keep only one requirement, and then resolve. If this resolves fine then at least you know that that bundle can potentially resolve.

+

However, often you find that even on its own it does not resolve. In most case the error message and the Reasons list provide sufficient information to understand why it does not resolve.

+

It is still a mystery, try checking the Run Blacklist list. If it is not there, it might be time to raise a bug.

+

OSGi bnd Snapshot Viewer

+

Another tool for diagnosing potential issues in your OSGI framework (bundle, packages, services), the SCR info, configuration, log, and custom extensions is the OSGi bnd Snapshot Viewer.

+

The Source View

+

So far this App Note only visited the graphic user interface (GUI). However, bnd always keeps all information in simple properties files that can also edited as text. In the Run editor (that edits bndrun files) you can also select the Source view. Not all features of a bndrun file can be manipulated through the GUI. This section therefore shows what is in the source and it can be manipulated.

+

Notice that most instructions are merge properties. That is, bnd will first find all properties that start with the instruction name and merge their values together. For example, if you set -runrequires, -runrequires.foo, and -runrequires.bar bnd will use the combination of these properties. The order is the sorting order of the names used.

+ +

Augmenting Legacy Bundles

+

The problem with metadata is that it can also be wrong. Especially legacy bundles lack the proper metadata to inform the resolver that they provide a service or require an implementation of a specification. This is not a problem in runtime since these requirements are generally not used by the Framework, they are designed for using the resolver in selecting a closure of bundles. However, in certain cases adding a capability or a requirement to a bundle in the repository would simplify things. Clearly it is possible to wrap the legacy bundle but this is extremely cumbersome and can create confusion down the line.

+

Therefore, another method is to use the augments that the bnd repositories support. Augments can add capabilities and requirements to existing bundles in a repository. However, it can only do this for the interactive resolve process. When the OSGi Framework resolves a number of bundles it will never takes augments into account.

+

There are two different ways to add the augments.

+ +

In both cases the augments are described using the standard OSGi/bnd syntax. The syntax is not a beauty since it stretches what you can do with the OSGi header format. However, augmenting should really be a last resort so maybe it is not really bad that the syntax is cumbersome.

+

You can add an augment with the -augment instruction in the bndrun file.

+
 -augment PARAMETER ( ',' PARAMETER ) *
+
+ +

Augmenting is adding additional capabilities and requirements. When bnd resolves a project or bndrun file, it will read these instructions. Since -augment is a merge property you can also use additional keys like -augment.xyz.

+

The key of the PARAMETER is used for matching the Bundle Symbolic Name. It can contain the * wildcard character to match multiple bundles. The bundle symbolic name must be allowed as a value in a filter it is therefore not a globbing expression.

+

The following directives and attribute are architected:

+ +

To augment the repositories during a resolve, bnd will find all bundles that match the bundle symbolic name and fall within the defined range. If no range is given, only the bundle symbolic name will constrain the search. Each found bundle will then be decorated with the capabilities and requirements defined in the capability: and requirement: directive.

+

For example, we need to provide an extender capability to a bundle with the bundle symbolic name com.example.prime with version [1.2,1.3). In that case add the following instruction to the bndrun file.

+
 -augment.prime = \
+      com.example.prime; \
+           capability:='osgi.extender; \
+                osgi.extender=some.extender; \
+                version:Version=1.2@'
+
+ +

The capability: and requirement: directives follow all the rules of the Provide-Capability and Require-Capability headers respectively. For the resolver, it is as if these headers were specified in their manifests. Since these headers can contain semicolons and commas they must be quoted. bnd will allow double quotes inside normal quotes and vice versa when it is necessary to nest quotes.

+

First Time Curating a Repository

+

A workspace setup with bnd will generally provide a good start. However, when you need to grandfather in a lot of bundles from Maven Central then it is likely that you will need to spend some time to augment these bundles. This can be a depressing task since you'll find out how messy the world is. However, experience shows that once the repository is resolvable, maintaining it has very little overhead. Better, it tends to signal probems very early in the development process.

+

There are a number of (rudimentary) functions in the command line version of bnd that might be useful. Unfortunately, the commands currently assume an OSGi repository.

+

Resolving against existing container

+

With openliberty, WebSphere Liberty, Karaf, Liferay, etc. you are deploying into an existing container which already has a lot of capabilities. The crux of the issue becomes resolving only what you need to deploy. What you need at that point is a way to find out what the container already provides in a format which can be used during resolve time.

+

Currently, the way to do that is to create a distro of the target container. This distro is a JAR file which provides all the capabilities that the target container provides at one point in time. It includes the capabilities of all currently installed bundles. It also contains all capabilities provided by the system bundle which may have been configured by framework properties. It is an aggregate view of all the capabilities available in the framework contained in a single JAR.

+

Resolving Multi-Release JAR files (MRJ)

+

A Multi-Release JAR (MRJ) has directories in META-INF/versions/<release> (see JAR File Specification). When the JAR is deployed on a VM with a given release R, that VM will preferentially load file resource from its own release R and then down to the main area. This means that a JAR can have different content depending on the VM it is deployed. For OSGi, this means that a bundle resource can have different requirements based on the runtime VM. The capabilities are the same since the public API must not change.

+

The problem is that this makes some requirements dependent on the VM. To model this, we introduced synthetic resource for each supported VM release that can only resolve on that release and when the release specific requirements of the bundle can be resolved.

+

This is only about modeling a JAR as a resource in an OSGi repository. Nothing is changed in the original JAR.

+

So we first treat the multi release bundle as any other bundle when we turn it into a resource, the release directories are ignored. If there are none, we're actually done.

+

Otherwise, we add a single requirement to a bnd.multirelease capability unique for this bundle. This namespace only has the properties bnd.multirelease=<bsn> and version=<version>. By requiring another resource, we can generate a synthetic resource for each VM release that the bundle supports. This is depicted here, where mrj is bnd.multirelease.

+

+

For the osgi.identity capability, we have to create a resource name that is unique. To keep it readable, the name is the original-bsn + "__" + release. The version is the original bundle's version. We introduced a new type for these synthetic resources: bnd.synthetic.

+

A Bundle x.y.z, providing code for JDK 1.8, 9 and 11 will appear as x.y.z__8, x.y.z__9 and x.y.z__11 with the corresponding narrow version ranges for their respective Java version.

+

We also add the requirements of the bundle if it would run on that release. +The synthetic resources are added to the same repository of the original bundle

+

For example the bundle org.assertj:assertj-core:3.24.1 contains classes for Java 8 and Java 9. In the Resolution View of bndtools it is shown with the following two capabilities for each Java version:

+
FROM: assertj-core__8 version=3.24.1 type=bnd.synthetic
+bnd.multireleaseCapability from a supporting resource 0 part of Optional[assertj-core version=3.24.1]
+;
+    bnd.multirelease = assertj-core;
+    version = 3.24.1
+
+ +
FROM: assertj-core__9 version=3.24.1 type=bnd.synthetic
+bnd.multireleaseCapability from a supporting resource 1 part of Optional[assertj-core version=3.24.1]
+;
+    bnd.multirelease = assertj-core;
+    version = 3.24.1
+
+ +

How do you create a distro?

+
    +
  1. Install the bnd remote agent bundle in the target container runtime. This will automatically open a local socket on a default port used by the bnd cli next.
  2. +
  3. +

    Execute the following command using the bnd cli:

    +
    bnd remote distro -o container-5.6.7.jar container 5.6.7
    +
    + +
  4. +
  5. +

    Take the jar container-5.6.7.jar created in 2. and place it into the directory containing the bndrun file that is used to resolve your deployment jars.

    +
  6. +
  7. +

    in the bndrun file add:

    +
    -distro: ${.}/container-5.6.7.jar;version=file
    +
    + +
  8. +
  9. +

    resolve... the result of the resolve should be the set of bundles you need to install in the container, minus everything the container already provides.

    +
  10. +
+

What you do with those resolved bundles is dependent on the goal of the developer. They can be directly installed in the existing container, or they could be assembled into a package format native to the container, or possibly a subsystem.

+

Considerations

+

What you need to bear in mind is that the distro needs to be re-created each time the target container changes in any significant way, otherwise it won't reflect the true capabilities of the system needed to resolve against.

+

Conclusion

+

Creating applications from reusable models is a goal that the software industry has been trying to achieve for a long time. To a certain extent, the Maven dependency model provides this model. However, it also is a model where dependencies are not strictly managed and much is left to chance.

+

The resolver model provides an alternative (working inside maven if so desired) to establish a class path that optimises the whole application class path instead of just slavishly following transitively dependencies. Experience shows that organisations that use the resolver have a much better grip of what is actually running in their runtime. Not only minimises this runtime errors, it generally also makes it easier to migrate and evolve the code base.

+

Converting an existing build into a resolve based build can be daunting but the efforts are worth it. For bnd users that use the workspace model the advantages will flow freely.

+ + diff --git a/org.bndtools.help/docs/chapters/300-launching.html b/org.bndtools.help/docs/chapters/300-launching.html new file mode 100644 index 0000000000..b56a6b7f4f --- /dev/null +++ b/org.bndtools.help/docs/chapters/300-launching.html @@ -0,0 +1,313 @@ + + + + +Launching + + + +

Launching

+

bnd integrates an OSGi launcher. This launcher will start a framework and then install and start a list of bundles. Launch descriptions are defined in a bndrun file. (A bnd.bnd file can actually also act as a bndrun file.) The bndrun file inherits properties from the workspace, not the profile.

+

The launching environment is described with a number of instructions that start with -run.

+ +

Additional properties can be specified, and can be inherited from the workspace, that are specific for a launcher or are used for exporting a bndrun to an executable format like OSGi Subsystems, KARs, WARs, or executable JARs.

+

Launcher Architecture

+

Launchers are not build into bnd, the actual launching strategy is parameterized. A launcher is associated with a bnd or bndrun file by placing a JAR on the -runpath. A JAR should have a Launcher-Plugin header to be a launcher. If no launcher is found on the -runpath then the built-in biz.aQute.launcher will be used.

+

The plugin maps the bnd model specified in a bndrun or bnd file to an external execution. In general this plugin launches or contacts a VM, installs the -runpath, installs -runbundles, fires up the bundles. The plugin is also called when the bundles or settings have changed so that it can dynamically update the bundles on the running VM.

+

There are currently two launchers in the bnd repository:

+ +

biz.aQute.launcher

+

The default launcher in bnd. It creates a new VM with the given options, creates a framework using the OSGi launching API, and then manages the bundles on this framework with the OSGi launching API. It can update the remote framework in real time by changing a properties file that is watched for by the launcher class running in the remote framework.

+

Example bndrun file

+
-runfw:                     org.apache.felix.framework;version='[4,5)'
+-runbundles: \
+    org.apache.felix.shell,\
+    org.apache.felix.shell.tui,\
+    org.apache.felix.scr,\
+    org.apache.felix.http.jetty,\
+    org.apache.felix.configadmin,\
+    org.apache.felix.metatype,\
+    org.apache.felix.log,\
+    org.apache.felix.webconsole,\
+    osgi.cmpn,\
+    aQute.xray.badbundle;version=latest,\
+    aQute.xray.plugin;version=latest,\
+    aQute.xray.hello;version=latest,\
+    com.springsource.org.apache.commons.fileupload;version=1.2.1,\
+    com.springsource.org.apache.commons.io;version=1.4.0,\
+    com.springsource.org.json;version=1.0.0
+
+-runproperties:            org.osgi.service.http.port=8080
+
+-runrequires:\
+    bundle:(symbolicname=org.apache.felix.shell),\
+    bundle:(symbolicname=org.apache.felix.shell.tui),\
+    bundle:(symbolicname=org.apache.felix.webconsole),\
+    bundle:(symbolicname=org.apache.felix.configadmin),\
+    bundle:(symbolicname=org.apache.felix.metatype),\
+    bundle:(symbolicname=org.apache.felix.log),\
+    bundle:(&(symbolicname=osgi.cmpn)(version>=4.2)),\
+    bundle:(&(symbolicname=org.apache.felix.scr)(version>=1.6.0))
+
+ +

Exports from the Runpath

+

The launcher analyzes the -runpath JARs. Any additional capabilities in the manifest (packages and Provide Capability headers) in these JARs are automatically added to the framework.

+

Exporting an older Java 8 compatible launcher

+

There are cases where you are working with a recent 7.x release of bnd / bndtools but you want to export an executable .jar which contains e.g. the launcher of bnd 6.4.1 which is compatible with JDK-8 (because newer 7.x bnd and launcher requires JDK-17 minimum). +In this you can do the following:

+
    +
  1. Place biz.aQute.bnd:biz.aQute.launcher:6.4.1 in one of your repositories
  2. +
  3. reference it in your .bndrun like this:
  4. +
+
# myapp.bndrun
+-runpath: ${repo;biz.aQute.bnd:biz.aQute.launcher;[6.4.1,6.4.2)};version=file
+
+ +

Runtime Information

+

The launcher registers a service with object class Object that provides some runtime information. The following properties are set on this service:

+ +

Embedded Activators

+

The launcher supports embedded activators. These are like normal Bundle Actviator classes but are instead found on the -runpath. Any bundle that has the header Embedded-Activator will be started. The start can happen at 3 points that are identified with a static field in the Embedded Activator class. This field is called IMMEDIATE. For example:

+
public class MyEmbeddedActivator implements BundleActivator {
+    public static String IMMEDIATE = "AFTER_FRAMEWORK_INIT";
+    ...
+}
+
+ +

The IMMEDIATE field can have the following values:

+ +

The reason strings are used is to not require the need for extraneous types on the executable's class path. If a string in IMMEDIATE is used that is not part of the previous one then a message must be logged. The behavior will then be "AFTER_BUNDLES_START". Other strings are reserved for future extensions.

+

For example:

+
public class MyActivator implements BundleActivator {
+    public static String IMMEDIATE = "BEFORE_BUNDLES_START";
+
+    public void start(BundleContext context) {}
+
+    public void stop(BundleContext context) {}
+}
+
+bnd.bnd:
+    Embedded-Activator: com.example.MyActivator
+
+ +

For backward compatibility reason the IMMEDIATE field the launcher will also recognize a boolean field.

+ +

It is recommended to update to one of the strings instead of the boolean and not use this pattern in new setups.

+

Startlevels

+

The -runbundles instruction supports an startlevel attribute. If one or more of the bundles listed in the -runbundles instruction +uses the startlevel attribute then the launcher will assign a startlevel to each bundle. This is currently supported for the +normal launcher and not for Launchpad nor the remote launcher.

+

If a bundle has a startlevel attribute then this must be an integer > 0, otherwise it is ignored. Bundles that have no +startlevel attribute will be assign the maximum assigned startlevel attribute + 1. For example, given the following +bundles:

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)',\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1)';startlevel=10,\
+    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
+    ...
+    osgi.enroute.twitter.bootstrap.webresource;version='[3.3.5,3.3.6)';startlevel=12,\
+    osgi.enroute.web.simple.provider;version='[2.1.0,2.1.1)'
+
+ +

The org.apache.felix.configadmin, org.apache.felix.http.servlet-api, and osgi.enroute.web.simple.provider do not specify +a startlevel attribute and will therefore be assigned to start level 13. This value is picked because max(10,12)= 12 + 1 = 13.

+

Startlevels are assigned before the framework is started, they are updated on the fly if during a debug session the setup changes.

+

Normally in OSGi the begining start level is selected with the system property org.osgi.framework.startlevel.beginning. If +this -runproperty is not set then the launcher will set this property before starting the framework to the maximum of +specified levels + 2. If a start level management agent is present then this property should be set, the launcher will +then not interfere.

+

The bundles are started at during start level 1.

+

For example, a management agent that manages start levels is placed in start level 1 and all other bundles are placed +at start level 100.

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)',\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1)';startlevel=100,\
+    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
+    org.example.management.agent;startlevel=1
+    osgi.enroute.twitter.bootstrap.webresource;version='[3.3.5,3.3.6)';startlevel=100,\
+    osgi.enroute.web.simple.provider;version='[2.1.0,2.1.1)'
+
+ +

The -runproperties specify a begining of 1:

+
-runproperties: \
+       org.osgi.framework.startlevel.beginning=1
+
+ +

The launcher will install all bundles and assign them their start level. The framework is then started and moves +to level 1. This starts the management agent. This management agent will then move the start level higher to finally +level 100.

+

Packaging

+

Any bndrun file can be packaged by the launcher plugin. This creates an executable JAR that will contain all its dependencies.

+
$ bnd package xyz.bndrun
+
+ +

You can then execute the jar:

+
$ java -jar xyz.jar
+
+ +

You can override all the properties that are embedded in the executable JAR with the -Dlauncher.properties=<file> option of the Java VM. Instead of consulting its internal properties file, the launcher will read the given file. However, you can also set individual System properties with the -D option that override a specific launching constant.

+ +

For example, if you want to run your executable in trace mode:

+
$ java -Dlaunch.trace=true xyz.jar
+
+ +

Expanding Executable JARs

+

An executable JAR can be unzipped in a directory. It will then include a Windows and Linuxy shell script to start the executable in expanded form. In the expanded form, the framework will try to use reference: URLs to install bundles when not on Windows. (Windows and reference URLs do not work well because Windows keeps files locked.)

+

If no reference URLs should be used, the -runnoreferences=true instruction can be set.

+

Properties

+

Framework properties can be set using the -runproperties instruction. Framework properties do not include the system properties but any property set using -runproperties can be overridden with a system property. That is, it is impossible to set a property using the -D on the Java command line unless it was prior given a default in the bndrun file.

+

For example:

+
bndrun:
+-runproperties: foo=3
+
+
+$ java -Dfoo=4 -Dbar=1 xyz.jar
+
+ +

In this example, the xyz app will see foo=4 but bar will not be a framework property.

+

Exit codes

+

If the framework stops the launcher will exit. It will set a system exit code that reflects the event type from that the framework returned. The shell script that started the launcher can take the system exit code into account to restart the framework in certain cases.

+
OSGi FrameworkEvent             Launcher Constant  Value
+STOPPED                         STOPPED            -9
+WAIT_TIMEDOUT                   TIMEDOUT           -3
+ERROR                           ERROR              -2
+WARNING                         WARNING            -1
+STOPPED_BOOTCLASSPATH_MODIFIED  STOPPED_UPDATE     -4
+STOPPED_UPDATE                  STOPPED_UPDATE     -4
+
+ +

The launcher therefore returns the process exit code UPDATE_NEEDED(-4) when it requires an update. This was chosen over doing an in-process update because it is much safer. So the launching script should look something like:

+
do {
+  bnd run app.bndrun
+} while ($?==-4)
+
+ +

Remote Launching

+

The purpose of the aQute Remote project is to provide remote debugging support for bnd projects. It can be used to debug bundles and bndrun files in a remote machine running an OSGi framework with an agent installed on it; it can also install a framework on a remote machine before it uses the agent. The architecture is heavily optimized to run on small remote machines.

+

Parts

+

This project is the bnd remote launcher. It consists of the following artifacts:

+ +

Usage

+

The biz.aQute.remote.launcher should be placed on the -runpath in a bnd or bndrun file. The remote plugin expects a -runremote instruction in the parent file. This property has the following syntax:

+
-runremote ::= remote (',' remote)*
+remote     ::= NAME ( ';' aspect '=' value ) *
+aspect     ::= 'jdb' | 'shell' | 'host' | 'agent' | `timeout`
+
+ +

It is possible to specity multiple remote clauses. All sections are started simultaneously. The aspects are described in the following sections:

+ +

Additionally, the communication can be traced by setting the aQute.remote.util.Link.trace system property to true on the target system.

+

Example bndrun

+

An example remote bndrun file:

+
local       =   \
+    local; \
+    shell   =   4003; \
+    jdb     =   1044; \
+    host    =   localhost
+
+-runremote:     ${local}    
+-runfw:         org.apache.felix.framework;version='[4,5)'
+-runee:         JavaSE-1.8
+-runproperties: gosh.args=--noshutdown, osgi.shell.telnet.port=4003
+
+-runpath:       biz.aQute.remote.launcher;version=latest
+-runrequires:\
+    osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.shell)',\
+    osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)'
+
+-runbundles:\
+    launch.simple.really;version=latest, \
+    org.apache.felix.gogo.shell,\
+    org.apache.felix.gogo.command,\
+    org.apache.felix.gogo.runtime, \
+    org.apache.felix.shell.remote
+
+ +

Example bndrun with the -javaagent parameter

+

One example where a javaagent is used is the JaCoCo Java Code Coverage Library. +The following example shows how Jacoco v0.8.5 can be started by adding the -javaagent parameter via -runvm as a VM-option.

+ +

A few notes about the example:

+ + + diff --git a/org.bndtools.help/docs/chapters/305-startlevels.html b/org.bndtools.help/docs/chapters/305-startlevels.html new file mode 100644 index 0000000000..272963d7ca --- /dev/null +++ b/org.bndtools.help/docs/chapters/305-startlevels.html @@ -0,0 +1,83 @@ + + + + +Startlevels + + + +

Startlevels

+

One of the primary authors of bnd has always objected to startlevels. His motivation was twofold:

+ +

With this disclaimer out of the way, there are actually cases where startlevels are quite important to +improve the non-functional aspects.

+ +

Startlevel Support in bnd

+

Run configurations in bnd are described in bndrun files. The list of bundles to run are listed in the -runbundles +instruction. The runbundles instruction has a startlevel attribute that specifies the startlevel of each bundle.

+

Since the -runbundles instruction is frequently calculated by the resolver support in bnd it is not possible to manually +assign the startlevel attributes to specific bundles. For this reason there is a decorator support in bnd for some selected +instructions. A decorator is a header with the same name but ending with a plus sign (+). This instruction acts like a selector +and can be used to assign startlevel attributes on the -runbundles.

+

For example:

+
-runbundles: \
+    org.apache.servicemix.bundles.junit;version='[4.13.0,5)',\
+    org.apache.felix.log, \
+    demo;version='[1.0.0,1.0.1)'
+
+-runbundles+: \
+    demo;startlevel=11,\
+    *;startlevel=99
+
+ +

Launching

+

The launcher is responsible for installing the bundles after starting or communicating with a framework. The +default bnd launcher will assign each bundle a startlevel, where bundles that do not have a specified startlevel are +assigned one level higher than the maximum specified levels.

+

The launcher supports narrow managed mode or all via the [-launcher] instruction. In narrow mode, the start levels +will only be assigned to the scope, the set of bundles listed in the run bundles. In the all mode, all bundles +that are installed at launch time will be assigned the default start level.

+

The default launcher will then move the framework start level to 2 higher than the highest specified start level.

+

Resolving

+

The resolve support in bnd can automatically assign startlevel attributes to the -runbundles based on different ordering +strategies. There are two strategies that use the dependency graph. This graph can be sorted in topological order. +This means that a resource is always listed ahead of any of its dependencies when there are no cycles.

+

The -runstartlevel instruction controls the ordering and assigned start levels.

+

Strategies

+

At the time of this writing it is not yet clear what the best strategy is, and it may depend.

+

Ordering by the topological sort (a resource is followed by its dependencies) will start something like the log service +last and any applications bundles first. Although at first sight this feels wrong (the log service should be started first +to capture the events at startup) it does solve the jojo problem because one of the last bundles started will be the +Service Component Runtime that will activate all components. At that time all initialization should have taken place.

+

Reversing the topplogical sort will start the something like SCR and log first because they have few or no dependencies. +Application bundles are then started latest.

+

Numbering

+

Traditionally start levels are managed by an application bundle. Shell commands can increase and decrease start levels. +For this reason, start levels often use nice numbers.

+

Using the resolver the need for nice numbers is diminished since bnd is now taking care. The basic default model +is to assign bundles sequentially in selected order from an initial level stepping with 10. The -runstartlevel instruction +can provide the initial level and the step if desired.

+

The launcher will by default move the framework then to a start level that includes any used start levels. This +default behavior can be blocked by specifying the org.osgi.framework.startlevel.beginning property. If this +property is set bnd will assume that there is an agent that will handle the runtime start levels.

+

Runtime

+

A quick way to disable the start level handling by the launch is to set the property used to convey the default +start level, launch.startlevel.default to 0. This will disable the complete start level handling regardless +of other settings.

+ + diff --git a/org.bndtools.help/docs/chapters/310-testing.html b/org.bndtools.help/docs/chapters/310-testing.html new file mode 100644 index 0000000000..c6ec473c20 --- /dev/null +++ b/org.bndtools.help/docs/chapters/310-testing.html @@ -0,0 +1,208 @@ + + + + +Testing + + + +

Testing

+
+ +

Deprecation: Note, that the default test biz.aQute.tester is deprecated as of bnd 7.2.0 and will be removed in 8.0.0. +Please use and migrate your tests to JUnit 5 and use biz.aQute.tester.junit-platform going forward. +The documentation below will be adjusted in the future.

+
+ +

This section describes how bnd implements a pluggable testing framework. With most tools that use bnd this information is hidden behind a pleasant GUI (sometimes). However, in certain cases it is necessary to understand how bnd handles testing.

+

Model

+

In the classic way testing consists of launching a new VM, dynamically loading the classes to be tested and then running the test framework on those. As this violates module boundaries as if they did not exist there is another way.

+

In bnd there is a header that allows a bundle to define what tests it contains:

+
Test-Cases ::= fqn+
+
+ +

Such a bundle therefore exports a number of test cases to the environment. These test cases can then be executed by the tester. The default tester in bnd is the biz.aQute.tester bundle, but this can be overridden because the launcher and the tester are pluggable (see Other Tester Frameworks).

+

The default tester can run in one shot mode or in automatic mode. The one shot mode is specified using the tester.names property - the tester will run the specified tests and then exit. This mode is typically used by build tools, which set the tester.names property, run the tests, and then parse the results.

+

In automatic mode, the default tester creates a list of available bundles with the Test-Cases header set and executes all of them. Automatic mode will then end, or if the tester.continuous property is set it will continue running (known as continuous mode).

+

In continuous mode, every time a test bundle is started the tester will run that bundle's tests. Continuous mode is intended for developing test bundles. You just run a framework and edit your test bundle's code. Any changes are saved and deployed, triggering a restart of the bundles and hence a re-run of the tests.

+

How to set the Test-Cases header Automatically

+

The Test-Cases header can be set by hand but this can become a maintenance nightmare. A very useful macro is the ${classes} macro. This macro inspects the JAR and can find all classes that are considered test cases:

+
Test-Cases = ${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
+
+ +

This example looks for concrete classes that extend the JUnit 3 base class. For non JUnit 3 tests, you can use a naming convention:

+
Test-Cases: ${classes;CONCRETE;PUBLIC;NAMED;*Test*}
+
+ +

This will include all concrete public classes whose name includes the word Test.

+

Default Tester - biz.aQute.tester

+

If you do not explicitly specify the tester module to use, bnd will use biz.aQute.tester. The configuration of this module is as follows.

+

Supported Framework Properties

+

The default tester uses the project information to parameterize the tester's runtime component. However, it is also possible to set these runtime parameters explicitly with framework properties when you want to run the framework in automatic mode. The default tester obeys the following framework properties:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDefaultDescription
tester.port-The port to send the JUnit information to in a format defined by Eclipse. If this property is not set, no information is send but tests are still run.
tester.hostlocalhostThe host to send the JUnit information to in a formatted defined by Eclipse. If this property is not set localhost is assumed.
tester.namesFully qualified names of classes to test. If this property is null automatic mode is chosen, otherwise these classes are tested and then the test exits.
tester.dirtestdirA directory to put the test reports. If the directory does not exist, no reports are generated. The default is testdir in the default directory. This directory is not automatically created so to see the results it is necessary to ensure such a directory exists. the files in the test directory are usable in Hudson/Jenkins as test reports
tester.continuousfalseIn automatic mode (ie, when no tester.names are set), continue watching the bundles and (re-)run a bundle's tests when it is started.
tester.tracefalseTrace the test framework in detail. Default is false, must be set to true or false.
+

Continuous Testing

+

To setup an environment to test continuously, the following launcher configuration can be used:

+
Test-Cases: ${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
+-runfw: org.apache.felix.framework
+-buildpath: osgi.core;version='[4.1,5)', \
+  osgi.cmpn,  \
+  junit.osgi
+Private-Package: org.example.tests
+-runtrace: true
+-runbundles: biz.aQute.junit
+-runproperties:  \
+  tester.trace=true, \
+  tester.continuous=true, \
+  tester.dir=testdir
+
+ +

The example setup creates a bundle containing the org.example.tests package and sets the Test-Cases header to all JUnit 3 test cases in that package. If you run this setup, it runs the project bundle with the biz.aQute.junit bundle. This tester bundle is parameterized with the tester.* properties to have trace on, continuous mode on, and to put the test reports in ./testdir.

+

You can find a bndtools project that shows this at Github.

+

Testing With JUnit 5 - biz.aQute.tester.junit-platform

+

As of Bnd 5.0, bnd includes a new tester bundle biz.aQute.tester.junit-platform that supports JUnit 5.

+

As per the JUnit 5 documentation, JUnit 5 is comprised of three modules:

+
    +
  1. JUnit Platform - the framework for launching test engines.
  2. +
  3. JUnit Jupiter - a test engine for executing the latest JUnit 5 tests.
  4. +
  5. JUnit Vintage - a test engine for executing JUnit 3 & 4 tests.
  6. +
+

biz.aQute.tester.junit-platform leverages JUnit Platform for discovering and launching tests. This tester will:

+ +

Feature compatibility with biz.aQute.tester

+

At the moment, biz.aQute.tester.junit-platform supports most of the features of biz.aQute.tester, including continuous testing and XML reporting. There are a couple of notable exceptions:

+ +

Improved Eclipse integration

+

In addition to JUnit Platform support, the new tester has some features that weren't available in the old tester, which makes its integration with Eclipse a bit more user-friendly:

+ +

Support for custom TestExecutionListeners

+

JUnit Platform has a publicly-defined TestExecutionListener interface. As of Bnd 5.2, biz.aQute.tester.junit-platform has support for adding your own custom TestExecutionListener implementations: simply write a class that implements this interface, and then register it as a OSGi service before the test run starts. biz.aQute.tester.junit-platform will invoke the callback methods on your custom listener(s) as the tests are executing.

+

This feature can be useful if you want to do any custom reporting for your tests - it is likely to be much easier and more flexible than (eg) trying to manipulate XML files generated by the legacy XML reporting module.

+

Using biz.aQute.tester.junit-platform

+ +

Bnd can help with the last two steps by adding the tester and engine bundles to -runrequires and using the resolver:

+
-runrequires: \
+    bnd.identity;id='org.junit.jupiter.engine',\
+    bnd.identity;id='org.junit.vintage.engine',\
+    bnd.identity;id='biz.aQute.tester.junit-platform'
+
+ +

See the chapter on resolving for more information.

+

Note that if you're only using JUnit 3/4, you can omit the -runrequires line for the Jupiter engine, and conversely if you're only using JUnit Jupiter you can omit the Vintage engine. Alternatively/additionally, if you have any other TestEngine implementation bundles available, you can list these here instead/as well (though this has not been tested).

+

Finding the JUnit Platform bundles

+

As noted above, biz.aQute.tester.junit-platform requires JUnit Platform (and its dependencies) on the classpath, and if it is to do much that is useful it will also require at least one TestEngine. Bundled versions of these are part of Eclipse since Oxygen. You can include them in your workspace from:

+ +
    -plugin.repository: \
+        aQute.bnd.repository.osgi.OSGiRepository;\
+            name="Eclipse 2018-12";\
+            locations="https://bndtools.jfrog.io/bndtools/bnd-build/eclipse/4.10/index.xml.gz";\
+            poll.time=-1;\
+            cache="${workspace}/cnf/cache/stable/Eclipse-2018-12"
+
+ + +
    -plugin.repository: \
+        aQute.bnd.repository.p2.provider.P2Repository;\
+            name="Eclipse Local";\
+            url="file:///path/to/eclipse/";\
+            location="${workspace}/cnf/cache/stable/EclipseLocal"
+
+ +

Alternatively, it is not difficult to download the required (non-OSGi) modules from Maven Central and include them as-is on -runpath, or else (preferably) wrap them into bundles and include them in -runrequires/-runbundles. +As of JUnit 5.6, the JUnit jars already have the OSGi metadata and so can be used as bundles +direct from Maven Central.

+

Also note that unfortunately, due to a bug in biz.aQute.tester.junit-platform, Bndtools 5.0 +does not work with JUnit 5.5+. A fix is already available in the latest development snapshot, and we expect the +fix to be included in a future Bndtools release (hopefully soon).

+

Other Tester Frameworks

+

The biz.aQute.tester is a normal bundle that gets started from the launcher framework. However, before bnd chooses the default tester, it scans the classpath for a tester (set with -runpath) for JARs that have the following header set:

+
Tester-Plugin ::= fqn
+
+ +

If no such tester is found on the -runpath it will look in the -tester instruction and loads that bundle:

+
-tester:                biz.aQute.junit
+
+ +

Otherwise it will use biz.aQute.tester (if it still can find it).

+

The Tester-Plugin header points to a class that must extend the aQute.bnd.build.ProjectTester class. This class is loaded in the bnd environment and not in the target environment. This ProjectTester plugin then gets a chance to configure the launcher as it sees fit. It can get properties from the project and set these in the Project Launcher so they can be picked up in the target environment.

+

As this is a quite specific area the rest of the documentation is found in the source code.

+

Older Versions

+

For a long time bnd had biz.aQute.junit as the default tester. biz.aQute.junit has the same functionality as biz.aQute.tester, but with the following key differences:

+ +

Unfortunately the design of biz.aQute.junit caused constraints between JUnit and bnd that was not good because JUnit itself is not directly a shining example of software engineering. :-( So for this reason, biz.aQute.tester (or the newer biz.aQute.tester.junit-platform) is generally preferred.

+

If for some reason you need to be backward compatible with the older model, set:

+
-tester: biz.aQute.junit
+
+ + diff --git a/org.bndtools.help/docs/chapters/315-launchpad-testing.html b/org.bndtools.help/docs/chapters/315-launchpad-testing.html new file mode 100644 index 0000000000..37f3476f80 --- /dev/null +++ b/org.bndtools.help/docs/chapters/315-launchpad-testing.html @@ -0,0 +1,488 @@ + + + + +Testing with Launchpad + + + +

Testing with Launchpad

+

note This featue is in beta. Feedback welcome and expect a few deficiencies in documentation and usage.

+

An OSGi framework poses special challenges to testing because it is necessary to start a framework instance for each +test. There has always been a bnd OSGi testing framework that was developed to test the OSGi specifications and reference +implementations. This testing framework packaged the tests as a bundle and had a special version of JUnit that could run +these tests from inside the framework. Actually quite powerful and it was fully integrated with Eclipse JUnit testing, +delivering identical output to the CI build tools. However, the use of a special JUnit runner excluded it for people that wanted +to use TestNG or other test frameworks.

+

A second problem was that since tests ran inside the framework as a bundle they could not influence the setup of the OSGi +framework easily. A last problem was that tests shared the same framework which could result in ordering dependencies.

+

Launchpad

+

Launchpad is a bnd runtime library that provides an API to launch a framework that is fully integrated with the +bnd workspace. It automatically exports the runtime class path via the framework bundle, ensuring there is a single class space for +the code on the class path and the code in the bundles. (This does require that bundles properly import their +exported packages.)

+

Launchpad provides a builder that incrementally can build up the specifications of the framework. The builder can +take bndrun files or bundle specifications in the same format as that are used to set the -buildpath or +-runbundles in the bnd.bnd files. Once the information is setup, bnd will calculate the setup based on +the classes in the test folder and launch an OSGi framework.

+

Once the framework is launched, Launchpad can then inject services and some key framework objects into annotated +fields. Each field can specify a timeout, target filter, and minimum cardinality. Injection can take place in any object but is +usually on the test instance.

+

In the original OSGi testing support test bundles had to be created during the build. In the OSGi test cases for the Blueprint +reference implementation more than 200 test bundles were used. Although the overhead was relatively small due to the bnd -make facility, +it was still a nuisance because the information in a test case had to be synchronized in a bnd file in another directory. For +this reason Launchpad contains a bundle builder. This bundle builder used bnd under the hood. It can use anything that a bnd +sub bundle could use; it is build in the context of the project that contains the test classes and shares the same +-buildpath. Bundles that are build with the bundle builder can actually leverage nested classes in the test class for +Bundle Activator or component classes.

+

Overall this is a comprehensive library for testing OSGi projects in a Bndtools workspace.

+

Quick Start

+

You need the biz.aQute.launchpad library on your -testpath.

+
bnd.bnd:
+... 
+-buildpath: ...
+-testpath: \
+    osgi.enroute.junit.wrapper, \
+    biz.aQute.launchpad
+
+ +

note The biz.aQute.launchpad is available in 4.2 but there are a few minor API changes that did not make it. You can +therefore use the snapshot version on JFrog or download the latest version and use:

+
lib/biz.aQute.launchpad.jar;version=file
+
+ +

The next step is to enable your workspace for launchpad. A bnd workspace can have a Remote Workspace Server and +Launchpad needs it. You therefore need to add the following to your cnf/build.bnd file.

+
cnf/build.bnd:
+    -remoteworkspace        true
+
+ +

Using JUnit, we can now create a test. We start with creating a LaunchpadBuilder. This builder stores information about the to be started framework. It has many +methods that usually align with the properties for a bnd.bnd file. The Javadoc contains the details. We could create this +object in a @Before method and close it in an @After method but this object does not have to be closed. It contains only +the settings.

+
LaunchpadBuilder    builder = new LaunchpadBuilder()
+                    .runfw("org.apache.felix.framework");
+
+ +

For this first quick start test we inject a Bundle Context, the core OSGi object that allows us to interact with the framework.

+
@Service
+BundleContext       context;
+
+ +

The method is a normal JUnit test method. We open the Launchpad in a try resource block. Closing the Launchpad object will +shutdown the framework. The test is simply verifying that the injection has worked.

+
@Test
+public void quickStart() throws Exception {
+    try (Launchpad launchpad = builder.create()
+        .inject(this)) {
+        assertNotNull(context);
+    }
+}
+
+ +

Voila! The first Launchpad test case.

+

Two Models

+

The Launchpad code can be used in different modes:

+ +

JUnit Launchpad Runner Mode

+

To use the Launchpad Runner it is necessary to add an @RunWith annotation on your JUnit test class:

+
@RunWith(LaunchpadRunner.class)
+public class TestMyCode {
+
+    LaunchpadBuilder    builder = new LaunchpadBuilder().runfw("org.apache.felix.framework").debug();
+
+    @Service
+    Launchpad       launchpad;
+
+    @Test
+    public void testMyCode() {
+        launchpad.report();
+    }
+}
+
+ +

Junit Theory

+

The Launchpad Runner is in control to gather the tests and then execute them. The test gathering is handled via the +standard JUnit support. However, when the test must run, LaunchpadRunner creates a bundle that has the following qualities:

+ +

The runner then launches a framework based on a LaunchpadBuilder that it finds in the the static field builder.

+

It then installs the bundles, and adds the test bundle. To execute a test, it loads the +class from the test bundle and finds the appropriate method, instantiates the class in an instance, runs the injector +on this object. and executes the methods.

+

This mode is similar to the PAX Exam model. It has similar constraints. It does run the @Before and @After annotated +methods but it cannot run the @BeforeClass and @AfterClass.

+

Classpath Mode

+

Launchpad is quite awesome to use but there are some pitfalls to take into account. It is strongly recommended +to read this section to get an idea how Launchpad handles class sharing between the test classes (which are on the +normal Java class path) and the classes in bundles. There is more going on than what one suspects looking at the +simplicity how it can be used. This section details the workings to make you aware of potential bugs and should +help in debugging problems. In general, the cleaner your code base, the better this all works. If you have a very messy +setup with lots of scripts, fragments, require bundle, and very wide code interfaces instead of services then this +might not be for you ...

+

Class Loading

+

In Java, class are loaded from the classpath. The class path is a (usually very long) list of Jar files. When a class +needs to be loaded, Java searches al those Jars for that class, first one wins.

+

In OSGi, this model is changed for a delegating model. Each bundle imports a set of packages and exports a set +of packages. This information is in a bundle's manifest. When an OSGi framework resolves a bundle, it wires these +imports to a corresponding export.

+

Lauchpad's Classpath

+

When a test case gets started the driver (Eclipse, Gradle, etc.) launches a new Java VM. The class path for that +VM will consist of all entries on the -buildpath, -testpath, and the main and test output folders. When the +Launchpad builder is first called it will contact the Remote Workspace in the driver and request for an analysis of +the test code. The Remote Workspace then uses the project setup to calculate a bundle that would export all the +test code and its imports. The Launchpad Builder then makes the OSGi framework export all packages that that +virtual test bundle would have exported. That is, any class visible from the test cases will be exported by +the OSGi framework by default. It is possible to exclude exports using glob expressions or predicates from a test case. +See the excludeExport() methods.

+

Bundles

+

A bundle installed on the OSGi Framework should this see all the relevant classes from the class path instead of +from other bundles. The tricky case is when a bundle exports a package that is also available from the +class path. If this package is only exported then the framework cannot substitute it for the package from the +class path. In such a bad case the bundle that exports it will see its embedded version of the class while +the rest of the system sees the version from the class path. This can then result in a class cast exception +like:

+
java.lang.ClassCastException: an instance of org.example.Foo cannot be assigned to org.example.Foo
+
+ +

Although the names of those classes are identical, the problem is that they will be loaded by different class +loaders.

+

Version Sensitivity

+

Due to this setup there is very strict sensitivity to the version of the OSGi Framework packages and bundles. Most bnd projects +have the OSGi framework packages on the -buildpath. The version of these packages can be lower than the version +of the Framework because of backward compatibility. Actually, bnd generally recommends to compile against the +lowest possible framework packages. However, with launchpad these packages will also be used by the Framework, there +is unfortunately no good way around this. The consequence is that the -buildpath version of the Framework +packages must match the exact version used by the implementation of the framework.

+

Excluding Exported System Packages

+

Launchpad will calculate the set of packages that are exported by the framework from the claspath. The so called +org.osgi.framework.system.packages.extra. It calculates this by creating bundle from the test sources, adding +all dependencies, and then exporting the full content. That export statement is then uses for org.osgi.framework.system.packages.extra.

+

However, this is generally too wide since it includes all dependencies, not just public dependencies. Version mismatches +can create nasty problems and sometimes the solution is to exclude exports.

+

The Launchpad Builder provides a number of methods called excludeExport() that take either a glob or a predicate. +The globs/predicates are then ran against the list of calculated export package names. Any matching entry is then +not exported.

+
Launchpad b = new LaunchpadBuilder()
+    .excludeExports( "slf4j.*")
+    .create();
+
+ +

If a bndrun file is the -excludeexports instruction can be placed in the bndrun file containing a list globs.

+
-excludeexports     aQute.lib*, slf4j.*
+
+ +

Naming

+

The Launchpad has a default name of the method and class that called create(). These names can be overwritten with +create(name) and create(name,className). The actual name of Launchpad is set under the following framework +property names:

+
launchpad.name
+launchpad.className
+
+ +

Interaction with Services

+

Clearly the best part of Launchpad is that you can actually use real services and do not have +to mock them up. Many a test seems to mostly test their mocks.

+

With Launchpad, real framework is running. You can inject services or register services.

+

In the following example we register a service Foo and then verify if we can get it. We then +unregister the service and see that it no longer exists.

+
interface Foo {}
+
+@Test
+public void services() throws Exception {
+    try (Launchpad launchpad = builder.create()) {
+
+        ServiceRegistration<Foo> register = 
+            launchpad.register(Foo.class, new Foo() {});
+        Optional<Foo> s = 
+            launchpad.waitForService(Foo.class, 100);
+        assertThat(s.isPresent()).isTrue();
+
+        register.unregister();
+
+        s = launchpad.waitForService(Foo.class, 100);
+        assertThat(s.isPresent()).isFalse();
+    }
+}
+
+ +

The waitForService methods take a timeout in milliseconds. Their purpose is to provide some leeway +during startup for the system to settle. If a service should be there then it the getService() methods +can be used.

+

Injection

+

Injection is not automatic because in many cases you want to handle the setup of the framework before +you inject. Injection can also happen as often as you want. However, you first need to create and +start the framework.

+
@Test
+public void inject() throws Exception {
+    try (Launchpad launchpad = builder.create()) {
+        ServiceRegistration<Foo> register = launchpad.register(Foo.class, new Foo() {});
+
+        class I {
+            @Service
+            Foo foo;
+            @Service
+            Bundle          bundles[];
+            @Service
+            BundleContext   context;
+        }
+        I inject = new I();
+        launchpad.inject(inject);
+        assertThat(inject.bundles).isNotEmpty();
+    }
+}
+
+ +

Hello World

+

Although Bundle-Activator's are not recommended to be used (they are singletons), they are very useful in +test cases. With Launchpad it is not necessary to to make a separate bundle, we can make a bundle with +an inner class as activator.

+

We therefore first define the Bundle Activator as a static public inner class of the test class:

+
public static class Activator implements BundleActivator {
+    @Override
+    public void start(BundleContext context) throws Exception {
+        System.out.println("Hello World");
+    }
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        System.out.println("Goodbye World");
+    }
+}
+
+ +

The Launchpad class contains a special Bundle builder. This bundle builder is based on bnd and can can do everything that +bnd can do in a bnd.bnd file. In this case we add the Bundle Activator and start it.

+
@Test
+public void activator() throws Exception {
+    try (Launchpad launchpad = builder.create()) {
+
+        Bundle start = launchpad.bundle()
+            .bundleActivator(Activator.class)
+            .start();
+    }
+}
+
+ +

When the test is run the output is:

+
Hello World
+Goodbye World
+
+ +

Components

+

Since the bundle builder can do anything bnd can do, we can also use inner classes for components. These inner +classes must be static and public (this is an OSGi DS requirement). The following is an example of a class +that depends on the Bar service.

+
interface Bar {
+    void bar();
+}
+
+@Component
+public static class C {
+    @Reference Bar bar;
+    @Activate  void activate() { bar.bar(); }
+}
+
+@Test
+public void component() throws Exception {
+    try (Launchpad launchpad = builder
+        .bundles("org.apache.felix.log")
+        .bundles("org.apache.felix.scr")
+        .bundles("org.apache.felix.configadmin")
+        .create()) {
+
+        Bundle b = launchpad.component(C.class);
+        AtomicBoolean   called = new AtomicBoolean(false);
+        launchpad.register(Bar.class, ()-> called.set(true) );
+        assertThat(called.get()).isTrue();
+    }
+}
+
+ +

Adding a component will return a Bundle. Uninstalling the bundle will remove the component.

+

Debugging

+

Clearly there are lots of things that can go wrong. You can therefore activate the debug() on the builder or +Launchpad. This will provide logging to the console.

+
@Test
+public void debug() {
+    try (Launchpad launchpad = builder
+        .debug()
+        .create()) {
+
+        }
+}
+
+ +

If you run this the console will show a lot of diagnostics information.

+

Using a bndrun file

+

One of the great innovations in bndtools is the resolver. So far we've assembled the list of bundles to run ourselves. +However, we can also use a bndrun file and bndrun files can be resolved.

+
@Test
+public void bndrun() {
+    try (Launchpad launchpad = builder
+        .bndrun("showit.bndrun")
+        .create()) {         
+        }
+}
+
+ +

If the bndrun file contains the following after resolving:

+
-runrequires: \
+    osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.shell)',\
+    osgi.identity;filter:='(osgi.identity=biz.aQute.bnd.runtime.gogo)'
+
+
+-runbundles: \
+    org.apache.felix.gogo.runtime;version='[1.1.0,1.1.1)',\
+    org.apache.felix.gogo.shell;version='[1.1.0,1.1.1)',\
+    biz.aQute.bnd.runtime.gogo;version=snapshot,\
+    org.apache.felix.log;version='[1.0.1,1.0.2)'
+-runfw: org.apache.felix.framework;version='[5.6.10,5.6.10]'
+-runee: JavaSE-1.8
+
+ +

Then we see the following output:

+
Welcome to Apache Felix Gogo
+g!
+
+ +

Making Bundles

+

The Launchpad object contains a special bundle builder. It provides the same capabilities that bnd already has when +it creates bundles. You can use all the facilities that you can use in the bnd.bnd file. Export-Package, Import-Package, +-includeresource, etc.

+

The following example shows how to create a bundle with a a special header.

+
@Test
+public void bundles() throws Exception {
+    try (Launchpad launchpad = builder.create()) {
+        Bundle b = launchpad.bundle()
+            .header("FooBar", "1")
+            .install();
+        String string = b.getHeaders()
+            .get("FooBar");
+        assertThat(string).isEqualTo("1");
+    }
+}
+
+ +

Inheriting from the project, workspace, or a bnd file

+

When you create a bundle from the Launchpad class then by default you inherit nothing from the enironment. However, +it is possible to set the parent of the builder. The parent(String) or parent(File) method can set multiple +parents.

+
parent ::= FILE* ( WORKSPACE | PROJECT )?
+
+ + +

The order of the parents is important. Earlier bnd files override the same named value in later bnd files.

+

Example:

+
Bundle b = lp.bundle().parent('foo.bnd').parent(WORKSPACE).start();
+
+ +

Hiding a Service

+

In some scenarios you'd like to hide a service so you can override it with a mocked version. Hiding in OSGi +can be achieved with the [Servic Hooks] services. The easiest way is to hide a service via the Launchpad Builder.

+
    LaunchpadBuilder    builder = new LaunchpadBuilder().runfw("org.apache.felix.framework").hide(SomeService.class);
+
+ +

If you now create a framework, all services not registered via Launchpad will be invisible to all bundles. That is, +only services registered through Launchpad can be seen by the other bundles in the OSGi framework.

+
@Test
+public void testHidingViaBuilder() throws Exception {
+    try (Launchpad fw = builder.runfw("org.apache.felix.framework")
+            .create()) {
+
+        boolean isHidden = fw.getServices(String.class)
+                .isEmpty();         
+        assertThat(isHidden).isTrue();
+
+        fw.framework.getBundleContext()
+                .registerService(String.class, "fw", null);
+
+        isHidden = fw.getServices(String.class)
+                .isEmpty();
+        assertThat(isHidden).isTrue();
+
+        ServiceRegistration<String> visibleToAllViaTestbundle = fw.register(String.class, "Hello");
+
+        assertThat(fw.getServices(String.class)).containsOnly("Hello");
+        visibleToAllViaTestbundle.unregister();
+
+        isHidden = fw.getServices(String.class)
+                .isEmpty();
+        assertThat(isHidden).isTrue();
+    }
+}
+
+ +

Although hiding via the Launchpad Builder is the easiest way to hide services, it has the disadvantage that all +tests hide the same service(s). It is also possible to handle the service hiding in a more controlled way +by hiding via the Launchpad object. Using this function does require a bit of orchestration. Once you hide +a service it becomes invisible to bundles that look for that service later. However, bundles that already +obtained this service will not lose sight of it. It is therefore necessary to hide a service before the +corresponding framework is started. Since the default is automatic start, the automatic start must be +disabled with the nostart() method on the builder.

+

After the framework is then created. the service is hidden and then the framework is started.

+
@Test
+public void testHiding() throws Exception {
+    try (Launchpad fw = builder.runfw("org.apache.felix.framework")
+            .nostart()
+            .create()) {
+
+        @SuppressWarnings("resource")
+        Closeable hide = fw.hide(String.class);
+        fw.start();
+
+        boolean isHidden = fw.getServices(String.class)
+                .isEmpty();
+        assertThat(isHidden).isTrue();
+
+        fw.framework.getBundleContext()
+                .registerService(String.class, "fw", null);
+
+        isHidden = fw.getServices(String.class)
+                .isEmpty();
+        assertThat(isHidden).isTrue();
+
+        ServiceRegistration<String> visibleToAllViaTestbundle = fw.register(String.class, "Hello");
+
+        assertThat(fw.getServices(String.class)).containsOnly("Hello");
+        visibleToAllViaTestbundle.unregister();
+
+        isHidden = fw.getServices(String.class)
+                .isEmpty();
+        assertThat(isHidden).isTrue();
+
+        hide.close();
+        assertThat(fw.getServices(String.class)).containsOnly("fw");
+    }
+}
+
+ +

As you can see from the test code, the hide method in this case returns a Closeable. This object can be used to +remove the hiding of the given service.

+

Visibility

+

To diagnose any issues it is important to realize that there are some special rules around which bundle does what. Launchpad +has the Bundle Context of the OSGi Framework as well as a special test bundle. The test bundle is empty but it used to have +a Bundle Context for the test code that runs outside the Framework. When you hide a service it will register +Service Hooks that only let services from the test bundle pass through, all other services of the given type are removed +from visibility.

+
Closeable Launchpad.hide(SomeService.class);
+
+ +

The service will remain hidden until you close the Closeable.

+ + diff --git a/org.bndtools.help/docs/chapters/320-packaging.html b/org.bndtools.help/docs/chapters/320-packaging.html new file mode 100644 index 0000000000..327973f32c --- /dev/null +++ b/org.bndtools.help/docs/chapters/320-packaging.html @@ -0,0 +1,12 @@ + + + + +Packaging Applications + + + +

Packaging Applications

+ + + diff --git a/org.bndtools.help/docs/chapters/330-jpms.html b/org.bndtools.help/docs/chapters/330-jpms.html new file mode 100644 index 0000000000..e530d63558 --- /dev/null +++ b/org.bndtools.help/docs/chapters/330-jpms.html @@ -0,0 +1,162 @@ + + + + +JPMS Libraries + + + +

JPMS Libraries

+

Java developers face a challenge today of building JPMS libraries, let alone when adding a secondary goal that those libraries be usable OSGi bundles. Accuracy and consistency of metadata can often become a problem reducing the time spent focusing on more productive aspect of the library.

+

A key OSGi innovation is the use of annotations to significantly reduce (in many cases to completely eliminate) the configuration needed to describe an OSGi bundle in build descriptors. See Bundle Annotations.

+

Creating JPMS Libraries with bnd

+

Just one of the additional benefits of using bnd is the ability to generate the module-info.class along side all of the traditional OSGi metadata.

+

When applying the instruction -jpms-module-info bnd will collect any relevant information and using several heuristics automatically generates the module-info.class.

+

Name, Version & Access

+

When calculating the module name the following is considered:

+
    +
  1. If the -jpms-module-info instruction contains a key, the key is used as the module name + e.g. -jpms-module-info: foo.module, the module name is foo.module
  2. +
  3. If the Automatic-Module-Name header is found in the manifest, the value is used as the module name
  4. +
  5. Otherwise, the Bundle-SymbolicName (as calculated) is used as the module name
  6. +
+

When calculating the module version, the following is considered:

+
    +
  1. If the -jpms-module-info instruction contains a key having a version attribute, the version attribute value is used as the module version + e.g. -jpms-module-info: foo.module;version=1.2.3, the module version is 1.2.3
  2. +
  3. Otherwise, the Bundle-Version (as calculated) is used as the module version
  4. +
+

When calculating the module access, the following is considered:

+
    +
  1. If the -jpms-module-info instruction contains a key having an access attribute, the access attribute value is used as the module access. Multiple comma separate values are allowed but quotes are required. + e.g. the module access is 0x0020 (OPEN): + properties + -jpms-module-info: foo.module;access=0x0020 + With multiple flags: + properties + -jpms-module-info: foo.module;access='OPEN,SYNTHETIC'
  2. +
+

Legal values are: + * OPEN or open, 0x0020, 32 + * SYNTHETIC or synthetic, 0x1000, 4096 + * MANDATED or mandated, 0x8000, 32768

+
    +
  1. If the header Require-Capability contains any capability in the osgi.extender namespace, the module access is open
  2. +
  3. Otherwise, module access is 0
  4. +
+

Note that for the above rules, the earliest matching rule wins.

+

Requires

+

When calculating the module requires the following is considered:

+
    +
  1. +

    If the -jpms-module-info instruction contains a key having a modules attribute, the modules attribute value is first split on commas (,) and each segment is added as a raw required module name + e.g. -jpms-module-info: foo.module;modules='java.desktop,java.logging', the modules java.desktop, and java.logging are added to module requires

    +
  2. +
  3. +

    In addition, if the -jpms-module-info instruction contains a key having a ee attribute, the ee attribute indicates the Java module name mapping table to use for Java SE packages using bnd's aQute.bnd.build.model.EE definitions which define a set of Java module name mapping tables keyed by EE. + e.g. -jpms-module-info: foo.module;ee=JavaSE-10, bnd will use the Java module name mapping table for Java SE 10 when determining module name for a given Java SE package

    +
  4. +
+

If no ee attribute is specified, bnd will use the Java module name mapping table for Java SE 11 when determining module name for a given Java SE package

+
    +
  1. If an imported package is associated with a module name, the module is added to module requires
  2. +
+

Note: Non-Java SE packages are associated with module names by indexing all packages on the classpath of the bnd analyzer where the providing jar's module's name is:

+ +

Requires - Access: Transitivity

+

Bnd will set the access to transitive if any package exported by the bundle has a uses constraint on a package of the required module.

+

Requires - Access: Static

+

Bnd will set the access to static if the module is specified in the -jpms-module-info instruction and does not actual have any imports.

+

Bnd will set the access to static if all the packages imported from the module are any combination of resolution:=optional, resolution:=dynamic or match the Dynamic-ImportPackage instruction.

+

Requires - Version

+

Bnd does not currently track a require's version.

+

Exports

+

Module exports will be mapped from all OSGi exported packages by default which can be managed easily with use of the Bundle Annotation @org.osgi.annotation.bundle.Export on package-info.java.

+
@org.osgi.annotation.bundle.Export
+package com.acme.foo;
+
+ +

Targeted exports (via the exports .. to .. clause) are supported with use of the @aQute.bnd.annotation.jpms.ExportTo. This annotation specifies the module name(s) to which a exported is targeted.

+
@org.osgi.annotation.bundle.Export
+@aQute.bnd.annotation.jpms.ExportTo("com.acme.bar")
+package com.acme.foo;
+
+ +

Note: The @ExportTo annotation is only relevant in conjunction with the @Export annotation.

+

Opens

+

Module opens are supported with use of the @aQute.bnd.annotation.jpms.Open annotation on package-info.java. This annotation optionally specifies the module name(s) to which the opens is targeted.

+
@aQute.bnd.annotation.jpms.Open
+package com.acme.foo;
+
+ +

Uses

+

Module uses are supported transparently with use of the bnd @aQute.bnd.annotation.spi.ServiceConsumer SPI Annotation.

+

Provides

+

Module provides are supported transparently with use of the bnd @aQute.bnd.annotation.spi.ServiceProvider SPI Annotation.

+

Main-Class

+

The module main class attribute is supported with use of the @aQute.bnd.annotation.jpms.MainClass annotation applied to the main class's Java type.

+
@aQute.bnd.annotation.jpms.MainClass
+public class Main {
+    public static void main(String... args) {...}
+}
+
+ +

Java 8 Support

+

Bnd's module-info.class generation is supported when building with Java 8 or higher. (Yes! I did say Java 8.)

+

Advanced Options

+

There are scenarios where the heuristics used by bnd don't give the desired result because the necessary information is not available or is incorrect.

+

The -jpms-module-info-options instruction provides some capabilities to help the developer handle these scenarios. The instruction uses the package header syntax similar to many other bnd instructions. The keys of these instructions are module names and there are 4 available attributes. They are:

+ +

properties + -jpms-module-info-options: java.enterprise;substitute="geronimo-jcdi_2.0_spec" + means that if bnd calculates the module name to be geronimo-jcdi_2.0_spec it should replace it with java.enterprise

+ +

properties + -jpms-module-info-options: java.enterprise;ignore="true"

+

means ignore the module java.enterprise

+ +

properties + -jpms-module-info-options: java.enterprise;static="true"

+

means make the require for module java.enterprise static

+ +

properties + -jpms-module-info-options: java.enterprise;transitive="true"

+

means make the require for module java.enterprise transitive

+

The following is an example with multiple attributes and instructions:

+
-jpms-module-info-options: \
+    java.enterprise;substitute="geronimo-jcdi_2.0_spec";static=true;transitive=true,\
+    java.management;ignore=true;
+
+ +

Exporting Executable JARs

+

Bnd's export functionality allows for the creation of executable jars which contain fully assembled applications whose only external dependency is a JDK.

+

When the -jpms-module-info instruction is used in a bndrun file that is the target of the export function the executable jar that is created will contain a generated module-info.class containing whatever information bnd's JPMS heuristics could glean from the assembly.

+

e.g.

+
-jpms-module-info: \
+    ${project.artifactId};\
+        version=${project.version};\
+        ee=JavaSE-${java.specification.version}
+
+ +

The example above produces a module-info.class whose module id comes from the property project.artifactId, version from the property project.version and ee from the property java.specification.version.

+

Launcher Main Class

+

When the -jpms-module-info instruction is used in a bndrun file that is the target of the export function bnd launcher's main class will be applied to the module info implicitly.

+ + diff --git a/org.bndtools.help/docs/chapters/390-wrapping.html b/org.bndtools.help/docs/chapters/390-wrapping.html new file mode 100644 index 0000000000..71abdb8a8b --- /dev/null +++ b/org.bndtools.help/docs/chapters/390-wrapping.html @@ -0,0 +1,424 @@ + + + + +Wrapping Libraries to OSGi Bundles + + + +

Wrapping Libraries to OSGi Bundles

+

OSGi developers face a challenge when using third-party libraries that +are not supplied as OSGi bundles. Though an increasing number of +libraries are available from their original sources as OSGi bundles, and +a large number are available as wrapped OSGi bundles from external +repositories, it is still sometimes necessary to build such a wrapper +ourselves. This technical note details an approach to OSGi bundle +production using only command line tools.

+

Introduction

+

This article details a simple and repeatable process to wrap +arbitrary Java libraries as OSGi bundles, using bnd as a command line +tool.

+

As a running example, the JDOM library version 1.1.2 will be wrapped as +an OSGi bundle.

+

NB: Many of the tasks described here can be more easily performed with a +full-featured OSGi IDE such as Bndtools. However, this document is +intended for users who perform these tasks infrequently and do not wish +to download an IDE; instead a single, lightweight +command-line tool is used.

+

Bnd generates the Import-Package statement of the output bundle via an +extremely thorough inspection of the compiled Java. Every bytecode +instruction of every class file inside the bundle is processed to +discover dependencies on external packages. Usually the result of this +inspection is more accurate than we would be able to achieve by manually +providing the Import-Package statement.

+

Unfortunately when wrapping third-party libraries it is sometimes not +sufficient to simply accept the generated Import-Package statement: +the result may need to be fine-tuned. This is because many third-party +libraries contain dependencies that are out of place, often due to +errors resulting from a lack of good modular practices.

+

For example:

+ +

Bnd detects dependencies statically by inspecting all code in the +library; it cannot determine which parts of the library are reachable. +For example a common error is to include JUnit test cases in a library +JAR, resulting in dependencies on JUnit. Unless fixed, the bundle will +only be usable in a runtime environment where JUnit is also present, +i.e., we will have to ship a copy of JUnit to our end users.

+

The problem of checking for and correcting such problems represents the +bulk of the manual effort required in what is otherwise a fairly +automatic process.

+

Initial Wrapping

+

We assume that the JDOM library has been downloaded, and jdom.jar is +available in the current directory.

+

In order to wrap as a bundle using bnd, we need an initial "recipe". +Create a file named jdom.bnd containing the following:

+
-classpath: jdom.jar
+Bundle-SymbolicName: org.jdom
+ver: 1.1.2
+-output: ${bsn}-${ver}.jar
+Bundle-Version: ${ver}
+Export-Package: *;version=${ver}
+
+ +

This is a bnd descriptor, and it instructs bnd how to generate the OSGi +bundle. To summarize the features used:

+ +

To generate the bundle: bnd reports the name of the generated file +(org.jdom-1.1.2.jar), the number of files contained (79) and its size in +bytes (151K). We refer to this bundle as the initial wrapping.

+

Examining Dependencies

+

The intial wrapping may contain dependency errors as described in the +introduction. Therefore we must examine the Import-Package statement +as generated by bnd. Unfortunately, direct viewing of the MANIFEST.MF +can be difficult due to the unusual formatting and line-wrapping rules +of the manifest file format that make it quite inaccessible. For +example:

+
$ bnd jdom.bnd
+org.jdom-1.1.2.jar 79 154490
+Import-Package: javax.xml.parsers,javax.xml.transform,javax.xml.transf
+ orm.sax,javax.xml.transform.stream,oracle.xml.parser,oracle.xml.parse
+ r.v2,org.apache.xerces.dom,org.apache.xerces.parsers,org.jaxen,org.ja
+ xen.jdom,org.jdom;version="[1.1,2)",org.jdom.adapters;version="[1.1,2
+ )",org.jdom.filter;version="[1.1,2)",org.jdom.input;version="[1.1,2)"
+ ,org.jdom.output;version="[1.1,2)",org.jdom.transform;version="[1.1,2
+ )",org.jdom.xpath;version="[1.1,2)",org.w3c.dom,org.xml.sax,org.xml.s
+ ax.ext,org.xml.sax.helpers
+
+ +

Since this is so unreadable, Bnd offers a print command that formats in +the manifest of a specified bundle JAR. We can request Bnd to print only +the imports and exports by using the -impexp switch:

+
$ bnd print -impexp org.jdom-1.1.2.jar
+[IMPEXP]
+Import-Package
+  javax.xml.parsers
+  javax.xml.transform
+  javax.xml.transform.sax
+  javax.xml.transform.stream
+  oracle.xml.parser
+  oracle.xml.parser.v2
+  org.apache.xerces.dom
+  org.apache.xerces.parsers
+  org.jaxen
+  org.jaxen.jdom
+  org.jdom                    {version=[1.1,2)}
+  org.jdom.input              {version=[1.1,2)}
+  org.w3c.dom
+  org.xml.sax
+  org.xml.sax.ext
+  org.xml.sax.helpers
+Export-Package
+  org.jdom                    {version=1.1.2, imported-as=[1.1,2)}
+  org.jdom.adapters           {version=1.1.2}
+  org.jdom.filter             {version=1.1.2}
+  org.jdom.input              {version=1.1.2, imported-as=[1.1,2)}
+  org.jdom.output             {version=1.1.2}
+  org.jdom.transform          {version=1.1.2}
+  org.jdom.xpath              {version=1.1.2}
+
+ +

Reviewing the imports, we see that most of them come +from JRE packages. However there are three groups of dependencies that +may cause problems: the Oracle XML parser; the Xerces XML parser; and +the Jaxen XPath library. Unless something is done to fix these, our JDOM +bundle will not work unless all three dependencies are present at +runtime.

+

Refining Dependencies

+

First we consider the Oracle XML parser dependency. We anticipate that +this probably derives from an optional feature, and can therefore be +considered an optional dependency. Importing a package with the +resolution:=optional directive allows our bundle to see the specified +package at runtime if an exported for it is available, but it does not +prevent the bundle from resolving in the event that an exported is not +available.

+

Indicating Optional Dependencies

+

To mark the two Oracle imports as optional, add the following line to +the jdom.bnd file:

+
Import-Package: \
+    oracle.xml.*;resolution:=optional, \
+    *
+
+ +

If we regenerate the bundle and again ask Bnd to print the imports and +exports, we will see that the Oracle dependencies are marked as +optional;

+
[IMPEXP]
+Import-Package
+  ...
+  oracle.xml.parser          {resolution:=optional}
+  oracle.xml.parser.v2       {resolution:=optional}
+  ...
+
+ +

We can do the same for the Xerces packages:

+
Import-Package: \
+    oracle.xml.*;resolution:=optional,\
+    org.apache.xerces.*;resolution:=optional,\
+    *
+
+ +

NB: the final * in the Import-Package statements is +extremely important. Without this, all other dependencies detected +by Bnd will be omitted from the final manifest.

+

Package Level Used-By Analysis

+

In some cases the root cause of a dependency is unclear, or we may wish +to obtain further information on the causes of a dependency.

+

JDOM depends on Jaxen, an XPath evaluation library. However not all +use-cases for JDOM involve evaluating XPath expressions, so this may be +an optional dependency. To get further information to help us make this +decision, we can use the Bnd print command again with the -usedby +option:

+
$ bnd print -usedby org.jdom-1.1.2.jar
+[USEDBY]
+java.sql                   org.jdom
+javax.xml.parsers          org.jdom.adapters
+...
+org.jaxen                  org.jdom.xpath
+org.jaxen.jdom             org.jdom.xpath
+org.jdom
+                                      . 
+                           org.jdom.adapters
+                           org.jdom.filter
+...
+
+ +

This tells us that the Jaxen dependencies (i.e. the +org.jaxen and org.jaxen.jdom packages) are used only from one package in +JDOM, namely org.jdom.xpath. Additionally by looking at the full results +we can see that org.jdom.xpath does not appear on the left hand side, +meaning that it is not imported by any other part of the JDOM library.

+

Splitting the Bundle

+

If we simply make our Jaxen imports optional, then a client that imports +org.jdom.xpath from the JDOM bundle will get NoClassDefFoundError or +ClassNotFoundException when it tries to use the XPath features. In +this case it is better to separate org.jdom.xpath into a new bundle. +Once separated, any client that explicitly needs the XPath features will +not resolve when the Jaxen bundle offering those features is +unavailable, which is the desired outcome: it is better to get a +resolution error than a runtime exception. Separation works in this case +because the org.jdom.xpath package has good coherency (i.e., it does +just one thing) and there are no references to it from elsewhere in +JDOM. If there were such references then the two bundles would be +tightly coupled to each other and the separation would be pointless.

+

In order to separate the bundles, we first need to omit org.jdom.xpath +from the exports of our main JDOM bundle. This is done by refining the +Export-Package statement as follows:

+
Export-Package: !org.jdom.xpath,\ *;version=${ver}
+
+ +

The leading exclamation mark can be read as "not" and it simply excludes +the named package from the generated bundle. Alternative we can just +list each package explicitly, though this requires us to repeat the +version directive on each line:

+
Export-Package: org.jdom;version=${ver},\
+  org.jdom.adapters;version=${ver},\
+  org.jdom.filter;version=${ver},\
+  org.jdom.input;version=${ver},\
+  org.jdom.output;version=${ver},\
+  org.jdom.transform;version=${ver}
+
+ +

We will also need a Bnd descriptor named jdom.xpath.bnd to generate the +JDOM XPath bundle. This is based on our original recipe:

+
-classpath: jdom.jar
+Bundle-SymbolicName: org.jdom.xpath
+ver: 1.1.2
+-output: ${bsn}-${ver}.jar
+Bundle-Version: ${ver}
+Export-Package: org.jdom.xpath;version=${ver}
+
+ +

Class Level Used-By Analysis

+

The previous used-by analysis yielded the package from which an import +dependency resulted. Sometimes we need to dig deeper and find the +individual class(es) responsible for the dependency. Unfortunately this +feature is not available from the Bnd command line, instead we have to +use a macro inside the descriptor file. To find out the class-level +causes for the dependency on the oracle.xml.parser package, add the +following temporary header to the descriptor:

+

TEMP: ${classes;IMPORTING;oracle.xml.parser}

+

This will result in a TEMP header being added to the manifest of the +output bundle. To view it, use Bnd’s print command again with the +-manifest option:

+
$ bnd print -manifest org.jdom-1.1.2.jar
+[MANIFEST org.jdom-1.1.2.jar]
+...
+TEMP                                    org.jdom.adapters.OracleV1DOMAdapter
+...
+
+ +

The output shows that the Oracle parser is used only from a single +class, strongly supporting our opinion that it is an optional +dependency. Unfortunately we cannot separate it into its own bundle +because there are several other such adapters in the same package, each +with their own dependencies. Performing the same analysis on the Oracle +parser V2 and Xerces dependencies yields similar results: individual +classes in the org.jdom.adapters package. This is poor modular design +on the part of JDOM, but we cannot fix it without breaking existing +clients. Therefore marking the dependencies as optional is the best +solution.

+

Even deeper analysis is sometimes required: e.g., do any other classes +in JDOM refer to OracleV1DOMAdapter? Such questions are best answered +by searching the source code of the library. When source code is not +available then disassembly with the javap tool or decompilation with JAD +usually helps.

+

After performing class level used-by analysis, remember to remove any +temporary headers, i.e. TEMP.

+

Excluding Imports

+

Undesirable imports can also result from "dead code", i.e. code that is +not reachable from any part of the public API of the library. For +example libraries sometimes contain JUnit test cases or old classes that +are no longer used. JDOM does not suffer from such problems, but let us +suppose for a moment that it did contain an invalid dependency on JUnit. +We could completely remove the imported org.junit package by adding an +exclusion rule to Import-Package:

+
Import-Package: \
+    oracle.xml.parser*;resolution:=optional,\
+    org.apache.xerces.*;resolution:=optional,\
+    !org.junit*,\ 
+    *
+
+ +

Exclusion rules should be used with caution, as they can cause the +bundle to produce NoClassDefFoundError. Careful used-by analysis should +be performed to ensure that the dependency really is only relevant to +unreachable code.

+

Versioning Imports

+

In this example bnd file, we do not provide the dependency JARs, bnd therefore does not +have the ability to automatically calculate the correct version of an +import because the target package is usually not visible when +the bundle is created. Therefore bnd generates imports that use the +default import version range, which in OSGi is implicitly "[0, ∞)", or +"zero to infinity" —in other words, a range that matches any version.

+

When such a wide version range is used, the bundle will normally work +initially, but will suffer problems when the API of the imported package +evolves. For example, a major new version of the imported API may +introduce breaking changes, but our bundle will still resolve against +it. This could result in errors such as IncompatibleClassChangeError, +AbstractMethodError, NoSuchMethodError, etc. Therefore we should +manually add import ranges where possible.

+

For example the JDOM version we are wrapping has been built against +version 1.1.2. The Jaxen imports can be refined by adding the following +Import-Package statement to jdom.xpath.bnd:

+
Import-Package: \
+    org.jaxen.*;version="[1.1,2)",\
+    *
+
+ +

Note the import range 1.1 through 2, exclusive of 2 — this is in +compliance with OSGi Semantic Versioning guidelines. The +API library may not follow the OSGi guidelines so sometimes an +alternative range may be required.

+

Often our biggest problem is working out which version of a dependency +library was used to build the library we are wrapping. In the case of +JDOM, we can find jaxen.jar in the lib directory of its source project +and note that its manifest indicates version 1.1.2. If the project is +built with Apache Maven we can usually find a version in the POM. Other +times we must resort to reading project documentation, if it exists.

+

Note that version ranges cannot be added for JRE packages, e.g. +javax.swing or org.xml.sax because the Java specifications do not +define the version of any of these packages, and therefore the OSGi +framework exports them all as version 0.0.0. As an alternative, add a +Bundle-RequiredExecutionEnvironment header to indicate the basic Java +level required by the bundle:

+
Bundle-RequiredExecutionEnvironment: J2SE-1.5
+
+ +

Other possible values include JavaSE-1.6, OSGi/Minimum-1.0, etc.

+

Other Concerns

+

Class References in Configuration

+

Bnd discovers package dependencies in a bundle by scanning the bytecode +of the compiled Java files. This process finds all of the static +dependencies of the Java code, but it does not discover dynamic +dependencies, for example those arising from the use of +Class.forName(). There is no generic way for Bnd to calculate all +dynamic dependencies. However there are certain well-known configuration +formats that result in dynamic dependencies, and Bnd can analyse these +formats through the use of plugins.

+

For example, some bundles use the Spring Framework for dependency +injection. Spring uses XML files that refer to fully qualified Java +class names:

+
<bean id="myBean" class="org.example.beans.MyBean">
+</bean>
+
+ +

Here the org.example.beans package is a dependency of the bundle that +should be added to Import-Package. Bnd can discover this dependency by +adding a Spring analyser plugin via a declaration in the descriptor +file:

+
-plugin: aQute.lib.spring.SpringComponent
+
+ +

Similar plugins exist for JPA and Hibernate, and custom plugins can be +written to support other configuration formats or scripting languages.

+

Summary

+

In summary the process of wrapping a JAR as an OSGi bundle is as +follows:

+
    +
  1. +

    Create the bnd descriptor, using the template in Appendix A.

    +
  2. +
  3. +

    Generate the initial wrapping and review the imports for suspicious +dependencies.

    +
  4. +
  5. +

    Fix problematic dependencies using the following heuristics:

    +
  6. +
  7. +

    if the dependency arises from a package that is coherent, has an + essential need for the dependency, and is not referred from other + parts of the bundle, separate this package into its own bundle;

    +
  8. +
  9. if the dependency arises from a small number of classes that are not + referred from other parts of the bundle, mark the dependency as + optional;
  10. +
  11. if the dependency arises from unreachable "dead code", exclude the + dependency;
  12. +
  13. +

    otherwise the dependency is probably valid and necessary, so should + be left in the bundle.

    +
  14. +
  15. +

    Add import version ranges for non-JRE imports, where possible.

    +
  16. +
+

A Template

+

The following template bnd descriptor can be used for the initial +wrapping. The placeholders on the first three lines must be filled in:

+
-classpath: <INPUT JAR(S)>
+Bundle-SymbolicName: <NAME>
+ver: <VERSION>
+-output: ${bsn}-${ver}.jar
+Bundle-Version: ${ver}
+Export-Package: *;version=${ver}
+# Uncomment next line to customize imports. The last entry MUST be "*"
+# Import-Package: *
+
+ + diff --git a/org.bndtools.help/docs/chapters/395-generating-documentation.html b/org.bndtools.help/docs/chapters/395-generating-documentation.html new file mode 100644 index 0000000000..4d7998f307 --- /dev/null +++ b/org.bndtools.help/docs/chapters/395-generating-documentation.html @@ -0,0 +1,86 @@ + + + + +Generating Documentation + + + +

Generating Documentation

+

Bnd can help you to maintain your projects' documentation up-to-date. +In a best effort, Bnd can automatically update your documentation according to changes in your programs. +Whenever it is not possible, you still have an easy way to edit the documentation manually.

+

The process is in two steps: first, Bnd will analyze your projects and your bundles to +collect and aggragate relevant data into an intermediate format (json or xml). Then, +it will process the data with a template file (xslt or twig) to generate the documentation.

+

Relevant data are the OSGi headers, the configuration of your services, code snippets that you write +with the help of your IDE, your Gogo commands, etc. Once they are collected you have three ways to use them:

+
    +
  1. You can export the intermediate data into a file. You can then use the exported file with any external +tool (such as Jekyll to generate a static site for example).
  2. +
  3. You can define your own documentation files and provide your own templates, Bnd can then directly export the final files.
  4. +
  5. You can use built-in documentation templates. In this latter case, you have no mandatory configurations to provide and updating +the documentation is done by executing a simple command.
  6. +
+

This feature is available for the Bnd Workspace Model and Maven projects respectivly using Bnd CLI and bnd-reporter-maven-plugin. We will use +Bnd CLI as an example in the next sections, you can directly look at the documentation in the Github repository for the corresponding feature with Maven.

+
+

Note: It is necessary that the workspace is completely built before generating the documentation files to take into account the latest changes.

+
+

Generating custom documentation

+

Custom documentations are configured with the -exportreport instruction. +This instruction defines a list of reports which can then be exported with the exportreport export subcommand.

+

For example, executing bnd exportreport export on a project with the following configuration:

+

bnd.bnd

+
-exportreport: metadata.json, info.html;template=https://.../mytemplate.xslt
+
+ +

will export two files: metadata.json (intermediate data) and info.html (final documentation file).

+

Generating built-in documentation

+

Readme files

+

With the exportreport readme subcommand you can generate a set of README files. +If this command is applied on a workspace, a readme.md file will be generated into the workspace folder as well as one +readme.md file for each project. If a project builds multiple bundles, additional readme.<bsn>.md will be generated for each +bundle built.

+

Manual edition

+

In case you want to customize the README files with your own text, you have to create a readme.twig file next to the readme.md file that you wish to customize.

+

The simplest way to proceed is to copy-paste the following snippet into this file:

+
Write your own markdown text here.
+
+ +

Inside an embed tag one can only specify block tags which will override the parent template included. +Here, the parent template is the readme template file built-in into Bnd available at the default:readme.twig URL (see the file here). This file defines a set of blocks that you can override with your own text. +In the above snippet, we override the beforeTitle block. You can add multiple blocks depending on where you want to insert your text, here is a list of available blocks:

+ +

before* blocks are shown between the title of a section and the generated content. after* blocks are shown at the end of a section, after the generated content.

+

Parameters

+ + + + + + + + + + + + + + + +
NameDescriptionDefault value
iconUrlURL to an icon that will be shown in front of the title""
+ + diff --git a/org.bndtools.help/docs/chapters/400-commands.html b/org.bndtools.help/docs/chapters/400-commands.html new file mode 100644 index 0000000000..3bdfd556e6 --- /dev/null +++ b/org.bndtools.help/docs/chapters/400-commands.html @@ -0,0 +1,52 @@ + + + + +bnd CLI Commands + + + +

bnd CLI Commands

+

The command line interface (bnd CLI) provides various tools to invoke bnd functions and features. It is using bndlib under the hood just like other tooling like bndtools, maven or gradle plugins do too.

+

Checkout the tutorial which makes use of the CLI.

+

Installation

+

See here to install the CLI.

+

Use

+

The bnd CLI can be invoked in several different ways:

+ +

In this text bnd is used as if it is a command line program. This should be set up as:

+

java -jar .jar ...

+

General Options

+

||General Option ||Description || +||--debug ||Show log debug output|| +||--failok ||Turns errors into warnings so command always succeeds || +||--exceptions ||Will print the exception when the software has ran into a bad exception and bails out. Normally only a message is printed. For debugging or diagnostic reasons, the exception stack trace can be very helpful. ||

+

Show list of all options for the bnd CLI.

+

Reference

+
+ +
+ + + + + + + + + + + + + + + +
pageDescriptionClass
+
+
+ + diff --git a/org.bndtools.help/docs/chapters/600-developer.html b/org.bndtools.help/docs/chapters/600-developer.html new file mode 100644 index 0000000000..e690baab2a --- /dev/null +++ b/org.bndtools.help/docs/chapters/600-developer.html @@ -0,0 +1,70 @@ + + + + +For Developers + + + +

For Developers

+

API

+

It is quite easy to use bnd from Java, you only need to include biz.aQute.bndlib on your class path. This chapter shows you some samples of how to use bndlib.

+

Creating a Manifest

+

By default, bnd creates a container with resources and then calculates the manifest. However, these phases are separated although they use the same instructions. The following snippet therefore shows how you can create a manifest from an existing file or directory.

+
Analyzer analyzer = new Analyzer(); 
+Jar bin = new Jar( new File("bin") );  // where our data is
+analyzer.setJar( bin );                // give bnd the contents
+
+// You can provide additional class path entries to allow
+// bnd to pickup export version from the packageinfo file,
+// Version annotation, or their manifests.
+analyzer.addClasspath( new File("jar/spring.jar") );
+
+analyzer.setProperty("Bundle-SymbolicName","org.osgi.core");
+analyzer.setProperty("Export-Package", 
+                   "org.osgi.framework,org.osgi.service.event");
+analyzer.setProperty("Bundle-Version","1.0");
+
+// There are no good defaults so make sure you set the 
+// Import-Package
+analyzer.setProperty("Import-Package","*");
+
+// Calculate the manifest
+Manifest manifest = analyzer.calcManifest();
+
+public interface MakePlugin {
+/**
+ * This plugin is called when Include-Resource detects 
+ * a reference to a resource that it can not find in the 
+ * file system.
+ * 
+ * @param builder   The current builder
+ * @param source    The source string (i.e. the place 
+ *                  where bnd looked)
+ * @param arguments Any arguments on the clause in 
+ *                  Include-Resource
+ * @return          A resource or null if no resource 
+ *                  could be made
+ * @throws Exception
+ */
+Resource make(Builder builder, String source, 
+      Map<String,String> arguments) throws Exception;
+}
+
+ +

Make

+

Make plugins kick in when the Include-Resource header tries to locate a resource but it cannot find that resource. The -make option defines a number of patterns that are mapped to a make instruction.

+

For example, if you have

+
Include-Resource:       com.acme.Abc.ann
+
+ +

If no such resource is found, bnd will look in the -make instruction. This instruction associates a pattern with a plugin type. For example:

+
-make:                  (*.jar); type=xyz; abc=3; def="$1"
+
+ +

The first name part of the clause is matched against the unfound resource. All plugins are called sequentially until one returns non-null. The arguments on the -make clause are given as parameters to the make plugin. Normally all Make Plugins should verify the type field.

+

bnd has a bnd and a copy Make Plugin.

+

Workspace Template Fragments

+

If, for example, you created a library for bnd and want to make it easy for the user to setup his functionality have a look at template fragments.

+ + diff --git a/org.bndtools.help/docs/chapters/620-template-fragments.html b/org.bndtools.help/docs/chapters/620-template-fragments.html new file mode 100644 index 0000000000..f706a15d34 --- /dev/null +++ b/org.bndtools.help/docs/chapters/620-template-fragments.html @@ -0,0 +1,129 @@ + + + + +Templates for Workspaces + + + +

Templates for Workspaces

+

A good workspace setup makes all the difference in the development cycle. Since a workspace can +contain many projects, creating new workspaces is relatively rare. However, a workspace tends +to consist of many aspects. There is the gradle setup, the OSGi release, maybe the maven +layout etc. Initially, we attempted to use a single GitHub repository as a template for new workspaces, but this approach quickly became complex.

+

For example, if someone created a library for bnd, to make it easy for the +user to setup his functionality, the author of the library had to maintain a full workspace +with gradle, etc. This put the burden on chasing the OSGi release, the gradle releases, on the +people that were willing to spread the gospel around OSGi/bndtools.

+

Template Fragments

+

Instead, we developed fragment templates. A fragment models one aspect of a workspace and is maintained in Github repository, but one repository can hold many fragments. Multiple template fragments can be combined by the end-user to enrich the workspace with various aspects. +During workspace creation there is a wizard where one can select template fragments via checkboxes.

+

+

Official templates from the bndtools Github organisation are shown with a green checkmark. +Non-official templates from 3rd-party authors are shown with a yellow exclamation mark.

+
+
Note: Check templates before installation
+

Make sure you carefully check templates beforehand, since this is content from potentially untrusted sources which is downloaded to your computer. +You should double click on an entry to open the Github repostory of that template in your browser. +This allows you to examine the content which is about to be downloaded to your workspace when you press finish. If you select at least one 3rd-Party template a confirmatin popup asks you to confirm, if you trust the authors. +{: .block-warning }

+
+

The workspace is already prepared for this model of fragments. The merged instructions mean that +we can extend the properties and instructions from many different sources. However, the most important +feature here is the cnf/ext folder. Any bnd or special fragment file placed in this folder will automatically +be ready before the build.bnd file is read. For example, a fragment could contain the +index for OSGi R8. See build.

+

Providing template fragments as a developer

+

There is a single master index for all template fragments hosted on

+

https://github.com/bndtools/workspace-templates/blob/master/index.bnd

+

This index is open for any person or organization that maintains one or more fragment and +seeks an easy way to make them available to bndtools users. All that is needed is to host the fragment somewhere and provide +a pull request (PR) to add it to this index file.

+

The format of the index file is like all Parameters.

+ +

The id is resolved against bndtools/workspace-templates#master. Therefore, in the example organization, +the example is a valid id that resolves to example/workspace-templates#master. Since the ID has a path, +it is possible to host multiple fragments in a single repository. +Instead of a branch name like #master as git-ref you could also point to a specific commit via its SHA e.g. #567648ff425693b27b191bd38ace7c9c10539c2d.

+

The index has the following attributes for a clause:

+ +

Example

+

For example consider this index.bnd:

+
-workspace-templates \
+    bndtools/workspace-templates/gradle; \
+        name=gradle; \
+        description="Setup gradle build for bnd workspace", \
+    bndtools/workspace-templates/maven#master; \
+        name=maven; \
+        description="Use the maven directory layout for sources and binaries", \
+    bndtools/workspace-templates/osgi#master; \
+        name=osgi; \
+        description="OSGi R8 with Felix distribution",\
+    acme-org/myrepo/subfolder/workspace-template#commitSHA; \
+        name=3rdparty-template; \
+        description="A Template fragment by acme-org at a specific commit SHA"
+
+ +

The id must resolve to a folder in the repository, and can be translated to github URLs:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
IDURL
bndtools/workspace-templates/gradlehttps://github.com/bndtools/workspace-templates/tree/master/gradle
bndtools/workspace-templates/maven#masterhttps://github.com/bndtools/workspace-templates/tree/master/maven
acme-org/myrepo/subfolder/workspace-template#otherbranchhttps://github.com/acme-org/myrepo/tree/otherbranch/subfolder/workspace-template
acme-org/myrepo/subfolder/workspace-template#567648ff425693b27b191bd38ace7c9c10539c2dhttps://github.com/acme-org/myrepo/tree/567648ff425693b27b191bd38ace7c9c10539c2d/subfolder/workspace-template
+

By default, bnd will recursively copy the +content to the new workspace. However, if there is a file tool.bnd present it will use this to +guide the copying process. This bnd file looks like:

+
-tool \
+    .*;tool.bnd;readme.md;skip=true, \
+    gradle.properties;macro=true;append=true,\
+    gradlew;exec=true, \
+    *
+
+ +

The -tool instruction is a SELECT that is matched against the file paths (not names!) in the fragment template folder. +The attributes that can be set are:

+ +

It is possible to define the -workspace-templates instruction in the build.bnd file. +It must contain the same format as the index. This local index is merged with the main index. In the

+

Bndtools GUI, it is possible to add an additional index from a URL or file via the '+' button. +For example you can directly point to a Github URL like: +https://raw.githubusercontent.com/bndtools/workspace-templates/567648ff425693b27b191bd38ace7c9c10539c2d/index.bnd

+ + diff --git a/org.bndtools.help/docs/chapters/650-windows.html b/org.bndtools.help/docs/chapters/650-windows.html new file mode 100644 index 0000000000..435a761d53 --- /dev/null +++ b/org.bndtools.help/docs/chapters/650-windows.html @@ -0,0 +1,58 @@ + + + + +Tips for Windows users + + + +

Tips for Windows users

+

Bnd and Bndtools runs on any system that can run Eclipse. However, every operating system is different and has its own quirks. Windows in particular has a few that impact developers using Bnd. While the Bnd experience may never be as smooth on Windows as it is on macOS or Linux, there are a few tweaks that make it a lot smoother than what comes out of the box.

+

It is possible that some of the tips listed here will also help for Eclipse development work in general, or perhaps any development work on Windows.

+

Key problems on Windows

+

Windows has two key architectural differences to *nix-based OSes that really impact development work in Java:

+

File locking

+

Most *nix systems use advisory file locking, rather than mandatory locking. Windows uses mandatory locking rather than advisory. Most Java programs are developed on *nix and tend to assume *nix locking semantics. This means that they are not as careful at cleaning up after themselves and ensuring that file locks are released.

+

In particular, there are problems when an application exits using System.exit() - the normal way for Java applications to clean up is to release a lock is in a finally clause. However, when an application calls System.exit(), these normal channels are bypassed, which means the JVM never gets a chance to release the locks and hence can't delete the locked files.

+

Real-time protection

+

From version 10, Windows' built-in anti-malware program Windows Defender has become very tightly integrated with the OS - seemingly, it is written into the Windows kernel API IO functions themselves, which means it's nearly impossible to bypass. This makes it extremely well suited to catching malware in the act. Unfortunately, it means it slows down every file write. When you are writing lots of small files, this delay is significant.

+

Workarounds and solutions

+

Use Bnd 5+

+

Prior to Bnd 5.0, there was a bug that caused the launcher to pause for several seconds if you had -runtrace enabled. This bug has been fixed as of 5.0 (currently in pre-release at the time of writing), so it is worthwhile upgrading to use 5.0 if you are able.

+

Manually clean up temp files

+

Due to file locking issues, Bnd on Windows will always copy bundles into a newly launched application rather than referencing them (see -runnoreferences). This copy can run to a few hundred megabytes.

+

Again due to file locking (and its overuse of System.exit()), Bnd is not very good at cleaning up temporary files on Windows after it exits. So usually, the application folders are left behind after the launched application exits.

+

A few hundred megabytes per launch starts to add up, and if you're running off a relatively small SSD you can find yourself running out of disk space.

+

It is recommended that you periodically clear out these files from your temp directory. By default, the temp directory is in %UserHome%\AppData\Local\Temp. OSGi temp dirs created by Felix typically have the pattern: osgi.nnnnnnnnnnnnnnnnn.fw. Depending on which OSGi framework and which Java utilities you are using in your app, there may be others to look out for - if you are using a custom temp dir (see below), then you can simply clear out the entire directory.

+

Turn off/filter real-time malware protection

+

You can turn off real-time malware protection in Windows settings. However, Windows 10 will only allow this situation to persist for a short time (perhaps 24 hours) before automatically turning it back on again. Also, this approach leaves your entire system without any real-time protection.

+

A better solution is to disable antivirus scanning for specific directories. You can find instructions on how to do this here. For maximum benefit, you should exclude: +* your Bnd workspace; +* the corresponding Eclipse workspace; and +* your temp directory (by default: %UserHome%\AppData\Local\Temp). +However, excluding your temp directory might be a bit of a security hole as it is likely to be a place where malware will try and write first. If you are concerned about this, see the next section +for a workaround.

+

It is possible that excluding other directories may help performance, as Windows Defender +seems to take a keen interest in jar files. Some examples: +* your .m2 directory (usually found in your home directory); +* the P2 repository for your local Eclipse installation. This is either in your Eclipse + root directory, or else in %UserHome%\.p2 directory if you have installed it using + the P2 bundle pool. +* any other local repositories you might be using in your workspace (that are not already + covered by one of the above exclusions).

+

Be wary that each additional exclusion you add increases the security risk. You need to weigh the performance benefits of excluding each folder vs the increase in security risk.

+

Create a custom temp directory

+

As noted above, for best performance you should exclude the temp directory, however for best safety you may not wish to. A good compromise is:

+ +

As an added bonus, this makes cleaning up the remaining temp files much easier as you can safely delete the entire directory, knowing that no other applications are using the directory.

+

Use a RAM disk

+

If you've got an SSD, the above tips should suffice to get good performance. On one test, launching the Bndtools test Eclipse instance itself (with over 200 bundles) took ~2s to install all the bundles for a running Eclipse instance.

+

However, if you're using a slower hard disk and you have enough RAM (at least 8GB), you may also consider configuring a small RAM disk of around 1GB and putting your temp directory on the RAM disk. There are a few free RAM disk utilities available for Windows.

+

You can also easily clear out the accumulated temp files by unmounting and re-mounting the RAM disk.

+ + diff --git a/org.bndtools.help/docs/chapters/700-tools.html b/org.bndtools.help/docs/chapters/700-tools.html new file mode 100644 index 0000000000..5884dce52b --- /dev/null +++ b/org.bndtools.help/docs/chapters/700-tools.html @@ -0,0 +1,22 @@ + + + + +Tools bound to bnd + + + +

Tools bound to bnd

+

Reference

+
+ +
+ +

If you're a developer of a tool that needs to be listed here, do not hesitate to submit a pull request at github.

+ + diff --git a/org.bndtools.help/docs/chapters/790-reference.html b/org.bndtools.help/docs/chapters/790-reference.html new file mode 100644 index 0000000000..67a847deca --- /dev/null +++ b/org.bndtools.help/docs/chapters/790-reference.html @@ -0,0 +1,33 @@ + + + + +Reference + + + +

Reference

+

The subsequent sections provide the reference part of the manual. This consists of the following:

+ +

Since bnd is a library, it gets used in many different places. This makes some of the headers, instructions, and/or +macros only applicable in a specific context. This is generally indicated on a page with a class button on the right +side. For example:

+
+Project +
+ +

The following classes are used:

+ +

Usually the format of both headers and instructions follows the Java properties files specification outlined in Concepts.

+ + diff --git a/org.bndtools.help/docs/chapters/800-headers.html b/org.bndtools.help/docs/chapters/800-headers.html new file mode 100644 index 0000000000..90b47888c6 --- /dev/null +++ b/org.bndtools.help/docs/chapters/800-headers.html @@ -0,0 +1,37 @@ + + + + +Headers + + + +

Headers

+

Learn the basics of bnd headers on the Generating JARs page.

+
+ +
+ +
+ + + + + + + + + + + + + + + +
pageDescriptionClass
+
+ +
+
+ + diff --git a/org.bndtools.help/docs/chapters/820-instructions.html b/org.bndtools.help/docs/chapters/820-instructions.html new file mode 100644 index 0000000000..508dfb7ca2 --- /dev/null +++ b/org.bndtools.help/docs/chapters/820-instructions.html @@ -0,0 +1,366 @@ + + + + +Instruction Reference + + + +

Instruction Reference

+

A bnd instruction is a property that starts with a minus sign ('-'). An instruction instructs bndlib to do something, in general providing parameters to the code. All instructions in bndlib are listed later in this page.

+

All instructions are listed on the Instruction index

+

Syntax

+

Almost all bndlib instructions follow the general OSGi syntax. However, the bndlib syntax is in general a bit more relaxed, for example you can use either single quotes (''') or double quotes ('"') while OSGi only allows double quotes. Dangling comma's and some other not exactly correct headers are accepted by bndlib without complaining. Values without quotes are accepted as long as they cannot confuse the general syntax. For example, a value like 1.20 does not have to be quoted since the period ('.') cannot confuse the parser on that place, however, a value like [1.3,4) must be quoted since it contains a comma.

+

In this mannual we adhere to the same conventions as the OSGi specification. This is mostly reflected in the names for the terminals in the syntax specifications. As a reminder we repeat the syntax rules and common terminals:

+ +

The following terminals are pre-defined:

+
ws               ::= <see Character.isWhitespace> 
+digit            ::= [0..9]
+alpha            ::= [a..zA..Z]
+alphanum         ::= alpha | digit
+token            ::= ( alphanum | '_' | '-' )+
+number           ::= digit+
+jletter          ::= <see [JSL][1] for JavaLetter>
+jletterordigit   ::= <See [JLS][1] for JavaLetterOrDigit >
+qname            ::= <See [JLS][1] for fully qualified class name >
+identifier       ::= jletter jletterordigit *
+extended         ::= ( alphanum | '_' | '-' | '.' )+
+quoted-string-d  ::= '"' ( ~["\#x0D#x0A#x00] | '\"'|'\')* '"'
+quoted-string-s  ::= ''' ( ~['\#x0D#x0A#x00] | '\''|'\')* '''
+quoted-string    ::= quoted-string-s | quoted-string-d  
+special-chars    ::= ~["\#x0D#x0A#x00:=;,<See [JLS][1] for whitespace>]
+path             ::= special-chars+ | quoted-string
+value            ::= quoted-string | path
+argument         ::= extended  | quoted-string
+parameter        ::= directive | attribute
+directive        ::= extended ':=' argument
+attribute        ::= extended '=' argument
+parameters       ::= parameter ( ',' parameter ) *
+unique-name      ::= identifier ( '.' identifier )*
+symbolic-name    ::= token('.'token)* 
+package-name     ::= unique-name
+
+version          ::= major( '.' minor ( '.' micro ( '.' qualifier )? )? )?
+major            ::= number 
+minor            ::= number
+micro            ::= number
+qualifier        ::= ( alphanum | '_' | '-' )+
+
+version-range    ::= interval | atleast
+interval         ::= ( '[' | '(' ) floor ',' ceiling ( ']' | ')' )
+atleast          ::= version
+floor            ::= version
+ceiling          ::= version
+
+ +

White spaces between terminals are ignored unless specifically noted. The only exception is the directive, a directive must be connected to the colon (':'). That is, bndlib stores attributes and directives in the same map and distinguishes them by the fact that directives end in a colon and attributes do not. For example, using a directive like foo; path := https://www.xyz.com will not work correctly because the path : is not a valid attribute nor directive name. Any value that contains a space, a tab, a comma, colon, semicolon, equal sign or any other character that is part of a terminal in the grammar must be quoted.

+

Almost all bndlib instructions follow the general OSGi syntax for a header.

+
-instruction     ::= parameters
+parameters       ::= clause ( ',' clause ) *
+clause           ::= path ( ';' path ) *
+                          ( ';' parameter ) *
+
+ +

There are a number of short-cuts that are regularly used in bnd commands:

+
list             ::= value ( ',' value ) *
+url              ::= <URL>
+file-path        ::= <file path, using / as separator>
+
+ +

Merged Instructions

+

Most instructions that accept multiple clauses are merged instructions. A merged instruction is an instruction which is specified by its prefix but which will merge any property that starts with this prefix followed by a period ('.'). For example, the base instruction -plugin instruction accepts -plugin.git as well. The reason for this merging is that allows to append the base instruction with instructions from other files. For example, the bnd file in the cnf/ext directory are automatically included in the properties of the workspace. Since there can be many files, there would be a need to coordinate the using of a singleton base instruction. As always, singletons suck and in this case we solved it with merged instructions.

+

Some instructions put, sometimes very subtle, semantics on their ordering. To prevent different results from run to run, we make order the merge properties by placing the base instruction in front and then followed by the values from the other keys in lexically sorted order. For example, -a, -a.x, and -a.Z, and -a.1 will concatenate the clauses in the order -a,-a.1,-a.Z,-a.x.

+

Each of the constituents of the merged properties can be empty, this is properly handled by bndlib and will not create a an empty clause as would easily happen when the same thing was done with macros. Empty clauses can help when there is an optionality that depends on some condition.

+

As an example, lets set the -buildpath instruction:

+
-buildpath: com.example.foo;version=1.2
+
+-buildpath.extra: ${if;${debug};com.example.foo.debug\;version=1.2}
+
+ +

This will result in a buildpath of (when debug is not false) of: com.example.foo;version=1.2, com.example.foo.debug;version=1.2.

+

Decorated Instructions

+

Instructions can also be decorated. A decorator is a header that ends with + or ++. A header like -runbundles is first merged and then decorated.

+

In this case, -runbundles is the stem. First, the total header is assembled by merging the property that has that stem. If there are properties that match stem + +.* or ++.*, then these properties are used to decorate the merged property. Notice that for the decorator the root key includes the + sign, the suffixes must come after the + sign. For example, for the header foo, the decorator would be foo+ and that would match a key like foo+.bar.

+

The decorator is a Parameters, it consists of a key and a set of attributes. The decorator key is usually a glob expressions.

+

After the header is merged, the key of each entry is matched against all globs in the decorator following the order of the decorator. When the first match is found, the attributes of the decorator clause that matches are stored with the attributes of the Parameter entry, overriding any attribute with the same attribute key. A Parameter entry key can only match one decorator glob expression.

+

For example, -runbundles a and -runbundles+ *;startlevel=20 will result in the content a;startlevel=20.

+

If the name of the decorator clause attribute starts with !, then the attribute, using the attribute name after removing the leading !, is removed from the Parameter entry. If the name of the decorator clause attribute starts with ~, then the decorator clause attribute value will not overwrite an existing value of the Parameter entry attribute, using the attribute name after removing the leading ~.

+

Example:

+
 -foo       a, b, c;skip=true, d
+ -foo+      b;skip=true,c;skip=false
+ -foo+.d    d;skip=true
+
+ +

In this case, the first entry matched is b and it is matched against the second entry in the -foo instruction. Since the decorator has the skip=true attribute, it is carried over to the instruction. The result is therefore:

+
a, b;skip=true; c;skip=false, d;skip=true
+
+ +

If the decoration ends with 2 plus signs, for example -foo++, then the literals in the decoration headers will be added to the result if they are not matched to any key in the source header. If the decoration ends with a single + sign, literals that do not match are ignored.

+ +

SELECTOR

+

If a value in an instruction has a scope then you will be able to use a selector. A scope is a well defined, finite, set. For example, if you use the '-exportcontents' instruction you can specify the packages that can be exported. Since you can only export the packages that are inside your bundle, the scope is the set of package names that were collected so far.

+

The syntax for a selector is:

+
selector ::= '!' ? 
+             '=' ?  
+                  '*' | ( '.' | '?' | '|' | '$' | . | other ) * 
+             ( '.*' ) ? 
+             ( ':i' | ':o' | ':io' ) ?
+
+ +

A selector is an expression that is matched against all members of the scope. For example, com.example.* will match any package name that starts with com.example, for example com.example.foo, as well as com.example itself. The syntax used to describe the wildcarding is based on a globbing kind model, however, the selector is translated into a regular expression according to some simple rules.

+

The replacement rules to build the regular expression are as follows:

+ +

If you want to go ballistic with regular expressions, then you can go ahead. As long as the wildcards are triggered by one of the defined characters, the replaced string will be used as a regular expression.

+

If the selector ends with :i then a case insensitive match is requested, this will ignore any case differences. +If the selector ends with :o then the selector is marked optional. This means that when Bnd might warn about unused selectors, it will not warn that an optional selector is unused. +You can specify both flags by ending the selector with :io.

+

A selector can be prefixed with an exclamation mark, this indicates that a match must be treated as a removal operation. To understand removal, it is necessary to realize that the selectors are not declarative, the order of the selectors is relevant.

+

When bndlib has a scope, it will iterator over each element in the scope and then for element it will iterator over each selector. If there is a match on the scope member then it is always removed from the scope, it will not be matched against later selectors. If the selector starts with an exclamation mark then the member is removed. but it is not treated as a result. Ergo, the exclamation mark allows you to remove members before they are actually matched.

+

For example, you want to match all implementation packages (i.e. they have impl in their name) except when they start with com.example. This can be achieved with:

+
!com.example.*impl*, *.impl.*
+
+ +

Last, and also least, you can prefix the selector with an equal sign ('=') (after the exclamation mark if one is present). This will signal a literal match with the string, no globbing will be done.

+

The way the period ('.') is treated is kind of special. The reason is that people expect that the selector com.example.* actually includes the package com.example itself. In bndlib this has always been the case although the OSGi Alliance later decided to not follow this pattern when there was a need for the globbing of packages.

+

In this example, the first selector will remove any match and ignore it, the second selector now only sees scope members that are fitting in the earlier pattern.

+

Selectors are used in virtually any place where there is a reasonable scope. It is a very powerful feature. However, it is also easy to go overboard. If you find you need to use this feature excessively then you are likely overdoing it.

+

FILE

+

One of the most painful thing in making bndlib run anywhere is handling of files. Even though Java has a decent abstraction of the file system, problems with spaces in file names and backslashes in the wrong place have caused an uneven amount of bugs. Ok, this partially because most bndlib developers tend to use Macs, still no excuse and quite embarrassing.

+

Since bnd files need to be portable across environments we've chosen to use the Unix file separator, the slash (or solidus '/') for more reasons than I can reasonably sum up here (what was Bill smoking when he picked the reverse solidus for file separator!). In bndlib, all file paths (ok, should) always go through a single method that actually parses it and turns it into a Java File object. This allows us to support a number of features in a portable way. The syntax of a file path is therefore:

+
file      ::=  ( '~/' | '/' )?  (  ~['/']+ '/' ) * ~['/'] *
+
+ +

If a file path starts with:

+ +

You can use the '..' operator for a segment in the file path to indicate a parent directory. It is highly advised to always use relative addressing to keep your workspace portable. However, there are a number of macros that can be used as anchors:

+ +

FILESPEC

+

A FILESPEC defines a set of files relative to a starting point. It can be identical to a FILE for a single file but it has some special syntax to recurse directories. For example, the FILESPEC foo/bar/**/spec/*.ts finds all files that end in spec/*.ts somewhere below the foo/bar directory.

+

The syntax is as follows:

+
FILESPEC  ::= filespec ( ',' filespec )*
+filespec  ::= ( segment '/' ) filematch
+segment   ::= '**' | GLOB
+filematch ::= '**' | '**' GLOB | GLOB
+
+ +

If a segment is ** then it will match any directory to any depth. Otherwise it must be a GLOB expression, which can also be a literal. The last segment is the filematch. This is a GLOB expression on a file name. As a convenience, if it is **, any file will match in any directory and if it starts with something like **.ts then it will also recurse and match on *.ts. That is, the following rules apply to the filematch:

+
prefix/**              prefix/**/*              
+prefix/**.ts           prefix/**/*.ts
+
+ +

PATH

+

A PATH is a repository specification. It is a specification for a number of JARs and/or bundles from a repository (well, most of the time). A PATH has the following syntax:

+
PATH      ::= target ( ',' target ) *
+target    ::= ( entry | FILE ';' 'version' '=' 'file' )
+              ( ';' PARAMETERS ) *
+entry     ::= symbolic-name ( ';' version ) ? 
+version   ::= 'version' '=' 
+              ( RANGE | 'latest' | 'project')
+
+ +

A PATH defines a number of bundles with its entries. Each entry is either a FILE or a symbolic-name. If only a symbolic name is specified, the default will be the import range from 0.0.0. This selects the whole repository for the given symbolic name. Outside the default, the repository entry can be specified in the following ways:

+ +

GLOB

+

A glob is a pattern that can be matched against a candidate to see if it matches. To match multiple candidates with +one pattern, the pattern is allowed to contain wildcard characters. A wildcard character is a stand in for zero or +more other characters. For example, a glob like *.xml matches any name that ends with .xml, the asterisk * stands +in for zero or more characters. Therefore, it matches foo.xml, xml.xml.xml, but also just .xml. The other +wildchar is the question mark (?) which matches exactly one character. For example, ???.xml matches abc.xml but not a.xml +or .xml.

+

Sometimes it is necessary to match against a number of strings. The vertical bar (|) can separate these strings. For +example, abc|def|ghi matches any of abc, def, or ghi.

+

It is also possible to group strings inside the pattern using parentheses. For example, foo(a|b)bar matches fooabar +or foobbar.

+

The glob also supports character classes with the square brackets [ and ]. Characters between the square brackets +literally match to any character at that position. These character classes also form a group. For example, foo[abc]bar matches +fooabar, foobbar, or foocbar.

+

Groups can be repeated using a question mark (cardinality 0..1), the asterisk (cardinality 0..n), or the plus sign (cardinality 1..n). For example, (a)* +matches aaaa but also the empty string. If the standard cardinalities do not suffice, then a group can be suffixed by a +cardinality specification using the curly braces ({ and }). Inside the curly braces the lower bound and the optional upper +bound can be specified. If no upper bound is specified then the lower bound is also the upper bound. +For example, (?i)([0-9A-F][0-9A-F]){20} matches a 40 digit SHA digest in hex regardless of case.

+

There are some special characters that get special treatment:

+
special ::= '{' | '}' | '|' | '+' | '*' | '?' | '(' | ')' | '[' | ']'
+
+ +

These characters can be escaped with a reverse solidus (\) to override their special meaning, they will then be matched literally. To +escape a long string, it is possible to place \Q at the beginning of a block that needs to be escaped and \E at the end. +For example, foo\Q*****\Ebar

+

Some examples:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobRegular ExpressionMatches
abc.tsabc\.tsabc.ts
*.ts.*\.tsabc.ts, def.ts
foo***barfoo.*.*.*barfoobar, fooXbar, fooXXXXbar
foo(A|B|C)*barfoo(A|B|C)*barfooAbar, fooBBBAbar,fooCbar
foo\{\}barfoo\{\}barfoo{}bar
xx(?i)xxxx(?i)xxxxXx, xxXX, xxxx
+

Special Cases

+

Some instruction use the GLOB but provide some convenience. For example, the package selectors of Export-Package et. al. +detect a case like com.example.* and turn it into a regular expression that matches com.example.foo but also matches +com.example. This is generally explained in the instruction.

+

Mapping a Glob to a Regular Expression

+

This section defines how globs are mapped to regular expressions. Although the globs are quite intuitive to use, +they do expose all regular expression capabilities. A strong advice is to keep it simple. The mapping itself +is actually non-trivial and takes a number of heuristics that can easily go wrong. Basically, if you need this +section you're likely doing something that is too complex.

+

For backward compatibility reasons, we support the unix like glob style for or'ing like {a,b,c}. However, it is +recommended to use the form using the vertical bar since it is more flexible and closer to regular expressions.

+

A glob is mapped to a regular expression character by character. During this traversal the following states are kept:

+ +

Character sets:

+
escaped     ::= `.` | `$` | `^` | `@` | `%`
+special     ::= `?` | `*` | `+`
+end         ::= ')' | ']' | '}'
+start       ::= '('
+
+ +

Escaped characters are escaped in SIMPLE mode and CURLIES mode. In QUOTED or BRACKETS mode no escaping is done. For example +^$ becomes \^\$ matching literally ^$. However, [^$] becomes [^$], matching anything but a dollar sign. In QUOTED +and BRACKETS mode, also the special, end, and start sets are directly inserted without any special handling.

+

In the SIMPLE and CURLIES mode the special characters require special handling. For these remaining mappings it is important +to realize that there are groups. There are parenthesized groups, bracketed group, and curly braces groups. For +example, (a|b), [abcd], or {a,b,c} respectively. If curly braces are used after a group then it is a quantifier and not considered a group. That is, {a,b} is +considered a group but [a,b]{1,2} then the {1,2} is a quantifier and not a group.

+

So when a special character is preceded with a group, it is inserted without any special processing. If it is not +preceded then the following rules apply:

+ +

Some examples:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobRegular Expression
*.*
(a)*(a)*
[abc]+[abc]+
.\.
[.*+|][.*+|]
+\+
(x|y)+(x|y)+
{x,y}(?:x|y)
{[xa],y}(?:[xa]|y)
(?:foo)(?:foo)
{foo}(?:foo)
[\p{Lower}][\p{Lower}]
[a-z&&[^bc]][a-z&&[^bc]]
+ + diff --git a/org.bndtools.help/docs/chapters/825-instructions-ref.html b/org.bndtools.help/docs/chapters/825-instructions-ref.html new file mode 100644 index 0000000000..69c75deba0 --- /dev/null +++ b/org.bndtools.help/docs/chapters/825-instructions-ref.html @@ -0,0 +1,32 @@ + + + + +Instruction Index + + + +

Instruction Index

+

Learn the basics of bnd instructions in the Instruction reference.

+
+ + + + + + + + + + + + + + + + + +
InstructionDescriptionClass
+
+ + diff --git a/org.bndtools.help/docs/chapters/850-macros.html b/org.bndtools.help/docs/chapters/850-macros.html new file mode 100644 index 0000000000..8c28fc989d --- /dev/null +++ b/org.bndtools.help/docs/chapters/850-macros.html @@ -0,0 +1,76 @@ + + + + +Macro Reference + + + +

Macro Reference

+

Bnd has a simple macro processor for the header processing. Variables allow a single definition of a value, and the use of derivations. Each header is a macro that can be expanded. Notice that headers that do not start with an upper case character will not be copied to the manifest, so they can be used as working variables. Variables are expanded by enclosing the name of the variable in ${<name>} (curly braces) or $(<name>) (parenthesis). Additionally, square brackets [], angled brackets <>, double guillemets «», and single guillemets ‹› are also allowed for brackets. If brackets are nested, that is $[replace;acaca;a(.*)a;[$1]] will return [cac].

+

There are also a number of macros that perform basic functions. All these functions have the following basic syntax:

+
 macro ::= '${' function '}' 
+     | '$\[' function '\]'
+     | '$(' function ')'
+     | '$<' function '>'
+
+ function ::= name ( ';' argument ) *
+
+ +

For example:

+
version=1.23.87.200109111023542
+Bundle-Version= ${version}
+Bundle-Description= This bundle has version ${version}
+
+ +

All macros are listed on the Macro index

+

Macro patterns

+

The default macro pattern is the ${...} pattern, a dollar sign ('$') followed by a left curly bracket ('{') and closed by a right curly bracket ('}'). However, since bndlib is often used inside other systems it also supports alternative macro patterns:

+ +

Arguments

+

@Since("2.3") Macros can contain arguments. These arguments are available in the expansion as ${0} to ${9}. ${0} is the name of the macro, so the actual arguments start at 1. The name is also available as ${@}. The arguments as an array (without the name of the macro) is available as ${#}. The more traditional * could not be used because it clashes with wildcard keys, it means ALL values.

+

For example:

+
foo: Hello ${1} -> ${foo;Peter} -> "Hello Peter"
+
+ +

Wildcarded Keys

+

Keys can be wildcarded. For example, if you want to set -plugin from different places, then you can set the plugin.xxx properties in different places and combine them with -plugins= ${plugins.*}.

+

Expansion of ./

+

The ./ sequence is automatically expanded to the current filename when found in a macro source file. This generally what you want but unfortunately not always. The ./ prefix is only replaced when:

+ +

So, do you really require the ./ without expansion? If so, then there are the following solutions. The first one is to use another macro to break the sequence:

+
.=.
+Some-Header: ${.}/conf/admin.xml
+
+ +

Alternatively there are a couple of macros that return the given value when called appropriately, and thereby break the sequence:

+
Some-Header-1: ${def;.;.}/conf/jetty/admin.xml
+Some-Header-2: ${uniq;.}/conf/jetty/admin.xml
+Some-Header-3: ${unescape;.}/conf/jetty/admin.xml
+
+ +

Booleans

+

In many places a header is used to indicate false or true. In those cases we use some heuristics. The header/macro or whatever is false when:

+ +

If the value starts with ! and text follows, the ! is removed and the remaining text is interpreted as a boolean and then negated.

+

In other cases, the value is considered true.

+

Types

+

@TODO

+ + diff --git a/org.bndtools.help/docs/chapters/855-macros-ref.html b/org.bndtools.help/docs/chapters/855-macros-ref.html new file mode 100644 index 0000000000..c3437f8184 --- /dev/null +++ b/org.bndtools.help/docs/chapters/855-macros-ref.html @@ -0,0 +1,37 @@ + + + + +Macro Index + + + +

Macro Index

+

Learn the basics of bnd macros in the Macro reference and our bnd cheatsheet. Also check out the corresponding unit tests for the macros on this page.

+
+ +
+ +
+ + + + + + + + + + + + + + + +
pageDescriptionClass
+
+ +
+
+ + diff --git a/org.bndtools.help/docs/chapters/870-plugins.html b/org.bndtools.help/docs/chapters/870-plugins.html new file mode 100644 index 0000000000..c6d5dddcce --- /dev/null +++ b/org.bndtools.help/docs/chapters/870-plugins.html @@ -0,0 +1,32 @@ + + + + +Plugins + + + +

Plugins

+

Plugins

+

Plugins are objects that can extend the functionality of bnd. They are called from inside bnd when a certain action should take place. For example, bnd uses a repository and plugins provide the actual repository implementations. Or for example, the SpringComponent analyzes the Spring files and adds references found in that XML to the imports.

+

A plugin is defined as:

+
PLUGIN ::= FQN ( ';' \<directive\|attribute\> )*
+
+ +

The following directive is defined for all plugin:

+

||path: ||A path to the jar file that contains the plugin. The directory/jar at that location is placed on your classpath for that plugin.||

+

Tagging of repository plugins

+

Repository plugins are usually referenced in cnf/build.bnd and implement the Tagged interface.

+

The tags property of repositories' configuration allows to add a comma separated list of tags to a repository. These tags will be used for filtering a list of repositories. +For example the -runrepos instruction in .bndrun considers only those repositories for resolution which have either the resolve tag or no tags property defined. This allows including and excluding repositories based on their tags.

+

Index

+
+
+ +
+ + +
+
+ + diff --git a/org.bndtools.help/docs/chapters/875-external-plugins.html b/org.bndtools.help/docs/chapters/875-external-plugins.html new file mode 100644 index 0000000000..d99e2f56bc --- /dev/null +++ b/org.bndtools.help/docs/chapters/875-external-plugins.html @@ -0,0 +1,35 @@ + + + + +External Plugins + + + +

External Plugins

+

External Plugins

+

External Plugins are external code to bnd code but that can be executed from within bnd. The JARs for this code are coming from the Workspace repository. The External Plugin Namespace defines the namespace (bnd.external.plugin) and the following attributes:

+

| Attribute | Description | +|-------------------------------+-------------------------------| +| bnd.external.plugin | Defines the name of the plugin, should follow simple token syntax| +| objectClass | The interface type the implementation should implement| +| implementation | The implementation fully qualified class name| +| subtype | Optional subtype when the objectClass has a type parameter | +| version | Optional version range to limit the candidates |

+

There is an annotation, aQute.bnd.service.externalplugin.ExternalPlugin, that can be applied on a type.

+

For example:

+
aQute.bnd.service.externalplugin.ExternalPlugin(
+    name          = "calling", 
+    objectClass   = Callable.class, 
+    subtype       = String.class)
+public class CallImpl implements Callable<String> {
+    public String call() throws Exception {
+        return "hello";
+    }
+}
+
+ +

In Bndtools, you can declare any class as an ExternalPlugin. The automatic build features will automatically build the JAR of the plugin and this will immediately become available in the rest of the build. If you use external plugins from the local workspace, make sure to declare a -dependson to the external plugin project in any project that uses it, this dependency is not automatically detected.

+

A JAR can contain any number of external plugins. It must ensure that it does not have any dependencies outside the bndlib it was compiled against.

+ + diff --git a/org.bndtools.help/docs/chapters/880-settings.html b/org.bndtools.help/docs/chapters/880-settings.html new file mode 100644 index 0000000000..f8262e81d4 --- /dev/null +++ b/org.bndtools.help/docs/chapters/880-settings.html @@ -0,0 +1,35 @@ + + + + +Settings + + + +

Settings

+

For a build model it is crucial that it has no dependencies on the machine it is running on. One of the most frustrating developer experiences is the phrase: 'Yes, but it runs on my machine!'. For this reason bnd goes out of it is way to have no dependencies outside its workspace. That is, until we hit security. It is in the nature of security to have secrets and by definitions these secrets cannot be in the workspace, or, well, they will not be that secret for long. Though the best solution is to keep the secret in your head, there are times when this is impossible or plain cumbersome.

+

For this reason, bnd maintains a settings file in ~/.bnd/settings.json. This file contains ordinary settings ...

+

TBD

+

Authorization

+

The bnd settings Command

+

The global macro

+

Authorizing a New System

+

The settings automatically generate a private and public key when they are initialized. However, in certain cases it is necessary to explicitly authorize a system. For example, Travis always starts a build from a completely freshly initialized VM. In such a case it is necessary to authorize the machine explicitly. Though it is possible to just copy an existing settings file to this machine, it is more elegant to use the bnd commands. Do the following steps to authorize a machine.

+

On a trusted host, get the current private and public key and the email:

+
$ bnd identity
+--publicKey 08E...CF --privateKey C7FE...D3 --email bnd@example.org
+
+ +

The output is a bit longer than shown because these keys are darned long, you know, security is hard. You should copy the output and then on the target system run:

+
$ bnd identity <copied output>
+
+ +

This will use the same authorization as the original machine. If you want to create a more unique authorization, then it is possible to create a new private/public key pair.

+
 $ bnd settings -l temp.json -g
+ $ bnd identity -l temp.json 
+ --publicKey 08E...CF --privateKey C7FE...D3 --email bnd@example.org
+ ...
+ $ bnd identity <copied output>
+
+ + diff --git a/org.bndtools.help/docs/chapters/900-errors.html b/org.bndtools.help/docs/chapters/900-errors.html new file mode 100644 index 0000000000..b3fe5fe192 --- /dev/null +++ b/org.bndtools.help/docs/chapters/900-errors.html @@ -0,0 +1,12 @@ + + + + +Errors + + + +

Errors

+ + + diff --git a/org.bndtools.help/docs/chapters/910-warnings.html b/org.bndtools.help/docs/chapters/910-warnings.html new file mode 100644 index 0000000000..fa314f93f1 --- /dev/null +++ b/org.bndtools.help/docs/chapters/910-warnings.html @@ -0,0 +1,16 @@ + + + + +Warnings + + + +

Warnings

+

Java source version inconsistency: bnd has '1.5' while Eclipse has '1.8'. Set the bnd 'javac.source' property or change the Eclipse project setup.

+

First to explain the message. In a Bndtools project, the Java version is configured in two places. For the offline bnd build with Gradle/Ant, we set it directly from the javac.source and javac.target properties that you find in cnf/build.bnd. But in the internal Eclipse build, the configuration of the Eclipse project contains the JRE settings. Unfortunately we cannot force Eclipse to use the same settings as the offline build, but we can detect when they are inconsistent, and so we generate the warning you have seen.

+

To fix the problem, first decide what version of Java you want to use. Then you need to set that in both the bnd configuration and in the Eclipse workspace.

+

For bnd, you can set javac.source and javac.target for the whole workspace in cnf/build.bnd, and you can override it if you wish in each project's bnd.bnd file. You can find these entries in cnf/build.bnd from the standard templates, it will be commented out so just uncomment it.

+

For Eclipse you can set a workspace-wide preference by opening Window -> Preferences and navigating to the Java -> Compiler preference panel. This can also be overridden on a per-project basis by right-clicking the project, selecting Properties and navigating to the Java Compiler property panel. To be really safe, it's best to set the Eclipse compiler properties explicitly per-project. This is because these properties are persisted by Eclipse into the .settings folder inside the project, which can be checked into source control, whereas the workspace-wide settings go into the workspace .metadata directory which is not usually checked in.

+ + diff --git a/org.bndtools.help/docs/chapters/920-faq.html b/org.bndtools.help/docs/chapters/920-faq.html new file mode 100644 index 0000000000..52a403adf8 --- /dev/null +++ b/org.bndtools.help/docs/chapters/920-faq.html @@ -0,0 +1,140 @@ + + + + +FAQ - Frequently Asked Questions + + + +

FAQ - Frequently Asked Questions

+

How to ask a question

+

You can use the bnd discourse site mail list or mail me.

+

Too Many Imports

+

Sometimes bnd reports imports that seem plain wrong. Believe me, they are almost always right. bnd does a thorough analysis of the byte codes in your class files and when it imports something it is almost sure to be a reference in your code. How can you find the culprit? Bndtools has tooling to drill down into your code. bnd also can print out the JAR and look at the [USEDBY] section to find the package(s) that cause the import.

+

If there is no package using the imported package, then look at the following places for imports:

+ +

In the likely case the import is real but unwanted, look at Unwanted Imports.

+

Importing the default package error

+

This usually indicates that:

+ +

Remove unwanted imports

+

If you have an unwanted import than you can remove it from the Import-Package manifest header with the '!' operator:

+
Import-Package: !com.unwanted.reference.*, *
+
+ +

A usually better way is to make the imports optional:

+
Import-Package: com.unwanted.reference.*;resolution:=optional, *
+
+ +

Note the end at the Import-Package statement, that wildcard '*' is crucial for remaining imports, see No Imports Show Up.

+

No Imports Show Up

+

The imports that show up in your Import-Package manifest header are controlled by the bnd file's Import-Package instruction. In bnd, the list is a set of patterns that are sequentially applied to your imports as calculated by bnd from the classes, resources, and headers in the JAR.

+

The default Import-Package bnd instruction is:

+
Import-Package: *
+
+ +

This imports all referred packages. The most common reasons imports do not appear in the manifest is that the default is overridden and the overrider forgot to add the wildcard '*' at the end. For example, the following is wrong:

+
Import-Package: com.example; version=1.2
+
+ +

This will create an import for com.example but it ignores all other imports.

+

Another reason is the exclude operator ('!') that will remove imports. If this is too wild, then no imports are left to insert in the manifest. So the following leads to no imports for any package starting with com.example.

+
Import-Package: !com.example.*, *
+
+ +

Last but not least, look at the [USEDBY] section of the JAR print out, make sure there are actually references.

+

Why do I have imports without version ranges?

+

With -pedantic:true bnd creates a warning like

+
+

Imports that lack version ranges due to not being found in any bundle on the -buildpath: com.example.foo.bar ...

+
+

These could stem from transitive dependencies of the jars on your buildpath. +There are multiple reasons for that, for example they could stem from transitive dependencies: +- of non-OSGi jars which are included via -includeresource +- of OSGi bundles on your classpath, if the import version ranges for those bundles are not specified in the Bundle. E.g. if the bundle imports the dependency via Require-Bundle it won't have the import range, or if it uses Import-Package with no import range.

+

Why No Automatic Bundle-Activator

+

Many people are surprised that bnd does not automatically calculate the Bundle-Activator. Basically, there are the following issues:

+ +

That said, it is possible to automate the Bundle-Activator:

+
Bundle-Activator: \
+   ${classes;IMPLEMENTS;org.osgi.framework.BundleActivator}
+
+ +

However, if there are multiple Bundle-Activators you will get an error.

+

How to assign an unbind method to a @Reference?

+

@Reference automatically sets the bind method but how is the unbind method set? Simple, you use a method with a similar name:

+ + + + + + + + + + + + + +
bindunbind
setXunsetX
addXremoveX
+ +

For example:

+
@Reference
+protected void setFoo(LogService l) { ... }
+protected void unsetFoo(LogService l) { ... }
+
+ +

If you want to override this, use

+
@Reference(unbind="IRefuseToCallMyMethodUnFoo");
+protected void foo(LogService l) {}
+protected void IRefuseToCallMyMethodUnFoo(LogService l) {}
+
+ +

Unfortunately Java has no method references so it is not type safe.A non existent @UnReference annotation is not very useful because that still requires linking it up symbolically to the associated @Reference.

+

packageinfo or package-info.java?

+

I'm just a little bit confused about the bnd approach with the file naming "packageinfo". The JLS already defines "package-info.java" for package relevant infos. Wouldn't it be simplier (less complex) to have only one file for package definitions? So, the bnd tool could manage the package version in "package-info.java", too.

+

You can use either file. The reason there are two options is that one constituency thinks annotations are the only solution and the other is running pre Java 5 ... Basically if I would have to choose it would be packageinfo because that works anywhere but I expect that you probably would not like that :-)

+

Why are superclass not inspected for Component annotations?

+

Annotations are not inherited from the component's super classes by default. The problem is that super classes from imported packages may be different at runtime than they were at build time. So it is always best to declare your annotations on the actual component class. Alternatively you can use the instruction -dsannotations-options: inherit. Then bnd will use DS annotations found in the class hierarchy of the component class. This will not work for the @Component annotation itself; it will not be inherited from super classes causing a subclass to suddenly be a component.

+

Why does bnd require a public no-arg constructor for my DS component?

+

Starting with bnd 7.3.0, bnd enforces the DS specification requirement that component classes must have either a public no-argument constructor or a public constructor annotated with @Activate for constructor injection.

+

If you see this error:

+
The DS component class {className} must be publicly accessible and have either a public no-arg constructor or a public constructor annotated with @Activate. Non-public classes, including public inner classes enclosed in non-public classes, are not supported.
+
+ +

You need to either add a public no-arg constructor, use @Activate on your constructor, ensure your class is public, or make inner classes static.

+

See Component Class Requirements for detailed explanations and code examples.

+

Can't find the source of the version on an Export-Package?

+

If no explicit export version is specified in the bnd file then bnd will look in the following places.

+ +

The use of the bundle version is a rather bad idea, packages should be versioned independently. It is possible +to not use the bundle version for a package with:

+
-nodefaultversion true
+
+ +

Should I use the Bundle-ClassPath?

+

No. It creates unnecessary complexity, it is slower, and it is not necessary. It will also not be compatible with techniques like PojoSR, something that the OSGi is looking into standardizing.

+

What should I use instead of the Bundle-ClassPath?

+

Just use Private-Package and Export-Package, know what goes into your JAR. If you really need to wrap one or more JARs, use the Include-Resource instruction, it has an option to unroll a JAR resource (see @ option. This will copy all its contents in the target JAR. The -exportcontents can then be used to export selected packages. Even better is of course to know

+

Sharing CNF Folder and BNDTools Projects

+

The Best Practices section provides some good tips about how you setup workspaces that share some information.

+
+

If an entry is wrong, send a mail with the JAR that has the problem. Preferably as small as possible.

+ + diff --git a/org.bndtools.help/docs/commands/action.html b/org.bndtools.help/docs/commands/action.html new file mode 100644 index 0000000000..56719444fe --- /dev/null +++ b/org.bndtools.help/docs/commands/action.html @@ -0,0 +1,21 @@ + + + + +action + + + +

action

+

Synopsis:

+
   action [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/add.html b/org.bndtools.help/docs/commands/add.html new file mode 100644 index 0000000000..e881eea08c --- /dev/null +++ b/org.bndtools.help/docs/commands/add.html @@ -0,0 +1,58 @@ + + + + +add + + + +

add

+

Synopsis:

+
   add  <what> ...
+
+ +

Available sub-commands

+ +

fragment

+

Add template fragment(s) to the current workspace. Leave the name empty to see a list of available templates at the index.\n\nExample:\n bnd add fragment osgi gradle

+

Synopsis:

+
   fragment  <[name]...>
+
+ +

plugin

+

Add a plugin

+

Synopsis:

+
   plugin [options]  <[name]> ...
+
+ +
Options:
+ +

project

+

Create a project in the current workspace

+

Synopsis:

+
   project  <name> ...
+
+ +

workspace

+

Create a bnd workspace in the current folder. The workspace can also be inialized with a set of template fragments.

+

Example: + bnd add workspace -f osgi -f gradle 'myworkspace'

+

See https://bnd.bndtools.org/chapters/620-template-fragments.html for more information.

+

Synopsis:

+
   workspace [options]  <name> ...
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/baseline.html b/org.bndtools.help/docs/commands/baseline.html new file mode 100644 index 0000000000..77589cdb19 --- /dev/null +++ b/org.bndtools.help/docs/commands/baseline.html @@ -0,0 +1,28 @@ + + + + +baseline + + + +

baseline

+

Synopsis:

+
   baseline [options]  <[newer jar]> <[older jar]>
+
+ +

Options:

+ + +

Examples

+

bnd baseline --diff newer.jar older.jar

+



+ + diff --git a/org.bndtools.help/docs/commands/bash.html b/org.bndtools.help/docs/commands/bash.html new file mode 100644 index 0000000000..83f69691c8 --- /dev/null +++ b/org.bndtools.help/docs/commands/bash.html @@ -0,0 +1,31 @@ + + + + +bash + + + +

bash

+

Synopsis:

+
   bash  ...
+
+ + +

Bash Command Autocompletion

+

The bash command in bnd can generate an autocompletion script for the Bash shell, making it easier to use bnd commands interactively.

+

When you run the bash autocompletion generator, bnd will create a temporary file containing the autocompletion script, populate it with the list of available commands, and output the result. This script can then be sourced in your shell to enable tab-completion for bnd commands.

+

Example:

+

To generate and use the autocompletion script for bash:

+
    +
  1. Run the following command to generate the script: + bnd bash > bnd-completion.bash
  2. +
  3. Source the script in your shell: + source bnd-completion.bash
  4. +
+

This will enable tab-completion for all available bnd commands in your current shell session.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/commands/bnd.html b/org.bndtools.help/docs/commands/bnd.html new file mode 100644 index 0000000000..67123e0e78 --- /dev/null +++ b/org.bndtools.help/docs/commands/bnd.html @@ -0,0 +1,28 @@ + + + + +bnd + + + +

bnd

+

Synopsis:

+
   bnd [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/bootstrap.html b/org.bndtools.help/docs/commands/bootstrap.html new file mode 100644 index 0000000000..a8fce46927 --- /dev/null +++ b/org.bndtools.help/docs/commands/bootstrap.html @@ -0,0 +1,28 @@ + + + + +bootstrap + + + +

bootstrap

+

Synopsis:

+
   bootstrap  ...
+
+ + +

Bootstrap Command

+

The bootstrap command in bnd is used to start a local OSGi framework using the workspace's configuration. This command looks for the bnd.bnd file in the workspace's cnf directory and uses it to launch the framework locally.

+

If the bnd.bnd file is not found, the command will report an error and exit. Otherwise, it will initialize the framework and run it in the local environment, making it easy to test or develop OSGi applications directly from your workspace setup.

+

Example:

+

To start a local framework using the workspace configuration:

+
bnd bootstrap
+
+ +

This will launch the OSGi framework as defined by your workspace's bnd.bnd file.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/commands/bsn2url.html b/org.bndtools.help/docs/commands/bsn2url.html new file mode 100644 index 0000000000..f7e851f5f8 --- /dev/null +++ b/org.bndtools.help/docs/commands/bsn2url.html @@ -0,0 +1,37 @@ + + + + +bsn2url + + + +

bsn2url

+

Synopsis:

+
   bsn2url [options]  ...
+
+ +

Options:

+ + +

bsn2url Command

+

The bsn2url command in bnd is used to generate a list of URLs for bundles based on their bundle symbolic names (bsns) and versions. This is useful for creating lists of bundle locations for deployment, analysis, or documentation purposes.

+

The command reads a list of bsns (and optional version ranges) from input files, looks up the available versions in the configured repositories, and outputs the corresponding URLs for each matching bundle.

+

Example:

+

Suppose you have a file bundles.txt containing:

+
com.example.foo;version='[1.0,2.0)'
+com.example.bar
+
+ +

You can generate a list of URLs for these bundles with:

+
bnd bsn2url bundles.txt
+
+ +

This will print the URLs for the matching bundles and versions, making it easy to retrieve or reference them in other tools or scripts.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/commands/build.html b/org.bndtools.help/docs/commands/build.html new file mode 100644 index 0000000000..9979e5f69a --- /dev/null +++ b/org.bndtools.help/docs/commands/build.html @@ -0,0 +1,27 @@ + + + + +build + + + +

build

+

Synopsis:

+
   build [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/buildtool.html b/org.bndtools.help/docs/commands/buildtool.html new file mode 100644 index 0000000000..ced86e9cf3 --- /dev/null +++ b/org.bndtools.help/docs/commands/buildtool.html @@ -0,0 +1,20 @@ + + + + +buildtool + + + +

buildtool

+

Synopsis:

+
   buildtool [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/buildx.html b/org.bndtools.help/docs/commands/buildx.html new file mode 100644 index 0000000000..bd735cc933 --- /dev/null +++ b/org.bndtools.help/docs/commands/buildx.html @@ -0,0 +1,30 @@ + + + + +buildx + + + +

buildx

+

Synopsis:

+
   buildx [options]  ...
+
+ +

Options:

+ + +

Examples

+

bnd buildx -classpath bin -noeclipse -output test.jar xyz.bnd

+



+ + diff --git a/org.bndtools.help/docs/commands/bump.html b/org.bndtools.help/docs/commands/bump.html new file mode 100644 index 0000000000..5b1918cd7c --- /dev/null +++ b/org.bndtools.help/docs/commands/bump.html @@ -0,0 +1,19 @@ + + + + +bump + + + +

bump

+

Synopsis:

+
   bump [options]  <<major|minor|micro>>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/changes.html b/org.bndtools.help/docs/commands/changes.html new file mode 100644 index 0000000000..b8a8a14c7f --- /dev/null +++ b/org.bndtools.help/docs/commands/changes.html @@ -0,0 +1,19 @@ + + + + +changes + + + +

changes

+

Synopsis:

+
   changes [options]
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/classpath.html b/org.bndtools.help/docs/commands/classpath.html new file mode 100644 index 0000000000..d8126997f0 --- /dev/null +++ b/org.bndtools.help/docs/commands/classpath.html @@ -0,0 +1,23 @@ + + + + +classpath + + + +

classpath

+

Synopsis:

+
   classpath [options]
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/classtoresource.html b/org.bndtools.help/docs/commands/classtoresource.html new file mode 100644 index 0000000000..d530e4421f --- /dev/null +++ b/org.bndtools.help/docs/commands/classtoresource.html @@ -0,0 +1,14 @@ + + + + +classtoresource + + + +

classtoresource

+

Synopsis:

+
   classtoresource  ...
+
+ + diff --git a/org.bndtools.help/docs/commands/clean.html b/org.bndtools.help/docs/commands/clean.html new file mode 100644 index 0000000000..05932aa9f5 --- /dev/null +++ b/org.bndtools.help/docs/commands/clean.html @@ -0,0 +1,22 @@ + + + + +clean + + + +

clean

+

Synopsis:

+
   clean [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/collect.html b/org.bndtools.help/docs/commands/collect.html new file mode 100644 index 0000000000..cea9b96aaa --- /dev/null +++ b/org.bndtools.help/docs/commands/collect.html @@ -0,0 +1,19 @@ + + + + +collect + + + +

collect

+

Synopsis:

+
   collect [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/com.html b/org.bndtools.help/docs/commands/com.html new file mode 100644 index 0000000000..b0ae1cd564 --- /dev/null +++ b/org.bndtools.help/docs/commands/com.html @@ -0,0 +1,43 @@ + + + + +com + + + +

com

+

Synopsis:

+
   com  ...
+
+ +

Available sub-commands

+ +

clear

+

Clear the cached file that is associated with the givenURI

+

Synopsis:

+
   clear  ...
+
+ +

info

+

Show the information used by the Http Client to get aremote file

+

Synopsis:

+
   info [options]  <url...>
+
+ +
Options:
+ +

settings

+

Show the bnd -connection-settings

+

Synopsis:

+
   settings  ...
+
+ + diff --git a/org.bndtools.help/docs/commands/compile.html b/org.bndtools.help/docs/commands/compile.html new file mode 100644 index 0000000000..a8740cf2ea --- /dev/null +++ b/org.bndtools.help/docs/commands/compile.html @@ -0,0 +1,23 @@ + + + + +compile + + + +

compile

+

Synopsis:

+
   compile [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/convert.html b/org.bndtools.help/docs/commands/convert.html new file mode 100644 index 0000000000..3274a112db --- /dev/null +++ b/org.bndtools.help/docs/commands/convert.html @@ -0,0 +1,20 @@ + + + + +convert + + + +

convert

+

Synopsis:

+
   convert [options]  <from> <to>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/copy.html b/org.bndtools.help/docs/commands/copy.html new file mode 100644 index 0000000000..c26224583a --- /dev/null +++ b/org.bndtools.help/docs/commands/copy.html @@ -0,0 +1,21 @@ + + + + +copy + + + +

copy

+

Synopsis:

+
   copy [options]  <src...> <dest>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/create.html b/org.bndtools.help/docs/commands/create.html new file mode 100644 index 0000000000..4bc4752298 --- /dev/null +++ b/org.bndtools.help/docs/commands/create.html @@ -0,0 +1,29 @@ + + + + +create + + + +

create

+

Synopsis:

+
   create [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/debug.html b/org.bndtools.help/docs/commands/debug.html new file mode 100644 index 0000000000..04032b7c4b --- /dev/null +++ b/org.bndtools.help/docs/commands/debug.html @@ -0,0 +1,20 @@ + + + + +debug + + + +

debug

+

Synopsis:

+
   debug [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/defaults.html b/org.bndtools.help/docs/commands/defaults.html new file mode 100644 index 0000000000..51c6191f1f --- /dev/null +++ b/org.bndtools.help/docs/commands/defaults.html @@ -0,0 +1,14 @@ + + + + +defaults + + + +

defaults

+

Synopsis:

+
   defaults  ...
+
+ + diff --git a/org.bndtools.help/docs/commands/deliverables.html b/org.bndtools.help/docs/commands/deliverables.html new file mode 100644 index 0000000000..467aa7b9cb --- /dev/null +++ b/org.bndtools.help/docs/commands/deliverables.html @@ -0,0 +1,47 @@ + + + + +deliverables + + + +

deliverables

+

Synopsis:

+
   deliverables [options]
+
+ +

Options:

+ + +

Example

+
biz.aQute.bnd (master)$ bnd deliverables 
+found password 
+aQute.libg                                  2.9.0  /Ws/bnd/aQute.libg/generated/aQute.libg.jar
+biz.aQute.bnd                               2.4.0  /Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar
+biz.aQute.bnd.annotation                    2.4.0  /Ws/bnd/biz.aQute.bnd.annotation/generated/biz.aQute.bnd.annotation.jar
+biz.aQute.bnd.bootstrap.console             0.0.0  /Ws/bnd/biz.aQute.bnd.bootstrap/generated/biz.aQute.bnd.bootstrap.console.jar
+biz.aQute.bnd.test                          2.4.0  /Ws/bnd/biz.aQute.bnd.test/generated/biz.aQute.bnd.test.jar
+biz.aQute.bnd.testextension                 2.4.0  /Ws/bnd/biz.aQute.bnd.testextension/generated/biz.aQute.bnd.testextension.jar
+biz.aQute.bndlib                            2.4.0  /Ws/bnd/biz.aQute.bndlib/generated/biz.aQute.bndlib.jar
+biz.aQute.bndlib.tests                      2.4.0  /Ws/bnd/biz.aQute.bndlib.tests/generated/biz.aQute.bndlib.tests.jar
+biz.aQute.junit                             1.3.0  /Ws/bnd/biz.aQute.junit/generated/biz.aQute.junit.jar
+biz.aQute.launcher                          1.4.0  /Ws/bnd/biz.aQute.launcher/generated/biz.aQute.launcher.jar
+biz.aQute.repository                        2.2.0  /Ws/bnd/biz.aQute.repository/generated/biz.aQute.repository.jar
+biz.aQute.resolve                           0.2.0  /Ws/bnd/biz.aQute.resolve/generated/biz.aQute.resolve.jar
+cnf                                         0.0.0  /Ws/bnd/cnf/generated/cnf.jar
+demo                                        1.1.0  /Ws/bnd/demo/generated/demo.jar
+dist                                        0.0.0  /Ws/bnd/dist/generated/dist.jar
+osgi.r5                                     1.0.1  /Ws/bnd/osgi.r5/generated/osgi.r5.jar
+biz.aQute.bnd (master)$ bnd deliverables -l
+found password 
+biz.aQute.bnd                               2.4.0  /Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar
+biz.aQute.bnd (master)$
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/dependencies.html b/org.bndtools.help/docs/commands/dependencies.html new file mode 100644 index 0000000000..0c62611e9c --- /dev/null +++ b/org.bndtools.help/docs/commands/dependencies.html @@ -0,0 +1,20 @@ + + + + +dependencies + + + +

dependencies

+

Synopsis:

+
   dependencies [options]  <instruction...>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/dev.html b/org.bndtools.help/docs/commands/dev.html new file mode 100644 index 0000000000..360803dc6a --- /dev/null +++ b/org.bndtools.help/docs/commands/dev.html @@ -0,0 +1,27 @@ + + + + +dev + + + +

dev

+

Synopsis:

+
   dev [options]  <[bndrun...]>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/diff.html b/org.bndtools.help/docs/commands/diff.html new file mode 100644 index 0000000000..ef8f37e1b0 --- /dev/null +++ b/org.bndtools.help/docs/commands/diff.html @@ -0,0 +1,1611 @@ + + + + +diff + + + +

diff

+

Synopsis:

+
   diff [options]  <[newer file]> <[older file]>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd diff generated/
+generated/.index             generated/biz.aQute.bnd.jar  generated/buildfiles         
+biz.aQute.bnd (master)$ bnd diff generated/biz.aQute.bnd.jar /Ws/archive/aQute.archive/aQute.bnd/archive/tmp/biz.aQute.bnd.jar 
+ADDED      PACKAGE    aQute.bnd.build
+ADDED      PACKAGE    aQute.bnd.header
+ADDED      PACKAGE    aQute.bnd.maven.support
+ADDED      PACKAGE    aQute.bnd.osgi
+ADDED      PACKAGE    aQute.bnd.osgi.resource
+ADDED      PACKAGE    aQute.bnd.service
+ADDED      PACKAGE    aQute.bnd.service.action
+ADDED      PACKAGE    aQute.bnd.service.classparser
+ADDED      PACKAGE    aQute.bnd.service.diff
+ADDED      PACKAGE    aQute.bnd.service.extension
+ADDED      PACKAGE    aQute.bnd.service.progress
+ADDED      PACKAGE    aQute.bnd.service.repository
+ADDED      PACKAGE    aQute.bnd.service.resolve.hook
+ADDED      PACKAGE    aQute.bnd.service.url
+ADDED      PACKAGE    aQute.bnd.util.dto
+ADDED      PACKAGE    aQute.bnd.version
+REMOVED    PACKAGE    aQute.lib.osgi
+ADDED      PACKAGE    aQute.service.reporter
+ADDED      PACKAGE    org.osgi.resource
+ADDED      PACKAGE    org.osgi.service.bindex
+ADDED      PACKAGE    org.osgi.service.repository
+ADDED      CLASS_VERSION J2SE6
+CHANGED    MANIFEST   <manifest>
+REMOVED    HEADER     Bundle-ActivationPolicy:lazy
+REMOVED    HEADER     Bundle-Activator:aQute.bnd.plugin.Activator
+REMOVED    HEADER     Bundle-Copyright:2006, 2007 (c) aQute, All rights reserved
+ADDED      HEADER     Bundle-Copyright:Copyright (c) aQute (2000, 2014). All Rights Reserved.
+REMOVED    HEADER     Bundle-Description:A utility and plugin to wrap, build, or print bundles
+ADDED      HEADER     Bundle-Description:This command line utility is the Swiss army knife of OSGi. It provides you with a breadth
+CHANGED    HEADER     Bundle-License
+  REMOVED    CLAUSE     ASL20
+  ADDED      CLAUSE     http://www.opensource.org/licenses/apache2.0.php
+REMOVED    HEADER     Bundle-Name:aQute Bundle Tool
+ADDED      HEADER     Bundle-Name:biz.aQute.bnd
+ADDED      HEADER     Bundle-SCM:git://github.com/bndtools/bnd.git
+CHANGED    HEADER     Bundle-SymbolicName
+  CHANGED    CLAUSE     biz.aQute.bnd
+  REMOVED    PARAMETER  singleton::true
+REMOVED    HEADER     Bundle-Version:0.0.279
+ADDED      HEADER     Bundle-Version:2.4.0
+REMOVED    HEADER     Conditional-Package:aQute.libg.*, aQute.lib.*
+ADDED      HEADER     Conditional-Package:aQute.libg.*,aQute.lib.*,aQute.configurable
+CHANGED    HEADER     Export-Package
+  ADDED      CLAUSE     aQute.bnd.build
+  ADDED      CLAUSE     aQute.bnd.header
+  ADDED      CLAUSE     aQute.bnd.maven.support
+  ADDED      CLAUSE     aQute.bnd.osgi
+  ADDED      CLAUSE     aQute.bnd.osgi.resource
+  ADDED      CLAUSE     aQute.bnd.service
+  ADDED      CLAUSE     aQute.bnd.service.action
+  ADDED      CLAUSE     aQute.bnd.service.classparser
+  ADDED      CLAUSE     aQute.bnd.service.diff
+  ADDED      CLAUSE     aQute.bnd.service.extension
+  ADDED      CLAUSE     aQute.bnd.service.progress
+  ADDED      CLAUSE     aQute.bnd.service.repository
+  ADDED      CLAUSE     aQute.bnd.service.resolve.hook
+  ADDED      CLAUSE     aQute.bnd.service.url
+  ADDED      CLAUSE     aQute.bnd.util.dto
+  ADDED      CLAUSE     aQute.bnd.version
+  REMOVED    CLAUSE     aQute.lib.osgi
+  ADDED      CLAUSE     aQute.service.reporter
+  ADDED      CLAUSE     org.osgi.resource
+  ADDED      CLAUSE     org.osgi.service.bindex
+  ADDED      CLAUSE     org.osgi.service.repository
+ADDED      HEADER     Git-Descriptor:2.4.0.M1-66-gc1ad07d-dirty
+ADDED      HEADER     Git-SHA:c1ad07dfeb4704ce590bd93c1405d7bfe8bef131
+CHANGED    HEADER     Import-Package
+  ADDED      CLAUSE     aQute.bnd.service
+  ADDED      CLAUSE     aQute.bnd.service.action
+  ADDED      CLAUSE     aQute.bnd.service.diff
+  ADDED      CLAUSE     aQute.bnd.service.progress
+  ADDED      CLAUSE     aQute.bnd.service.repository
+  ADDED      CLAUSE     aQute.bnd.service.url
+  ADDED      CLAUSE     aQute.bnd.version
+  REMOVED    CLAUSE     aQute.lib.filter
+  REMOVED    CLAUSE     aQute.lib.osgi
+  REMOVED    CLAUSE     aQute.libg.generics
+  REMOVED    CLAUSE     aQute.libg.header
+  REMOVED    CLAUSE     aQute.libg.qtokens
+  REMOVED    CLAUSE     aQute.libg.reporter
+  REMOVED    CLAUSE     aQute.libg.version
+  ADDED      CLAUSE     aQute.service.reporter
+  ADDED      CLAUSE     javax.crypto
+  ADDED      CLAUSE     javax.crypto.spec
+  ADDED      CLAUSE     javax.naming
+  ADDED      CLAUSE     javax.net.ssl
+  ADDED      CLAUSE     javax.script
+  ADDED      CLAUSE     javax.xml.namespace
+  ADDED      CLAUSE     javax.xml.transform
+  ADDED      CLAUSE     javax.xml.transform.dom
+  ADDED      CLAUSE     javax.xml.transform.stream
+  ADDED      CLAUSE     javax.xml.xpath
+  ADDED      CLAUSE     junit.framework
+  CHANGED    CLAUSE     org.apache.tools.ant
+  ADDED      PARAMETER  resolution::optional
+  ADDED      CLAUSE     org.apache.tools.ant.taskdefs
+  CHANGED    CLAUSE     org.apache.tools.ant.types
+  ADDED      PARAMETER  resolution::optional
+  REMOVED    CLAUSE     org.eclipse.core.resources
+  REMOVED    CLAUSE     org.eclipse.core.runtime
+  REMOVED    CLAUSE     org.eclipse.debug.core
+  REMOVED    CLAUSE     org.eclipse.debug.ui
+  REMOVED    CLAUSE     org.eclipse.debug.ui.sourcelookup
+  REMOVED    CLAUSE     org.eclipse.jdt.core
+  REMOVED    CLAUSE     org.eclipse.jdt.debug.ui.launchConfigurations
+  REMOVED    CLAUSE     org.eclipse.jdt.internal.junit.launcher
+  REMOVED    CLAUSE     org.eclipse.jdt.junit.launcher
+  REMOVED    CLAUSE     org.eclipse.jdt.launching
+  REMOVED    CLAUSE     org.eclipse.jdt.ui.wizards
+  REMOVED    CLAUSE     org.eclipse.jface.action
+  REMOVED    CLAUSE     org.eclipse.jface.dialogs
+  REMOVED    CLAUSE     org.eclipse.jface.resource
+  REMOVED    CLAUSE     org.eclipse.jface.text
+  REMOVED    CLAUSE     org.eclipse.jface.text.source
+  REMOVED    CLAUSE     org.eclipse.jface.viewers
+  REMOVED    CLAUSE     org.eclipse.jface.wizard
+  REMOVED    CLAUSE     org.eclipse.swt.events
+  REMOVED    CLAUSE     org.eclipse.swt.graphics
+  REMOVED    CLAUSE     org.eclipse.swt.layout
+  REMOVED    CLAUSE     org.eclipse.swt.widgets
+  REMOVED    CLAUSE     org.eclipse.ui
+  REMOVED    CLAUSE     org.eclipse.ui.part
+  REMOVED    CLAUSE     org.eclipse.ui.plugin
+  REMOVED    CLAUSE     org.eclipse.ui.texteditor
+  CHANGED    CLAUSE     org.osgi.framework
+  ADDED      PARAMETER  version:[1.6,2)
+  ADDED      CLAUSE     org.osgi.resource
+  ADDED      CLAUSE     org.osgi.service.log
+  REMOVED    CLAUSE     org.osgi.service.packageadmin
+  ADDED      CLAUSE     org.xml.sax.helpers
+REMOVED    HEADER     Include-Resource:plugin.xml, LICENSE, maven-dependencies.txt
+ADDED      HEADER     Private-Package:aQute.bnd.annotation;version="1.43.2",aQute.bnd.annotation.component;version="1.43.1",aQute.bnd.annotation.headers;version="1.0",aQute.bnd.annotation.licenses;version="1.0",aQute.bnd.annotation.metatype;version="1.44.1",aQute.bnd.ant,aQute.bnd.build.model;version="2.6.0",aQute.bnd.build.model.clauses;version=2,aQute.bnd.build.model.conversions,aQute.bnd.compatibility,aQute.bnd.component,aQute.bnd.component.error;version="1.0.0",aQute.bnd.differ;version="1.1.0",aQute.bnd.enroute.commands,aQute.bnd.filerepo;version="1.0",aQute.bnd.gradle,aQute.bnd.help;version="1.1",aQute.bnd.indexer,aQute.bnd.indexer.analyzers,aQute.bnd.main;version="0.9",aQute.bnd.make,aQute.bnd.make.calltree,aQute.bnd.make.component,aQute.bnd.make.coverage,aQute.bnd.make.metatype,aQute.bnd.maven,aQute.bnd.obr,aQute.bnd.osgi.eclipse,aQute.bnd.properties;version="2.0",aQute.bnd.resource.repository,aQute.bnd.signing,aQute.bnd.testing;version="1.0",aQute.bnd.url;version="1.0",aQute.configurable;version="1.0.0",aQute.lib.deployer,embedded-repo.jar,org.osgi.service.component.annotations;version="1.3",org.osgi.service.coordinator;version="1.0",templates,aQute.lib.base64;version="1.2.0",aQute.lib.collections;version="1.2.0",aQute.lib.converter;version="2.0.1",aQute.lib.filter;version="1.1.0",aQute.lib.getopt;version="1.0.0",aQute.lib.hex;version="1.1.0",aQute.lib.io;version="1.4.0",aQute.lib.json;version="3.0.0",aQute.lib.justif;version="1.1.0",aQute.lib.persistentmap;version="1.1.0",aQute.lib.settings;version="1.2.0",aQute.lib.strings;version="1.1.0",aQute.lib.tag;version="1.1",aQute.libg.classdump;version="1.0",aQute.libg.command;version="3.0.0",aQute.libg.cryptography;version="1.1.0",aQute.libg.filelock;version="1.0.0",aQute.libg.filters;version="1.0",aQute.libg.forker;version="1.0",aQute.libg.generics;version="1.0",aQute.libg.glob;version="1.1.1",aQute.libg.map;version="1.2.0",aQute.libg.qtokens;version="1.0",aQute.libg.reporter;version="1.5",aQute.libg.sed;version="1.1.0",aQute.libg.tuple;version="1.0",aQute.lib.markdown
+REMOVED    HEADER     Private-Package:aQute.lib.deployer,aQute.bnd.test,aQute.bnd.junit,aQute.bnd.launch,aQute.lib.jardiff,aQute.bnd.build,aQute.bnd.plugin.popup.actions,aQute.bnd.annotation,aQute.bnd.service,aQute.lib.osgi.eclipse,aQute.bnd.ant,aQute.bnd.main;version="0.9",aQute.bnd.plugin,aQute.bnd.make,aQute.bnd.plugin.builder,aQute.bnd.jareditor,aQute.bnd.classpath
+ADDED      HEADER     Require-Capability:osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))"
+MAJOR      RESOURCES  <resources>
+MAJOR      RESOURCE   LICENSE
+  ADDED      SHA        2B8B815229AA8A61E483FB4BA0588B8B6C491890
+  REMOVED    SHA        47B573E3824CD5E02A1A3AE99E2735B49E0256E4
+REMOVED    RESOURCE   OSGI-OPT/bnd.bnd
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/ConsumerType.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/Export.java
+  ADDED      SHA        57B5F624DE03F979D4876F63422BA92203EF1910
+  REMOVED    SHA        6A6378BCE886CA435A3F166F70F0E0AB12828B13
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/Import.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/Pair.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/ProviderType.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/Version.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/Activate.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/Component.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/ConfigurationPolicy.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/Deactivate.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/Modified.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/Reference.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/component/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/About.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleCategory.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleContributors.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleCopyright.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleDevelopers.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleDocURL.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/BundleLicense.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/Category.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/ProvideCapability.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/RequireCapability.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/Resolution.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/headers/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/ASL_2_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/BSD_2_Clause.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/BSD_3_Clause.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/CDDL_1_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/CPL_1_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/EPL_1_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/GPL_2_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/GPL_3_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/LGPL_2_1.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/MIT_1_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/MPL_2_0.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/licenses/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/metatype/Configurable.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/metatype/Meta.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/metatype/packageinfo
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/package-info.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/annotation/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/AntMessages.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/BaseTask.java
+  REMOVED    SHA        45CF7C2907DD82AD23A979E880C20007206AA0E6
+  ADDED      SHA        C27D9C96DFCDB750A1FDBA926EE99A1ED5B154B2
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/BndTask.java
+  ADDED      SHA        881EC2597543A91A9F1A883817C55D2B80F12CB7
+  REMOVED    SHA        ABCC53977C4924B29EDF334DA1B3FE5010EFD3B6
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/ConsoleProgress.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/DeployTask.java
+  ADDED      SHA        33ED2BB9356BCFBD7A0D0AF8EB1BB10B6D7E7C7D
+  REMOVED    SHA        CF24BA22F1A33E61F950E34317F0D82082B08921
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/EclipseTask.java
+  REMOVED    SHA        62E6497D3868BD6E48C86689E6CE26157A33AC6D
+  ADDED      SHA        B6D59DF94689FEEE1166D9EAC0938CCF92812115
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/ExpandPropertiesTask.java
+  REMOVED    SHA        08B914BB997480B60C3F48E8A5CB4BD1E7E84EF9
+  ADDED      SHA        B429909161768A44F2BE870C43E3F3DA84E6D827
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/PackageTask.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/PrepareTask.java
+  REMOVED    SHA        60468618217981C8ED498CE4D66668C7D3A0459B
+  ADDED      SHA        949B04B29AEBC412A3485BF9AFAF446ED292DBF8
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/ProjectBuildOrderTask.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/ProjectTask.java
+  ADDED      SHA        9540543903DD936FFAD6C972D40C772C3B6CD3B0
+  REMOVED    SHA        9D9BF171CB0AF435A92FA6F7F7BA6D6ADDAE8A22
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/ReleaseTask.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/RunconfigToDistributionTask.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/TestTask.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/ant/WrapTask.java
+  ADDED      SHA        164E838D471D1773C0010560A3B419EE5D666418
+  REMOVED    SHA        62318CD6C8F4D42EFDA0C39D22F418185091A712
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/build/CircularDependencyException.java
+  ADDED      SHA        2DBD8F2F5382CBF94E4F495B085C44770FD52796
+  REMOVED    SHA        903622D5709FBB2D44120AC242F8A6BAB2ED9604
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/build/Container.java
+  REMOVED    SHA        914441F7D5DBB2F86BFD83F4FAC9EB047E464ABD
+  ADDED      SHA        A897B7CAFD1004D6FA0F06625F25CAB5D19CBFA6
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/DownloadBlocker.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ErrorDetails.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/build/Framework.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/JUnitLauncher.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/build/Project.java
+  ADDED      SHA        C7A0428FE040DA06D28D865209F573B88D0ABCB5
+  REMOVED    SHA        D33BBA8757E45959B32ED2283B1E176DFF8A6BAE
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ProjectBuilder.java
+  REMOVED    SHA        4BC12A6E5EE452B093F8EDCFC7810D7E475C89B3
+  ADDED      SHA        6069CBE1015591C5E02C3A63272EE499573A12A4
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ProjectLauncher.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ProjectMessages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ProjectTester.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ReflectAction.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ResolverMode.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/Run.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/ScriptAction.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/build/Workspace.java
+  REMOVED    SHA        07AF5474B58E11D2806FBD6AAC0DBFB4B8F66EBC
+  ADDED      SHA        6A9DEF93C7F8704B74059D56AFD4A7F279FB3D75
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/WorkspaceRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/BndEditModel.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/EE.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/ComponentSvcReference.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/ExportedPackage.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/HeaderClause.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/ImportPattern.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/ServiceComponent.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/VersionedClause.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/clauses/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/ClauseListConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/CollectionFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/Converter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/DefaultFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/EEConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/EEFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/EnumConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/EnumFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/HeaderClauseConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/MapFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/NoopConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/PropertiesConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/RequirementFormatter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/RequirementListConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/SimpleListConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/StringEntryConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/conversions/VersionedClauseConverter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/model/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/build/packageinfo
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/classpath/BndContainer.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/classpath/BndContainerInitializer.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/classpath/BndContainerPage.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/classpath/ModelListener.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/Access.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/GenericParameter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/GenericType.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/Kind.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/ParseSignatureBuilder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/Scope.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/compatibility/Signatures.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/AnnotationReader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/ComponentDef.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/DSAnnotations.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/HeaderReader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/ReferenceDef.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/TagResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/error/DeclarativeServicesAnnotationError.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/component/error/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/Baseline.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/DiffImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/DiffPluginImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/Element.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/JavaElement.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/RepositoryElement.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/differ/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/enroute/commands/EnrouteCommand.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/enroute/commands/EnrouteOptions.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/filerepo/FileRepo.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/filerepo/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/header/Attrs.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/header/OSGiHeader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/header/Parameters.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/header/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/help/Syntax.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/help/Warnings.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/help/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/MimeType.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/Namespaces.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/RepoIndex.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/ResourceAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/BlueprintAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/BundleAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/EE.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/KnownBundleAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/OSGiFrameworkAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/SCRAnalyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/indexer/analyzers/Yield.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/jareditor/JarConfiguration.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/jareditor/JarDocumentProvider.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/jareditor/JarEditor.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/junit/OSGiArgumentsTab.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/junit/OSGiJUnitLaunchShortcut.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/junit/OSGiJUnitLauncherConfigurationDelegate.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/junit/OSGiJUnitTabGroup.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/launch/LaunchDelegate.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/launch/LaunchTabGroup.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/launch/Shortcut.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/main/BaselineCommands.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/main/BndMessages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/main/DiffCommand.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/main/PatchCommand.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/main/RepoCommand.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/main/bnd.java
+  ADDED      SHA        57EE3BDF196034FB708705A3F4656111277E9F97
+  REMOVED    SHA        6CCDD322FC98BF0D7ACA4F26451A62F02D7A078A
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/main/packageinfo
+  REMOVED    SHA        4CBF1AE09B541F925C0D6BCBB8684EF85A0B8373
+  ADDED      SHA        D6E9A3759405E18A266202C40D9AA4EBA6F83A87
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/make/Make.java
+  ADDED      SHA        32419B285AD910CED3A1BE2CA2DE06103634D997
+  REMOVED    SHA        ABD503ABDB9F0A9D20FCDDB541B819EC0D70BA70
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/make/MakeBnd.java
+  ADDED      SHA        7A16BD28EBD4A2334424FB9836644D4ABCBFFABC
+  REMOVED    SHA        C4FC212EB0584C41BA276F679A0F137802F387AF
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/make/MakeCopy.java
+  REMOVED    SHA        06D298002296B2AEAFA4412515174712A2893ED2
+  ADDED      SHA        D4C879A84C0D44461049118CFD2B6DE835EC0295
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/calltree/CalltreeResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/component/ComponentAnnotationReader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/component/ServiceComponent.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/coverage/Coverage.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/coverage/CoverageResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/metatype/MetaTypeReader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/make/metatype/MetatypePlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/BsnToMavenPath.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenCommand.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenDependencyGraph.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenDeploy.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenDeployCmd.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenGroup.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/MavenRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/PomFromManifest.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/PomParser.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/PomResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/CachedPom.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/Maven.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/MavenEntry.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/MavenRemoteRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/Pom.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/ProjectPom.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/Repo.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/maven/support/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/obr/OBRFragment.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/About.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/AbstractResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Analyzer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/AnalyzerMessages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Annotation.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/AnnotationHeaders.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Builder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/BundleId.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/ClassDataCollector.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/ClassDataCollectors.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Classpath.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Clazz.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/CombinedResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/CommandResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Constants.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Contracts.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Descriptors.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Domain.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/EmbeddedResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/FileResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Instruction.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Instructions.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Jar.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/JarResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Macro.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/OSInformation.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/OpCodes.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Packages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/PreprocessResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Processor.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Resource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/URLResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/Verifier.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/WriteResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/ZipResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/eclipse/EclipseClasspath.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/CapReq.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/CapReqBuilder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/CapabilityImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/FilterParser.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/Filters.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/PersistentResource.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/RequirementImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/ResourceBuilder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/ResourceImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/osgi/resource/packageinfo
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/Activator.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/Central.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/builder/BndBuilder.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/builder/BndNature.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/builder/ToggleNatureAction.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/popup/actions/InstallBundle.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/popup/actions/MakeBundle.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/popup/actions/VerifyBundle.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/plugin/popup/actions/WrapBundle.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/BadLocationException.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/CopyOnWriteTextStore.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/Document.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/GapTextStore.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/IDocument.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/IRegion.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/ITextStore.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/Line.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/LineTracker.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/LineType.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/PropertiesLineReader.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/Region.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/properties/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/resource/repository/ResourceDescriptorImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/resource/repository/ResourceRepositoryImpl.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Actionable.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/service/AnalyzerPlugin.java
+  REMOVED    SHA        01DCF34F1B2C6961BC001D6EB5D68BFFEEF15F70
+  ADDED      SHA        D25A7039580D56816F0E9ECE913C23644B43802A
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/BndListener.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/CommandPlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Compiler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/DependencyContributor.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Deploy.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/EclipseJUnitTester.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/IndexProvider.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/LauncherPlugin.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/service/MakePlugin.java
+  ADDED      SHA        1DD964999442F1CEAED362243DA916643C348359
+  REMOVED    SHA        C6C083B804A2784D789182E00597B32CDFB89A78
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Plugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Refreshable.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Registry.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/RegistryDonePlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/RegistryPlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/RemoteRepositoryPlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/RepositoryListenerPlugin.java
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/bnd/service/RepositoryPlugin.java
+  REMOVED    SHA        3A6380D8D841D53668F18EF37363EFFA25A9FC73
+  ADDED      SHA        BC4B6801701A62CE8D4FD31090D31357D7595DC3
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/ResolutionPhase.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/ResourceHandle.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Scripter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/SignerPlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/Strategy.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/action/Action.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/action/NamedAction.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/action/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/classparser/ClassParser.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/classparser/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/Delta.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/Diff.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/Differ.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/Tree.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/Type.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/diff/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/extension/ExtensionActivator.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/extension/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/progress/ProgressPlugin.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/progress/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/InfoRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/MinimalRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/Phase.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/RepositoryDigest.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/ResourceRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/SearchableRepository.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/repository/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/resolve/hook/ResolverHook.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/resolve/hook/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/url/TaggedData.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/url/URLConnectionHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/url/URLConnector.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/service/url/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/signing/JartoolSigner.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/signing/Signer.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/bnd/test/ProjectLauncher.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/testing/DSTestWiring.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/testing/TestingLog.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/testing/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/BasicAuthentication.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/BndAuthentication.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/ConnectionSettings.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/DefaultURLConnectionHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/HttpsVerification.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/MultiURLConnectionHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/url/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/util/dto/DTO.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/util/dto/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/version/Version.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/version/VersionRange.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/bnd/version/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/configurable/Config.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/configurable/Configurable.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/configurable/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/base64/Base64.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/base64/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/EnumerationIterator.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/ExtList.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/IteratorList.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/LineCollection.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/Logic.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/MultiMap.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/SortedList.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/collections/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/converter/Converter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/converter/TypeReference.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/converter/packageinfo
+MAJOR      RESOURCE   OSGI-OPT/src/aQute/lib/deployer/FileRepo.java
+  REMOVED    SHA        43016599CDFB8D16479E06DBADA03D8AF32783F1
+  ADDED      SHA        C447FBEB09414CF0ECF5508BA06A649DC9DD34FD
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/deployer/ProjectRepo.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/deployer/RDImpl.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/deployer/RepoDeployer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/filter/Filter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/filter/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/Arguments.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/CommandLine.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/CommandLineMessages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/Description.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/OptionArgument.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/Options.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/getopt/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/hex/Hex.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/hex/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/io/IO.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/io/IOConstants.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/io/LimitedInputStream.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/io/packageinfo
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/jardiff/Diff.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/ArrayHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/BooleanHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/ByteArrayHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/CharacterHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/CollectionHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/DateHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/Decoder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/Encoder.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/EnumHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/FileHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/Handler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/JSONCodec.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/MapHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/NumberHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/ObjectHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/SpecialHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/StringHandler.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/json/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/justif/Justif.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/justif/Table.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/justif/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/markdown/MarkdownFormatter.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/About.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Analyzer.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Builder.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Clazz.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Constants.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/EmbeddedResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/FileResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Instruction.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Jar.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/JarResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Macro.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/OpCodes.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Plugin.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/PreprocessResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Processor.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Resource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/URLResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/Verifier.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/ZipResource.java
+REMOVED    RESOURCE   OSGI-OPT/src/aQute/lib/osgi/eclipse/EclipseClasspath.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/persistentmap/PersistentMap.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/persistentmap/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/settings/PasswordCryptor.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/settings/Settings.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/settings/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/strings/Strings.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/strings/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/tag/Tag.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/lib/tag/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/classdump/ClassDumper.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/classdump/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/command/Command.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/command/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Crypto.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Digest.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Digester.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Key.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/MD5.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/RSA.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/SHA1.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/SHA256.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Signer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/Verifier.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/cryptography/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filelock/DirectoryLock.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filelock/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/AndFilter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/Filter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/LiteralFilter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/NotFilter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/Operator.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/OrFilter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/SimpleFilter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/filters/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/forker/Forker.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/forker/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/generics/Create.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/generics/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/glob/Glob.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/glob/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/map/MAP.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/map/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/qtokens/QuotedTokenizer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/qtokens/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/reporter/Message.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/reporter/ReporterAdapter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/reporter/ReporterMessages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/reporter/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/sed/Domain.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/sed/Replacer.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/sed/ReplacerAdapter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/sed/Sed.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/sed/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/tuple/ComparablePair.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/tuple/Pair.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/libg/tuple/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/aQute/service/reporter/Messages.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/service/reporter/Report.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/service/reporter/Reporter.java
+ADDED      RESOURCE   OSGI-OPT/src/aQute/service/reporter/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Capability.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Namespace.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Requirement.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Resource.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Wire.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/Wiring.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/package-info.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/resource/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/bindex/BundleIndexer.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/bindex/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/Activate.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/Component.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ConfigurationPolicy.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/Deactivate.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/LookupReference.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/Modified.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/Reference.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ReferenceCardinality.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ReferencePolicy.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ReferencePolicyOption.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ReferenceScope.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/ServiceScope.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/package-info.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/component/annotations/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/Coordination.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/CoordinationException.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/CoordinationPermission.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/Coordinator.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/Participant.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/package-info.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/coordinator/packageinfo
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/repository/ContentNamespace.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/repository/Repository.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/repository/RepositoryContent.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/repository/package-info.java
+ADDED      RESOURCE   OSGI-OPT/src/org/osgi/service/repository/packageinfo
+ADDED      RESOURCE   aQute/bnd/annotation/ConsumerType.class
+MAJOR      RESOURCE   aQute/bnd/annotation/Export.class
+  ADDED      SHA        1143580202AA1EED607C3B44C18C4FDDFF807556
+  REMOVED    SHA        2BFAD4181827144A0B7BF70F1B50AFFFD1486DB0
+REMOVED    RESOURCE   aQute/bnd/annotation/Import.class
+REMOVED    RESOURCE   aQute/bnd/annotation/Pair.class
+ADDED      RESOURCE   aQute/bnd/annotation/ProviderType.class
+ADDED      RESOURCE   aQute/bnd/annotation/Version.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/Activate.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/Component.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/ConfigurationPolicy.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/Deactivate.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/Modified.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/Reference.class
+ADDED      RESOURCE   aQute/bnd/annotation/component/packageinfo
+ADDED      RESOURCE   aQute/bnd/annotation/headers/About.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleCategory.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleContributors.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleCopyright.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleDevelopers.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleDocURL.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/BundleLicense.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/Category.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/ProvideCapability.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/RequireCapability.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/Resolution.class
+ADDED      RESOURCE   aQute/bnd/annotation/headers/packageinfo
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/ASL_2_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/BSD_2_Clause.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/BSD_3_Clause.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/CDDL_1_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/CPL_1_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/EPL_1_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/GPL_2_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/GPL_3_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/LGPL_2_1.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/MIT_1_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/MPL_2_0.class
+ADDED      RESOURCE   aQute/bnd/annotation/licenses/packageinfo
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Configurable$ConfigurableHandler.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Configurable.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Meta$AD.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Meta$OCD.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Meta$Type.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/Meta.class
+ADDED      RESOURCE   aQute/bnd/annotation/metatype/packageinfo
+REMOVED    RESOURCE   aQute/bnd/annotation/package-info.class
+ADDED      RESOURCE   aQute/bnd/annotation/packageinfo
+ADDED      RESOURCE   aQute/bnd/ant/AntMessages.class
+MAJOR      RESOURCE   aQute/bnd/ant/BaseTask.class
+  REMOVED    SHA        51D09D3D464164F6ADC6362CA1B27B38DFFF7775
+  ADDED      SHA        B4D7F65A6C5B0945D0BBDD1AD45C628C69945A49
+MAJOR      RESOURCE   aQute/bnd/ant/BndTask.class
+  ADDED      SHA        2B9158162896486E31EF06E4EAADE45EC4F928BD
+  REMOVED    SHA        3D24F9D832A2CFCE08FB5B63A0787BF8D8B9C08F
+ADDED      RESOURCE   aQute/bnd/ant/ConsoleProgress$1.class
+ADDED      RESOURCE   aQute/bnd/ant/ConsoleProgress.class
+MAJOR      RESOURCE   aQute/bnd/ant/DeployTask.class
+  REMOVED    SHA        52741E8FA833A6F5770C2E07C44926B51AA03FF4
+  ADDED      SHA        B1FD3738343C5BDDEDCD61C8F16C82151F1E5C38
+MAJOR      RESOURCE   aQute/bnd/ant/EclipseTask.class
+  REMOVED    SHA        1EDD3A0BD19408E75550B699EFD8E605175A966C
+  ADDED      SHA        3BAD8CC8DB9F4C3AD5D0BBFF0CA4471FBB1DC27A
+MAJOR      RESOURCE   aQute/bnd/ant/ExpandPropertiesTask.class
+  ADDED      SHA        27A2EFF363C15BAF95BBF4FE0F4511F082CC89D7
+  REMOVED    SHA        2EFC6B42F01F13BFACB93F0D794547749A2392BF
+ADDED      RESOURCE   aQute/bnd/ant/PackageTask.class
+MAJOR      RESOURCE   aQute/bnd/ant/PrepareTask.class
+  REMOVED    SHA        54FE708015DC152FBA2AC912C5F43823F2297E11
+  ADDED      SHA        605DCAD147113525F3FA93F47FC598AC49B35266
+ADDED      RESOURCE   aQute/bnd/ant/ProjectBuildOrderTask.class
+MAJOR      RESOURCE   aQute/bnd/ant/ProjectTask.class
+  REMOVED    SHA        B99801A0059530E09B4C378C6BFB19F7EC51FC87
+  ADDED      SHA        C80B65108386F8484624573016EB7B170743DD5E
+ADDED      RESOURCE   aQute/bnd/ant/ReleaseTask.class
+ADDED      RESOURCE   aQute/bnd/ant/RunconfigToDistributionTask$JarFileFilter.class
+ADDED      RESOURCE   aQute/bnd/ant/RunconfigToDistributionTask$NonTestProjectFileFilter.class
+ADDED      RESOURCE   aQute/bnd/ant/RunconfigToDistributionTask.class
+ADDED      RESOURCE   aQute/bnd/ant/TestTask.class
+MAJOR      RESOURCE   aQute/bnd/ant/WrapTask.class
+  REMOVED    SHA        1B2451001E019453C391ADD866B2C6F447BB8634
+  ADDED      SHA        F7EF8607FD423257913E692044478BA62CBC23AA
+MAJOR      RESOURCE   aQute/bnd/ant/taskdef.properties
+  REMOVED    SHA        1F5BB944D17010889C822CB49ACD790CA0B4BEAA
+  ADDED      SHA        BB9108C257261825D22A7E893516293707C87E20
+MAJOR      RESOURCE   aQute/bnd/build/CircularDependencyException.class
+  REMOVED    SHA        76252D29BAB7D6C9EEE9CA30D7C487A214974E40
+  ADDED      SHA        D4B16B74592DDA7F7E3DC794FD2FEB062EFB2B45
+MAJOR      RESOURCE   aQute/bnd/build/Container$TYPE.class
+  ADDED      SHA        098B23F977005C8CD012084BF095FB6F0A4EA49F
+  REMOVED    SHA        AE3A226139BCF586C92B7003D1961DA741CA1738
+MAJOR      RESOURCE   aQute/bnd/build/Container.class
+  REMOVED    SHA        8458A19DB2BB531949466ED9DB5B72E310BAC81D
+  ADDED      SHA        D196DA5CE6E0FF6D680D279C3C1017656BB9A579
+ADDED      RESOURCE   aQute/bnd/build/DownloadBlocker$Stage.class
+ADDED      RESOURCE   aQute/bnd/build/DownloadBlocker.class
+ADDED      RESOURCE   aQute/bnd/build/ErrorDetails.class
+REMOVED    RESOURCE   aQute/bnd/build/Framework$FilterLoader.class
+REMOVED    RESOURCE   aQute/bnd/build/Framework.class
+ADDED      RESOURCE   aQute/bnd/build/JUnitLauncher.class
+ADDED      RESOURCE   aQute/bnd/build/Project$1.class
+ADDED      RESOURCE   aQute/bnd/build/Project$2.class
+MAJOR      RESOURCE   aQute/bnd/build/Project.class
+  ADDED      SHA        6B8BC68C0CA5FB105A03813147E09DC02C236327
+  REMOVED    SHA        C5F1CBF529FFFBE114BB09F8D0609B586E61103A
+MAJOR      RESOURCE   aQute/bnd/build/ProjectBuilder.class
+  REMOVED    SHA        2E8690B06114FC5ECF967371D0A9F92FA64D1B35
+  ADDED      SHA        6997CF482327EECA249D215F9522CD051FB13952
+ADDED      RESOURCE   aQute/bnd/build/ProjectLauncher$1.class
+ADDED      RESOURCE   aQute/bnd/build/ProjectLauncher$NotificationListener.class
+ADDED      RESOURCE   aQute/bnd/build/ProjectLauncher$NotificationType.class
+ADDED      RESOURCE   aQute/bnd/build/ProjectLauncher.class
+ADDED      RESOURCE   aQute/bnd/build/ProjectMessages.class
+ADDED      RESOURCE   aQute/bnd/build/ProjectTester.class
+ADDED      RESOURCE   aQute/bnd/build/ReflectAction.class
+ADDED      RESOURCE   aQute/bnd/build/ResolverMode.class
+ADDED      RESOURCE   aQute/bnd/build/Run.class
+ADDED      RESOURCE   aQute/bnd/build/ScriptAction.class
+ADDED      RESOURCE   aQute/bnd/build/Workspace$CachedFileRepo.class
+MAJOR      RESOURCE   aQute/bnd/build/Workspace.class
+  ADDED      SHA        53261A511EDC0A6939C7CC784F2929BE2D1A233C
+  REMOVED    SHA        C1E463E37C42CB254EC9EE5AFDB456108F01B263
+ADDED      RESOURCE   aQute/bnd/build/WorkspaceRepository.class
+ADDED      RESOURCE   aQute/bnd/build/defaults.bnd
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$1.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$2.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$3.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$4.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$5.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel$6.class
+ADDED      RESOURCE   aQute/bnd/build/model/BndEditModel.class
+ADDED      RESOURCE   aQute/bnd/build/model/EE.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/ComponentSvcReference.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/ExportedPackage.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/HeaderClause.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/ImportPattern.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/ServiceComponent.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/VersionedClause.class
+ADDED      RESOURCE   aQute/bnd/build/model/clauses/packageinfo
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/ClauseListConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/CollectionFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/Converter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/DefaultBooleanFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/DefaultFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/EEConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/EEFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/EnumConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/EnumFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/HeaderClauseConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/HeaderClauseFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/HeaderClauseListConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/MapFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/NoopConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/PropertiesConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/PropertiesEntryFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/RequirementFormatter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/RequirementListConverter$1.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/RequirementListConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/SimpleListConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/StringEntryConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/conversions/VersionedClauseConverter.class
+ADDED      RESOURCE   aQute/bnd/build/model/packageinfo
+ADDED      RESOURCE   aQute/bnd/build/packageinfo
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainer.class
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainerInitializer.class
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainerPage$1.class
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainerPage$2.class
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainerPage$3.class
+REMOVED    RESOURCE   aQute/bnd/classpath/BndContainerPage.class
+REMOVED    RESOURCE   aQute/bnd/classpath/ModelListener.class
+REMOVED    RESOURCE   aQute/bnd/classpath/messages.properties
+ADDED      RESOURCE   aQute/bnd/compatibility/Access.class
+ADDED      RESOURCE   aQute/bnd/compatibility/GenericParameter.class
+ADDED      RESOURCE   aQute/bnd/compatibility/GenericType$GenericArray.class
+ADDED      RESOURCE   aQute/bnd/compatibility/GenericType$GenericWildcard.class
+ADDED      RESOURCE   aQute/bnd/compatibility/GenericType.class
+ADDED      RESOURCE   aQute/bnd/compatibility/Kind.class
+ADDED      RESOURCE   aQute/bnd/compatibility/ParseSignatureBuilder$1.class
+ADDED      RESOURCE   aQute/bnd/compatibility/ParseSignatureBuilder.class
+ADDED      RESOURCE   aQute/bnd/compatibility/RuntimeSignatureBuilder.class
+ADDED      RESOURCE   aQute/bnd/compatibility/Scope.class
+ADDED      RESOURCE   aQute/bnd/compatibility/Signatures$Rover.class
+ADDED      RESOURCE   aQute/bnd/compatibility/Signatures.class
+ADDED      RESOURCE   aQute/bnd/component/AnnotationReader$1.class
+ADDED      RESOURCE   aQute/bnd/component/AnnotationReader.class
+ADDED      RESOURCE   aQute/bnd/component/ComponentDef.class
+ADDED      RESOURCE   aQute/bnd/component/DSAnnotations.class
+ADDED      RESOURCE   aQute/bnd/component/HeaderReader$1.class
+ADDED      RESOURCE   aQute/bnd/component/HeaderReader.class
+ADDED      RESOURCE   aQute/bnd/component/ReferenceDef.class
+ADDED      RESOURCE   aQute/bnd/component/TagResource.class
+ADDED      RESOURCE   aQute/bnd/component/error/DeclarativeServicesAnnotationError$ErrorType.class
+ADDED      RESOURCE   aQute/bnd/component/error/DeclarativeServicesAnnotationError.class
+ADDED      RESOURCE   aQute/bnd/component/error/packageinfo
+ADDED      RESOURCE   aQute/bnd/differ/Baseline$1.class
+ADDED      RESOURCE   aQute/bnd/differ/Baseline$BundleInfo.class
+ADDED      RESOURCE   aQute/bnd/differ/Baseline$Info.class
+ADDED      RESOURCE   aQute/bnd/differ/Baseline.class
+ADDED      RESOURCE   aQute/bnd/differ/DiffImpl.class
+ADDED      RESOURCE   aQute/bnd/differ/DiffPluginImpl.class
+ADDED      RESOURCE   aQute/bnd/differ/Element.class
+ADDED      RESOURCE   aQute/bnd/differ/JavaElement$1.class
+ADDED      RESOURCE   aQute/bnd/differ/JavaElement.class
+ADDED      RESOURCE   aQute/bnd/differ/RepositoryElement.class
+ADDED      RESOURCE   aQute/bnd/differ/packageinfo
+ADDED      RESOURCE   aQute/bnd/enroute/commands/EnrouteCommand$WorkspaceOptions.class
+ADDED      RESOURCE   aQute/bnd/enroute/commands/EnrouteCommand.class
+ADDED      RESOURCE   aQute/bnd/enroute/commands/EnrouteOptions.class
+ADDED      RESOURCE   aQute/bnd/filerepo/FileRepo$1.class
+ADDED      RESOURCE   aQute/bnd/filerepo/FileRepo$2.class
+ADDED      RESOURCE   aQute/bnd/filerepo/FileRepo$3.class
+ADDED      RESOURCE   aQute/bnd/filerepo/FileRepo.class
+ADDED      RESOURCE   aQute/bnd/filerepo/packageinfo
+ADDED      RESOURCE   aQute/bnd/gradle/BndPlugin.gradle
+ADDED      RESOURCE   aQute/bnd/header/Attrs$1.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$2.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$3.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$4.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$5.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$6.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$7.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$8.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$DataType.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs$Type.class
+ADDED      RESOURCE   aQute/bnd/header/Attrs.class
+ADDED      RESOURCE   aQute/bnd/header/OSGiHeader.class
+ADDED      RESOURCE   aQute/bnd/header/Parameters.class
+ADDED      RESOURCE   aQute/bnd/header/packageinfo
+ADDED      RESOURCE   aQute/bnd/help/Syntax.class
+ADDED      RESOURCE   aQute/bnd/help/Warnings.class
+ADDED      RESOURCE   aQute/bnd/help/changed.txt
+ADDED      RESOURCE   aQute/bnd/help/packageinfo
+ADDED      RESOURCE   aQute/bnd/help/syntax.properties
+ADDED      RESOURCE   aQute/bnd/help/syntax.xml
+ADDED      RESOURCE   aQute/bnd/indexer/MimeType.class
+ADDED      RESOURCE   aQute/bnd/indexer/NOTE
+ADDED      RESOURCE   aQute/bnd/indexer/Namespaces.class
+ADDED      RESOURCE   aQute/bnd/indexer/RepoIndex$IndexResult.class
+ADDED      RESOURCE   aQute/bnd/indexer/RepoIndex.class
+ADDED      RESOURCE   aQute/bnd/indexer/ResourceAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/BlueprintAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/BundleAnalyzer$1.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/BundleAnalyzer$2.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/BundleAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/EE$Segment.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/EE.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/KnownBundleAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/NOTE
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/OSGiFrameworkAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/SCRAnalyzer$SCRContentHandler.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/SCRAnalyzer.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/Yield.class
+ADDED      RESOURCE   aQute/bnd/indexer/analyzers/known-bundles.properties
+REMOVED    RESOURCE   aQute/bnd/jareditor/JarConfiguration.class
+REMOVED    RESOURCE   aQute/bnd/jareditor/JarDocumentProvider.class
+REMOVED    RESOURCE   aQute/bnd/jareditor/JarEditor.class
+REMOVED    RESOURCE   aQute/bnd/junit/OSGiArgumentsTab.class
+REMOVED    RESOURCE   aQute/bnd/junit/OSGiJUnitLaunchShortcut.class
+REMOVED    RESOURCE   aQute/bnd/junit/OSGiJUnitLauncherConfigurationDelegate.class
+REMOVED    RESOURCE   aQute/bnd/junit/OSGiJUnitTabGroup.class
+REMOVED    RESOURCE   aQute/bnd/launch/LaunchDelegate.class
+REMOVED    RESOURCE   aQute/bnd/launch/LaunchTabGroup.class
+REMOVED    RESOURCE   aQute/bnd/launch/Shortcut.class
+ADDED      RESOURCE   aQute/bnd/main/BaselineCommands$1.class
+ADDED      RESOURCE   aQute/bnd/main/BaselineCommands$PSpec.class
+ADDED      RESOURCE   aQute/bnd/main/BaselineCommands$baseLineOptions.class
+ADDED      RESOURCE   aQute/bnd/main/BaselineCommands$schemaOptions.class
+ADDED      RESOURCE   aQute/bnd/main/BaselineCommands.class
+ADDED      RESOURCE   aQute/bnd/main/BndMessages.class
+ADDED      RESOURCE   aQute/bnd/main/DiffCommand$diffOptions.class
+ADDED      RESOURCE   aQute/bnd/main/DiffCommand.class
+ADDED      RESOURCE   aQute/bnd/main/PatchCommand$applyOptions.class
+ADDED      RESOURCE   aQute/bnd/main/PatchCommand$createOptions.class
+ADDED      RESOURCE   aQute/bnd/main/PatchCommand.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$1Spec.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$CopyOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$RefreshOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$VersionsOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$diffOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$getOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$listOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$putOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$repoOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand$reposOptions.class
+ADDED      RESOURCE   aQute/bnd/main/RepoCommand.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$1.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$2.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$ActionOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$Alg.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$All.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$BootstrapOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$Bsn2UrlOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$ChangesOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$EEOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$FindOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$MergeOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$ParallelBuildOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$bndOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$buildoptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$buildxOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$bumpoptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$cleanOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$convertOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$createOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$debugOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$deliverableOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$dooptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$eclipseOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$extractOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$grepOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$hashOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$infoOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$macroOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$packageOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$patchOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$printOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$projectOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$releaseOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$runOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$runtestsOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$selectOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$settingOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$sourceOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$syntaxOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$testOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$typeOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$verifyOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$versionOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$viewOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$wrapOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd$xrefOptions.class
+ADDED      RESOURCE   aQute/bnd/main/bnd-completion.bash
+MAJOR      RESOURCE   aQute/bnd/main/bnd.class
+  REMOVED    SHA        EC8E2F8B6765E64C5D418653DC3871A6DA71844F
+  ADDED      SHA        FF3A6531C0DD6E4E5CD3D729560D599EB929AF89
+ADDED      RESOURCE   aQute/bnd/main/component.xslt
+ADDED      RESOURCE   aQute/bnd/main/maven-settings.xsl
+MAJOR      RESOURCE   aQute/bnd/main/packageinfo
+  REMOVED    SHA        4CBF1AE09B541F925C0D6BCBB8684EF85A0B8373
+  ADDED      SHA        D6E9A3759405E18A266202C40D9AA4EBA6F83A87
+ADDED      RESOURCE   aQute/bnd/main/schema.xsl
+ADDED      RESOURCE   aQute/bnd/main/testreport.xsl
+MAJOR      RESOURCE   aQute/bnd/make/Make.class
+  REMOVED    SHA        C450A93D92842FFF73F919416D67D8566529ECD2
+  ADDED      SHA        F248C429BED7224A1B11ADAB230FF812487D41E2
+MAJOR      RESOURCE   aQute/bnd/make/MakeBnd.class
+  ADDED      SHA        B3A3364451F9DC3A4E091C47EA9D85E345B6F6F1
+  REMOVED    SHA        F255AC80281C5577080A25A0E0F2C1CEF36C53E9
+MAJOR      RESOURCE   aQute/bnd/make/MakeCopy.class
+  REMOVED    SHA        1B9DD05EB5FF75A176E39BA6B3D23D8FA1610953
+  ADDED      SHA        C99F91A71B005FBA46F74B265A12475BA7B056AC
+ADDED      RESOURCE   aQute/bnd/make/calltree/CalltreeResource$1.class
+ADDED      RESOURCE   aQute/bnd/make/calltree/CalltreeResource$2.class
+ADDED      RESOURCE   aQute/bnd/make/calltree/CalltreeResource.class
+ADDED      RESOURCE   aQute/bnd/make/component/ComponentAnnotationReader.class
+ADDED      RESOURCE   aQute/bnd/make/component/ServiceComponent$ComponentMaker.class
+ADDED      RESOURCE   aQute/bnd/make/component/ServiceComponent.class
+ADDED      RESOURCE   aQute/bnd/make/coverage/Coverage$1.class
+ADDED      RESOURCE   aQute/bnd/make/coverage/Coverage$2.class
+ADDED      RESOURCE   aQute/bnd/make/coverage/Coverage$3.class
+ADDED      RESOURCE   aQute/bnd/make/coverage/Coverage.class
+ADDED      RESOURCE   aQute/bnd/make/coverage/CoverageResource.class
+ADDED      RESOURCE   aQute/bnd/make/metatype/MetaTypeReader$1.class
+ADDED      RESOURCE   aQute/bnd/make/metatype/MetaTypeReader$Find.class
+ADDED      RESOURCE   aQute/bnd/make/metatype/MetaTypeReader.class
+ADDED      RESOURCE   aQute/bnd/make/metatype/MetatypePlugin.class
+ADDED      RESOURCE   aQute/bnd/maven/BsnToMavenPath.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenCommand.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenDependencyGraph$Artifact.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenDependencyGraph$Scope.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenDependencyGraph.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenDeploy.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenDeployCmd.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenGroup.class
+ADDED      RESOURCE   aQute/bnd/maven/MavenRepository.class
+ADDED      RESOURCE   aQute/bnd/maven/PomFromManifest.class
+ADDED      RESOURCE   aQute/bnd/maven/PomParser.class
+ADDED      RESOURCE   aQute/bnd/maven/PomResource.class
+ADDED      RESOURCE   aQute/bnd/maven/support/CachedPom.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Maven.class
+ADDED      RESOURCE   aQute/bnd/maven/support/MavenEntry$1.class
+ADDED      RESOURCE   aQute/bnd/maven/support/MavenEntry$2.class
+ADDED      RESOURCE   aQute/bnd/maven/support/MavenEntry.class
+ADDED      RESOURCE   aQute/bnd/maven/support/MavenRemoteRepository.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Pom$Dependency.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Pom$Rover.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Pom$Scope.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Pom.class
+ADDED      RESOURCE   aQute/bnd/maven/support/ProjectPom$Rover.class
+ADDED      RESOURCE   aQute/bnd/maven/support/ProjectPom.class
+ADDED      RESOURCE   aQute/bnd/maven/support/Repo.class
+ADDED      RESOURCE   aQute/bnd/maven/support/packageinfo
+ADDED      RESOURCE   aQute/bnd/obr/OBRFragment.class
+ADDED      RESOURCE   aQute/bnd/osgi/About.class
+ADDED      RESOURCE   aQute/bnd/osgi/AbstractResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Analyzer$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Analyzer$2.class
+ADDED      RESOURCE   aQute/bnd/osgi/Analyzer.class
+ADDED      RESOURCE   aQute/bnd/osgi/AnalyzerMessages.class
+ADDED      RESOURCE   aQute/bnd/osgi/Annotation.class
+ADDED      RESOURCE   aQute/bnd/osgi/AnnotationHeaders.class
+ADDED      RESOURCE   aQute/bnd/osgi/Builder.class
+ADDED      RESOURCE   aQute/bnd/osgi/BundleId.class
+ADDED      RESOURCE   aQute/bnd/osgi/ClassDataCollector.class
+ADDED      RESOURCE   aQute/bnd/osgi/ClassDataCollectors.class
+ADDED      RESOURCE   aQute/bnd/osgi/Classpath$ClassVisitor.class
+ADDED      RESOURCE   aQute/bnd/osgi/Classpath.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$Assoc.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$ClassConstant.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$Def.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$FieldDef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$JAVA$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$JAVA.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$MethodDef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$QUERY.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz$TypeDef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Clazz.class
+ADDED      RESOURCE   aQute/bnd/osgi/CombinedResource$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/CombinedResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/CommandResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Constants.class
+ADDED      RESOURCE   aQute/bnd/osgi/Contracts$Contract.class
+ADDED      RESOURCE   aQute/bnd/osgi/Contracts.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$ArrayRef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$ConcreteRef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$Descriptor.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$PackageRef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$Signature.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$SignatureType.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors$TypeRef.class
+ADDED      RESOURCE   aQute/bnd/osgi/Descriptors.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain$1$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain$2$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain$2.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain$3.class
+ADDED      RESOURCE   aQute/bnd/osgi/Domain.class
+ADDED      RESOURCE   aQute/bnd/osgi/EmbeddedResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/FileResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Instruction$Filter.class
+ADDED      RESOURCE   aQute/bnd/osgi/Instruction.class
+ADDED      RESOURCE   aQute/bnd/osgi/Instructions.class
+ADDED      RESOURCE   aQute/bnd/osgi/Jar$Compression.class
+ADDED      RESOURCE   aQute/bnd/osgi/Jar.class
+ADDED      RESOURCE   aQute/bnd/osgi/JarResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Macro$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Macro$Link.class
+ADDED      RESOURCE   aQute/bnd/osgi/Macro.class
+ADDED      RESOURCE   aQute/bnd/osgi/OSInformation.class
+ADDED      RESOURCE   aQute/bnd/osgi/OpCodes.class
+ADDED      RESOURCE   aQute/bnd/osgi/Packages.class
+ADDED      RESOURCE   aQute/bnd/osgi/PreprocessResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Processor$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/Processor$CL.class
+ADDED      RESOURCE   aQute/bnd/osgi/Processor$FileLine.class
+ADDED      RESOURCE   aQute/bnd/osgi/Processor$SetLocationImpl.class
+ADDED      RESOURCE   aQute/bnd/osgi/Processor.class
+ADDED      RESOURCE   aQute/bnd/osgi/Resource.class
+ADDED      RESOURCE   aQute/bnd/osgi/URLResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/Verifier$ActivatorErrorType.class
+ADDED      RESOURCE   aQute/bnd/osgi/Verifier$BundleActivatorError.class
+ADDED      RESOURCE   aQute/bnd/osgi/Verifier$EE.class
+ADDED      RESOURCE   aQute/bnd/osgi/Verifier.class
+ADDED      RESOURCE   aQute/bnd/osgi/WriteResource$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/WriteResource$CountingOutputStream.class
+ADDED      RESOURCE   aQute/bnd/osgi/WriteResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/ZipResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/bnd.info
+ADDED      RESOURCE   aQute/bnd/osgi/eclipse/EclipseClasspath.class
+ADDED      RESOURCE   aQute/bnd/osgi/packageinfo
+ADDED      RESOURCE   aQute/bnd/osgi/profiles-OpenJDK8.properties
+ADDED      RESOURCE   aQute/bnd/osgi/resource/CapReq$MODE.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/CapReq.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/CapReqBuilder.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/CapabilityImpl.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$And.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$ApproximateExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$BundleExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Expression$1.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Expression$2.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Expression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$HostExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$IdentityExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Not.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Op.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Or.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$PackageExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$PatternExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$RangeExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$Rover.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$SimpleExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$SubExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser$WithRangeExpression.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/FilterParser.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/Filters.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource$Attr.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource$DataType.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource$Namespace.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource$RC.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource$RCData.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/PersistentResource.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/RequirementImpl.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/ResourceBuilder.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/ResourceImpl.class
+ADDED      RESOURCE   aQute/bnd/osgi/resource/packageinfo
+REMOVED    RESOURCE   aQute/bnd/plugin/Activator$1.class
+REMOVED    RESOURCE   aQute/bnd/plugin/Activator$2.class
+REMOVED    RESOURCE   aQute/bnd/plugin/Activator$3.class
+REMOVED    RESOURCE   aQute/bnd/plugin/Activator.class
+REMOVED    RESOURCE   aQute/bnd/plugin/Central$1.class
+REMOVED    RESOURCE   aQute/bnd/plugin/Central.class
+REMOVED    RESOURCE   aQute/bnd/plugin/builder/BndBuilder$DeltaVisitor.class
+REMOVED    RESOURCE   aQute/bnd/plugin/builder/BndBuilder$ResourceVisitor.class
+REMOVED    RESOURCE   aQute/bnd/plugin/builder/BndBuilder.class
+REMOVED    RESOURCE   aQute/bnd/plugin/builder/BndNature.class
+REMOVED    RESOURCE   aQute/bnd/plugin/builder/ToggleNatureAction.class
+REMOVED    RESOURCE   aQute/bnd/plugin/popup/actions/InstallBundle.class
+REMOVED    RESOURCE   aQute/bnd/plugin/popup/actions/MakeBundle.class
+REMOVED    RESOURCE   aQute/bnd/plugin/popup/actions/VerifyBundle.class
+REMOVED    RESOURCE   aQute/bnd/plugin/popup/actions/WrapBundle.class
+ADDED      RESOURCE   aQute/bnd/properties/BadLocationException.class
+ADDED      RESOURCE   aQute/bnd/properties/CopyOnWriteTextStore$StringTextStore.class
+ADDED      RESOURCE   aQute/bnd/properties/CopyOnWriteTextStore.class
+ADDED      RESOURCE   aQute/bnd/properties/Document$DelimiterInfo.class
+ADDED      RESOURCE   aQute/bnd/properties/Document.class
+ADDED      RESOURCE   aQute/bnd/properties/GapTextStore.class
+ADDED      RESOURCE   aQute/bnd/properties/IDocument.class
+ADDED      RESOURCE   aQute/bnd/properties/IRegion.class
+ADDED      RESOURCE   aQute/bnd/properties/ITextStore.class
+ADDED      RESOURCE   aQute/bnd/properties/Line.class
+ADDED      RESOURCE   aQute/bnd/properties/LineTracker.class
+ADDED      RESOURCE   aQute/bnd/properties/LineType.class
+ADDED      RESOURCE   aQute/bnd/properties/PropertiesLineReader.class
+ADDED      RESOURCE   aQute/bnd/properties/Region.class
+ADDED      RESOURCE   aQute/bnd/properties/packageinfo
+ADDED      RESOURCE   aQute/bnd/resource/repository/ResourceDescriptorImpl.class
+ADDED      RESOURCE   aQute/bnd/resource/repository/ResourceRepositoryImpl$1.class
+ADDED      RESOURCE   aQute/bnd/resource/repository/ResourceRepositoryImpl$2.class
+ADDED      RESOURCE   aQute/bnd/resource/repository/ResourceRepositoryImpl$FileLayout.class
+ADDED      RESOURCE   aQute/bnd/resource/repository/ResourceRepositoryImpl.class
+ADDED      RESOURCE   aQute/bnd/service/Actionable.class
+MAJOR      RESOURCE   aQute/bnd/service/AnalyzerPlugin.class
+  REMOVED    SHA        6174C960699993F1F85880FE856A711616BDE67E
+  ADDED      SHA        627FCDE5472BC5042106CCF06CBD3080BEA7B30D
+ADDED      RESOURCE   aQute/bnd/service/BndListener.class
+ADDED      RESOURCE   aQute/bnd/service/CommandPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/Compiler.class
+ADDED      RESOURCE   aQute/bnd/service/DependencyContributor.class
+ADDED      RESOURCE   aQute/bnd/service/Deploy.class
+ADDED      RESOURCE   aQute/bnd/service/EclipseJUnitTester.class
+ADDED      RESOURCE   aQute/bnd/service/IndexProvider.class
+ADDED      RESOURCE   aQute/bnd/service/LauncherPlugin.class
+MAJOR      RESOURCE   aQute/bnd/service/MakePlugin.class
+  REMOVED    SHA        6CBEC0D0266E75F5B416D933C8DB96BAD3F11858
+  ADDED      SHA        862ADC2AD2ED8E88CEE4F668F281B41C7883E53A
+ADDED      RESOURCE   aQute/bnd/service/Plugin.class
+ADDED      RESOURCE   aQute/bnd/service/Refreshable.class
+ADDED      RESOURCE   aQute/bnd/service/Registry.class
+ADDED      RESOURCE   aQute/bnd/service/RegistryDonePlugin.class
+ADDED      RESOURCE   aQute/bnd/service/RegistryPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/RemoteRepositoryPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/RepositoryListenerPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/RepositoryPlugin$DownloadListener.class
+ADDED      RESOURCE   aQute/bnd/service/RepositoryPlugin$PutOptions.class
+ADDED      RESOURCE   aQute/bnd/service/RepositoryPlugin$PutResult.class
+MAJOR      RESOURCE   aQute/bnd/service/RepositoryPlugin.class
+  ADDED      SHA        7865276EC971AD9FFACB3A296DECE9E4C9A4A03F
+  REMOVED    SHA        957238133AA5116ABC5415641ACE3D087FFD44BE
+ADDED      RESOURCE   aQute/bnd/service/ResolutionPhase.class
+ADDED      RESOURCE   aQute/bnd/service/ResourceHandle$Location.class
+ADDED      RESOURCE   aQute/bnd/service/ResourceHandle.class
+ADDED      RESOURCE   aQute/bnd/service/Scripter.class
+ADDED      RESOURCE   aQute/bnd/service/SignerPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/Strategy.class
+ADDED      RESOURCE   aQute/bnd/service/action/Action.class
+ADDED      RESOURCE   aQute/bnd/service/action/NamedAction.class
+ADDED      RESOURCE   aQute/bnd/service/action/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/classparser/ClassParser.class
+ADDED      RESOURCE   aQute/bnd/service/classparser/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/diff/Delta.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Diff$Data.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Diff$Ignore.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Diff.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Differ.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Tree$Data.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Tree.class
+ADDED      RESOURCE   aQute/bnd/service/diff/Type.class
+ADDED      RESOURCE   aQute/bnd/service/diff/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/extension/ExtensionActivator.class
+ADDED      RESOURCE   aQute/bnd/service/extension/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/progress/ProgressPlugin$Task.class
+ADDED      RESOURCE   aQute/bnd/service/progress/ProgressPlugin.class
+ADDED      RESOURCE   aQute/bnd/service/progress/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/repository/InfoRepository.class
+ADDED      RESOURCE   aQute/bnd/service/repository/MinimalRepository$Gestalt.class
+ADDED      RESOURCE   aQute/bnd/service/repository/MinimalRepository.class
+ADDED      RESOURCE   aQute/bnd/service/repository/Phase.class
+ADDED      RESOURCE   aQute/bnd/service/repository/RepositoryDigest.class
+ADDED      RESOURCE   aQute/bnd/service/repository/ResourceRepository$Listener.class
+ADDED      RESOURCE   aQute/bnd/service/repository/ResourceRepository$ResourceRepositoryEvent.class
+ADDED      RESOURCE   aQute/bnd/service/repository/ResourceRepository$TYPE.class
+ADDED      RESOURCE   aQute/bnd/service/repository/ResourceRepository.class
+ADDED      RESOURCE   aQute/bnd/service/repository/SearchableRepository$ResourceDescriptor.class
+ADDED      RESOURCE   aQute/bnd/service/repository/SearchableRepository.class
+ADDED      RESOURCE   aQute/bnd/service/repository/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/resolve/hook/ResolverHook.class
+ADDED      RESOURCE   aQute/bnd/service/resolve/hook/packageinfo
+ADDED      RESOURCE   aQute/bnd/service/url/TaggedData.class
+ADDED      RESOURCE   aQute/bnd/service/url/URLConnectionHandler.class
+ADDED      RESOURCE   aQute/bnd/service/url/URLConnector.class
+ADDED      RESOURCE   aQute/bnd/service/url/packageinfo
+ADDED      RESOURCE   aQute/bnd/signing/JartoolSigner$1.class
+ADDED      RESOURCE   aQute/bnd/signing/JartoolSigner.class
+ADDED      RESOURCE   aQute/bnd/signing/Signer.class
+REMOVED    RESOURCE   aQute/bnd/test/ProjectLauncher$1.class
+REMOVED    RESOURCE   aQute/bnd/test/ProjectLauncher$Streamer.class
+REMOVED    RESOURCE   aQute/bnd/test/ProjectLauncher.class
+REMOVED    RESOURCE   aQute/bnd/test/aQute.runtime.jar
+ADDED      RESOURCE   aQute/bnd/testing/DSTestWiring$Component.class
+ADDED      RESOURCE   aQute/bnd/testing/DSTestWiring$Reference.class
+ADDED      RESOURCE   aQute/bnd/testing/DSTestWiring.class
+ADDED      RESOURCE   aQute/bnd/testing/TestingLog$1.class
+ADDED      RESOURCE   aQute/bnd/testing/TestingLog$Config.class
+ADDED      RESOURCE   aQute/bnd/testing/TestingLog.class
+ADDED      RESOURCE   aQute/bnd/testing/packageinfo
+ADDED      RESOURCE   aQute/bnd/url/BasicAuthentication.class
+ADDED      RESOURCE   aQute/bnd/url/BndAuthentication.class
+ADDED      RESOURCE   aQute/bnd/url/ConnectionSettings$Config.class
+ADDED      RESOURCE   aQute/bnd/url/ConnectionSettings.class
+ADDED      RESOURCE   aQute/bnd/url/DefaultURLConnectionHandler.class
+ADDED      RESOURCE   aQute/bnd/url/HttpsVerification$1.class
+ADDED      RESOURCE   aQute/bnd/url/HttpsVerification$2.class
+ADDED      RESOURCE   aQute/bnd/url/HttpsVerification.class
+ADDED      RESOURCE   aQute/bnd/url/MultiURLConnectionHandler.class
+ADDED      RESOURCE   aQute/bnd/url/packageinfo
+ADDED      RESOURCE   aQute/bnd/util/dto/DTO.class
+ADDED      RESOURCE   aQute/bnd/util/dto/packageinfo
+ADDED      RESOURCE   aQute/bnd/version/Version.class
+ADDED      RESOURCE   aQute/bnd/version/VersionRange.class
+ADDED      RESOURCE   aQute/bnd/version/packageinfo
+ADDED      RESOURCE   aQute/configurable/Config.class
+ADDED      RESOURCE   aQute/configurable/Configurable$ConfigurableHandler.class
+ADDED      RESOURCE   aQute/configurable/Configurable.class
+ADDED      RESOURCE   aQute/configurable/packageinfo
+ADDED      RESOURCE   aQute/lib/base64/Base64.class
+ADDED      RESOURCE   aQute/lib/base64/packageinfo
+ADDED      RESOURCE   aQute/lib/collections/EnumerationIterator.class
+ADDED      RESOURCE   aQute/lib/collections/ExtList.class
+ADDED      RESOURCE   aQute/lib/collections/IteratorList.class
+ADDED      RESOURCE   aQute/lib/collections/LineCollection.class
+ADDED      RESOURCE   aQute/lib/collections/Logic.class
+ADDED      RESOURCE   aQute/lib/collections/MultiMap$1.class
+ADDED      RESOURCE   aQute/lib/collections/MultiMap.class
+ADDED      RESOURCE   aQute/lib/collections/SortedList$1.class
+ADDED      RESOURCE   aQute/lib/collections/SortedList$It.class
+ADDED      RESOURCE   aQute/lib/collections/SortedList.class
+ADDED      RESOURCE   aQute/lib/collections/packageinfo
+ADDED      RESOURCE   aQute/lib/converter/Converter$1.class
+ADDED      RESOURCE   aQute/lib/converter/Converter$Hook.class
+ADDED      RESOURCE   aQute/lib/converter/Converter.class
+ADDED      RESOURCE   aQute/lib/converter/TypeReference.class
+ADDED      RESOURCE   aQute/lib/converter/packageinfo
+ADDED      RESOURCE   aQute/lib/deployer/FileRepo$1.class
+ADDED      RESOURCE   aQute/lib/deployer/FileRepo$2.class
+ADDED      RESOURCE   aQute/lib/deployer/FileRepo$3.class
+MAJOR      RESOURCE   aQute/lib/deployer/FileRepo.class
+  ADDED      SHA        5AE445A1EFA3EA6F6BF2120F28AF029BC32DEFC1
+  REMOVED    SHA        DA9A1E483557668D4A3CD944C96DB236DE7920CB
+REMOVED    RESOURCE   aQute/lib/deployer/ProjectRepo.class
+ADDED      RESOURCE   aQute/lib/deployer/RDImpl.class
+REMOVED    RESOURCE   aQute/lib/deployer/RepoDeployer.class
+ADDED      RESOURCE   aQute/lib/filter/Filter$DictQuery.class
+ADDED      RESOURCE   aQute/lib/filter/Filter$MapQuery.class
+ADDED      RESOURCE   aQute/lib/filter/Filter$Query.class
+ADDED      RESOURCE   aQute/lib/filter/Filter.class
+ADDED      RESOURCE   aQute/lib/filter/packageinfo
+ADDED      RESOURCE   aQute/lib/getopt/Arguments.class
+ADDED      RESOURCE   aQute/lib/getopt/CommandLine$Option.class
+ADDED      RESOURCE   aQute/lib/getopt/CommandLine.class
+ADDED      RESOURCE   aQute/lib/getopt/CommandLineMessages.class
+ADDED      RESOURCE   aQute/lib/getopt/Description.class
+ADDED      RESOURCE   aQute/lib/getopt/OptionArgument.class
+ADDED      RESOURCE   aQute/lib/getopt/Options.class
+ADDED      RESOURCE   aQute/lib/getopt/packageinfo
+ADDED      RESOURCE   aQute/lib/hex/Hex.class
+ADDED      RESOURCE   aQute/lib/hex/packageinfo
+ADDED      RESOURCE   aQute/lib/io/IO$1.class
+ADDED      RESOURCE   aQute/lib/io/IO$2.class
+ADDED      RESOURCE   aQute/lib/io/IO.class
+ADDED      RESOURCE   aQute/lib/io/IOConstants.class
+ADDED      RESOURCE   aQute/lib/io/LimitedInputStream.class
+ADDED      RESOURCE   aQute/lib/io/packageinfo
+REMOVED    RESOURCE   aQute/lib/jardiff/Diff.class
+ADDED      RESOURCE   aQute/lib/json/ArrayHandler.class
+ADDED      RESOURCE   aQute/lib/json/BooleanHandler.class
+ADDED      RESOURCE   aQute/lib/json/ByteArrayHandler.class
+ADDED      RESOURCE   aQute/lib/json/CharacterHandler.class
+ADDED      RESOURCE   aQute/lib/json/CollectionHandler.class
+ADDED      RESOURCE   aQute/lib/json/DateHandler.class
+ADDED      RESOURCE   aQute/lib/json/Decoder.class
+ADDED      RESOURCE   aQute/lib/json/Encoder.class
+ADDED      RESOURCE   aQute/lib/json/EnumHandler.class
+ADDED      RESOURCE   aQute/lib/json/FileHandler.class
+ADDED      RESOURCE   aQute/lib/json/Handler.class
+ADDED      RESOURCE   aQute/lib/json/JSONCodec.class
+ADDED      RESOURCE   aQute/lib/json/MapHandler.class
+ADDED      RESOURCE   aQute/lib/json/NumberHandler.class
+ADDED      RESOURCE   aQute/lib/json/ObjectHandler$1.class
+ADDED      RESOURCE   aQute/lib/json/ObjectHandler.class
+ADDED      RESOURCE   aQute/lib/json/SpecialHandler.class
+ADDED      RESOURCE   aQute/lib/json/StringHandler.class
+ADDED      RESOURCE   aQute/lib/json/packageinfo
+ADDED      RESOURCE   aQute/lib/justif/Justif.class
+ADDED      RESOURCE   aQute/lib/justif/Table.class
+ADDED      RESOURCE   aQute/lib/justif/packageinfo
+ADDED      RESOURCE   aQute/lib/markdown/MarkdownFormatter.class
+REMOVED    RESOURCE   aQute/lib/osgi/About.class
+REMOVED    RESOURCE   aQute/lib/osgi/Analyzer.class
+REMOVED    RESOURCE   aQute/lib/osgi/Builder.class
+REMOVED    RESOURCE   aQute/lib/osgi/Clazz$Assoc.class
+REMOVED    RESOURCE   aQute/lib/osgi/Clazz$QUERY.class
+REMOVED    RESOURCE   aQute/lib/osgi/Clazz.class
+REMOVED    RESOURCE   aQute/lib/osgi/Constants.class
+REMOVED    RESOURCE   aQute/lib/osgi/EmbeddedResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/FileResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/Instruction.class
+REMOVED    RESOURCE   aQute/lib/osgi/Jar.class
+REMOVED    RESOURCE   aQute/lib/osgi/JarResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/Macro$Link.class
+REMOVED    RESOURCE   aQute/lib/osgi/Macro.class
+REMOVED    RESOURCE   aQute/lib/osgi/OpCodes.class
+REMOVED    RESOURCE   aQute/lib/osgi/Plugin.class
+REMOVED    RESOURCE   aQute/lib/osgi/PreprocessResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/Processor.class
+REMOVED    RESOURCE   aQute/lib/osgi/Resource.class
+REMOVED    RESOURCE   aQute/lib/osgi/URLResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/Verifier.class
+REMOVED    RESOURCE   aQute/lib/osgi/ZipResource.class
+REMOVED    RESOURCE   aQute/lib/osgi/bnd.info
+REMOVED    RESOURCE   aQute/lib/osgi/eclipse/EclipseClasspath.class
+ADDED      RESOURCE   aQute/lib/persistentmap/PersistentMap$1$1$1.class
+ADDED      RESOURCE   aQute/lib/persistentmap/PersistentMap$1$1.class
+ADDED      RESOURCE   aQute/lib/persistentmap/PersistentMap$1.class
+ADDED      RESOURCE   aQute/lib/persistentmap/PersistentMap.class
+ADDED      RESOURCE   aQute/lib/persistentmap/packageinfo
+ADDED      RESOURCE   aQute/lib/settings/PasswordCryptor.class
+ADDED      RESOURCE   aQute/lib/settings/Settings$Data.class
+ADDED      RESOURCE   aQute/lib/settings/Settings.class
+ADDED      RESOURCE   aQute/lib/settings/packageinfo
+ADDED      RESOURCE   aQute/lib/strings/Strings.class
+ADDED      RESOURCE   aQute/lib/strings/packageinfo
+ADDED      RESOURCE   aQute/lib/tag/Tag.class
+ADDED      RESOURCE   aQute/lib/tag/packageinfo
+ADDED      RESOURCE   aQute/libg/classdump/ClassDumper$Assoc.class
+ADDED      RESOURCE   aQute/libg/classdump/ClassDumper.class
+ADDED      RESOURCE   aQute/libg/classdump/packageinfo
+ADDED      RESOURCE   aQute/libg/command/Command$1.class
+ADDED      RESOURCE   aQute/libg/command/Command$2.class
+ADDED      RESOURCE   aQute/libg/command/Command$3.class
+ADDED      RESOURCE   aQute/libg/command/Command$Collector.class
+ADDED      RESOURCE   aQute/libg/command/Command.class
+ADDED      RESOURCE   aQute/libg/command/packageinfo
+ADDED      RESOURCE   aQute/libg/cryptography/Crypto.class
+ADDED      RESOURCE   aQute/libg/cryptography/Digest.class
+ADDED      RESOURCE   aQute/libg/cryptography/Digester.class
+ADDED      RESOURCE   aQute/libg/cryptography/Key.class
+ADDED      RESOURCE   aQute/libg/cryptography/MD5$1.class
+ADDED      RESOURCE   aQute/libg/cryptography/MD5.class
+ADDED      RESOURCE   aQute/libg/cryptography/RSA.class
+ADDED      RESOURCE   aQute/libg/cryptography/SHA1$1.class
+ADDED      RESOURCE   aQute/libg/cryptography/SHA1.class
+ADDED      RESOURCE   aQute/libg/cryptography/SHA256$1.class
+ADDED      RESOURCE   aQute/libg/cryptography/SHA256.class
+ADDED      RESOURCE   aQute/libg/cryptography/Signer.class
+ADDED      RESOURCE   aQute/libg/cryptography/Verifier.class
+ADDED      RESOURCE   aQute/libg/cryptography/packageinfo
+ADDED      RESOURCE   aQute/libg/filelock/DirectoryLock.class
+ADDED      RESOURCE   aQute/libg/filelock/packageinfo
+ADDED      RESOURCE   aQute/libg/filters/AndFilter.class
+ADDED      RESOURCE   aQute/libg/filters/Filter.class
+ADDED      RESOURCE   aQute/libg/filters/LiteralFilter.class
+ADDED      RESOURCE   aQute/libg/filters/NotFilter.class
+ADDED      RESOURCE   aQute/libg/filters/Operator.class
+ADDED      RESOURCE   aQute/libg/filters/OrFilter.class
+ADDED      RESOURCE   aQute/libg/filters/SimpleFilter.class
+ADDED      RESOURCE   aQute/libg/filters/packageinfo
+ADDED      RESOURCE   aQute/libg/forker/Forker$Job.class
+ADDED      RESOURCE   aQute/libg/forker/Forker.class
+ADDED      RESOURCE   aQute/libg/forker/packageinfo
+ADDED      RESOURCE   aQute/libg/generics/Create.class
+ADDED      RESOURCE   aQute/libg/generics/packageinfo
+ADDED      RESOURCE   aQute/libg/glob/Glob.class
+ADDED      RESOURCE   aQute/libg/glob/packageinfo
+ADDED      RESOURCE   aQute/libg/map/MAP$MAPX.class
+ADDED      RESOURCE   aQute/libg/map/MAP.class
+ADDED      RESOURCE   aQute/libg/map/packageinfo
+ADDED      RESOURCE   aQute/libg/qtokens/QuotedTokenizer.class
+ADDED      RESOURCE   aQute/libg/qtokens/packageinfo
+ADDED      RESOURCE   aQute/libg/reporter/Message.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterAdapter$LocationImpl.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterAdapter.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterMessages$1.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterMessages$ERRORImpl.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterMessages$WARNINGImpl.class
+ADDED      RESOURCE   aQute/libg/reporter/ReporterMessages.class
+ADDED      RESOURCE   aQute/libg/reporter/packageinfo
+ADDED      RESOURCE   aQute/libg/sed/Domain.class
+ADDED      RESOURCE   aQute/libg/sed/Replacer.class
+ADDED      RESOURCE   aQute/libg/sed/ReplacerAdapter$1.class
+ADDED      RESOURCE   aQute/libg/sed/ReplacerAdapter$2.class
+ADDED      RESOURCE   aQute/libg/sed/ReplacerAdapter$3.class
+ADDED      RESOURCE   aQute/libg/sed/ReplacerAdapter$Link.class
+ADDED      RESOURCE   aQute/libg/sed/ReplacerAdapter.class
+ADDED      RESOURCE   aQute/libg/sed/Sed.class
+ADDED      RESOURCE   aQute/libg/sed/packageinfo
+ADDED      RESOURCE   aQute/libg/tuple/ComparablePair.class
+ADDED      RESOURCE   aQute/libg/tuple/Pair.class
+ADDED      RESOURCE   aQute/libg/tuple/packageinfo
+ADDED      RESOURCE   aQute/service/reporter/Messages$ERROR.class
+ADDED      RESOURCE   aQute/service/reporter/Messages$WARNING.class
+ADDED      RESOURCE   aQute/service/reporter/Messages.class
+ADDED      RESOURCE   aQute/service/reporter/Report$Location.class
+ADDED      RESOURCE   aQute/service/reporter/Report.class
+ADDED      RESOURCE   aQute/service/reporter/Reporter$SetLocation.class
+ADDED      RESOURCE   aQute/service/reporter/Reporter.class
+ADDED      RESOURCE   aQute/service/reporter/packageinfo
+ADDED      RESOURCE   embedded-repo.jar
+REMOVED    RESOURCE   maven-dependencies.txt
+ADDED      RESOURCE   org/osgi/resource/Capability.class
+ADDED      RESOURCE   org/osgi/resource/Namespace.class
+ADDED      RESOURCE   org/osgi/resource/Requirement.class
+ADDED      RESOURCE   org/osgi/resource/Resource.class
+ADDED      RESOURCE   org/osgi/resource/Wire.class
+ADDED      RESOURCE   org/osgi/resource/Wiring.class
+ADDED      RESOURCE   org/osgi/resource/package-info.class
+ADDED      RESOURCE   org/osgi/resource/packageinfo
+ADDED      RESOURCE   org/osgi/service/bindex/BundleIndexer.class
+ADDED      RESOURCE   org/osgi/service/bindex/packageinfo
+ADDED      RESOURCE   org/osgi/service/component/annotations/Activate.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/Component.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ConfigurationPolicy.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/Deactivate.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/LookupReference.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/Modified.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/Reference.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ReferenceCardinality.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ReferencePolicy.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ReferencePolicyOption.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ReferenceScope.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/ServiceScope.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/package-info.class
+ADDED      RESOURCE   org/osgi/service/component/annotations/packageinfo
+ADDED      RESOURCE   org/osgi/service/coordinator/Coordination.class
+ADDED      RESOURCE   org/osgi/service/coordinator/CoordinationException.class
+ADDED      RESOURCE   org/osgi/service/coordinator/CoordinationPermission$1.class
+ADDED      RESOURCE   org/osgi/service/coordinator/CoordinationPermission.class
+ADDED      RESOURCE   org/osgi/service/coordinator/CoordinationPermissionCollection.class
+ADDED      RESOURCE   org/osgi/service/coordinator/Coordinator.class
+ADDED      RESOURCE   org/osgi/service/coordinator/Participant.class
+ADDED      RESOURCE   org/osgi/service/coordinator/SignerProperty.class
+ADDED      RESOURCE   org/osgi/service/coordinator/package-info.class
+ADDED      RESOURCE   org/osgi/service/coordinator/packageinfo
+ADDED      RESOURCE   org/osgi/service/repository/ContentNamespace.class
+ADDED      RESOURCE   org/osgi/service/repository/Repository.class
+ADDED      RESOURCE   org/osgi/service/repository/RepositoryContent.class
+ADDED      RESOURCE   org/osgi/service/repository/package-info.class
+ADDED      RESOURCE   org/osgi/service/repository/packageinfo
+REMOVED    RESOURCE   plugin.xml
+REMOVED    RESOURCE   pom.xml
+ADDED      RESOURCE   templates/enroute.zip
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/digest.html b/org.bndtools.help/docs/commands/digest.html new file mode 100644 index 0000000000..cd88c33e08 --- /dev/null +++ b/org.bndtools.help/docs/commands/digest.html @@ -0,0 +1,30 @@ + + + + +digest + + + +

digest

+

Synopsis:

+
   digest [options]  <file...>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd digest generated/biz.aQute.bnd.jar 
+16B415286B53FA499BD7B2684A93924CA7C198C8
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/do.html b/org.bndtools.help/docs/commands/do.html new file mode 100644 index 0000000000..4081b3e169 --- /dev/null +++ b/org.bndtools.help/docs/commands/do.html @@ -0,0 +1,49 @@ + + + + +do + + + +

do

+

Synopsis:

+
   do [options]  ...
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd do generated/biz.aQute.bnd.jar 
+[MANIFEST biz.aQute.bnd]
+Bnd-LastModified                         1404915822703                           
+Bundle-Copyright                         Copyright (c) aQute (2000, 2014). All Rights Reserved.
+Bundle-Description                       This command line utility is the Swiss army knife of OSGi. It provides you with a breadth
+Bundle-DocURL                            http://www.aQute.biz/Code/Bnd           
+Bundle-License                           http://www.opensource.org/licenses/apache2.0.php; description="Apache License, Version 2.0"; link=http://www.apache.org/licenses/LICENSE-2.0.html
+Bundle-ManifestVersion                   2                                       
+Bundle-Name                              biz.aQute.bnd                           
+Bundle-SCM                               git://github.com/bndtools/bnd.git       
+Bundle-SymbolicName                      biz.aQute.bnd                           
+Bundle-Vendor                            aQute SARL http://www.aQute.biz         
+Bundle-Version                           2.4.0.201407091423                      
+Conditional-Package                      aQute.libg.*,aQute.lib.*,aQute.configurable
+Created-By                               1.8.0 (Oracle Corporation)              
+Export-Package                           aQute.bnd.service;version="4.1.0";uses:="aQute.bnd.build,aQute.bnd.osgi,aQute.bnd.version,aQute.service.reporter",aQute.bnd.service.action;version="2.0.0";uses:="aQute.bnd.build",aQute.bnd.service.classparser;version="1.0";uses:="aQute.bnd.osgi",aQute.bnd.service.diff;version="1.0";uses:="aQute.bnd.osgi",aQute.bnd.service.extension;version="1.0";uses:="aQute.bnd.build",aQute.bnd.service.progress;version="1.0.0",aQute.bnd.service.repository;version="1.2";uses:="aQute.bnd.service,aQute.bnd.version,aQute.service.reporter,org.osgi.resource",aQute.bnd.service.resolve.hook;version="1.0";uses:="org.osgi.resource",aQute.bnd.service.url;version="1.2",aQute.bnd.header;version="1.3.0";uses:="aQute.bnd.version,aQute.service.reporter",aQute.bnd.osgi;version="2.3.0";uses:="aQute.bnd.build,aQute.bnd.header,aQute.bnd.service,aQute.bnd.util.dto,aQute.bnd.version,aQute.service.reporter",aQute.bnd.build;version="2.4.0";uses:="aQute.bnd.maven.support,aQute.bnd.osgi,aQute.bnd.service,aQute.bnd.service.action,aQute.bnd.version,aQute.service.reporter",aQute.bnd.version;version="1.1.0",aQute.bnd.maven.support;version="2.0";uses:="aQute.bnd.service,aQute.bnd.version,aQute.service.reporter,javax.xml.xpath,org.w3c.dom",org.osgi.service.bindex;version="1.0",aQute.service.reporter;version="1.0.1",aQute.bnd.osgi.resource;version="1.4.0";uses:="aQute.bnd.header,aQute.bnd.util.dto,org.osgi.resource",org.osgi.service.repository;version="1.0";uses:="org.osgi.resource",org.osgi.resource;version="1.0",aQute.bnd.util.dto;version="1.0"
+Git-Descriptor                           2.4.0.M1-66-gc1ad07d-dirty              
+Git-SHA                                  c1ad07dfeb4704ce590bd93c1405d7bfe8bef131
+Import-Package                           org.apache.tools.ant;resolution:=optional,org.apache.tools.ant.taskdefs;resolution:=optional,org.apache.tools.ant.types;resolution:=optional,aQute.bnd.service;version="[4.1,5)",aQute.bnd.service.action;version="[2.0,2.1)",aQute.bnd.service.diff;version="[1.0,2)",aQute.bnd.service.progress;version="[1.0,2)",aQute.bnd.service.repository;version="[1.2,2)",aQute.bnd.service.url;version="[1.2,2)",aQute.bnd.version;version="[1.1,2)",aQute.service.reporter;version="[1.0,2)",javax.crypto,javax.crypto.spec,javax.naming,javax.net.ssl,javax.script,javax.xml.namespace,javax.xml.parsers,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.stream,javax.xml.xpath,org.osgi.framework;version="[1.6,2)",org.osgi.resource;version="[1.0,2)",org.osgi.service.log;version="[1.3,2)",org.w3c.dom,org.xml.sax,org.xml.sax.helpers,junit.framework;resolution:=optional;version="[3.8,4)"
+Main-Class                               aQute.bnd.main.bnd                      
+Manifest-Version                         1.0                                     
+Private-Package                          aQute.bnd.annotation;version="1.43.2",aQute.bnd.annotation.component;version="1.43.1",aQute.bnd.annotation.headers;version="1.0",aQute.bnd.annotation.licenses;version="1.0",aQute.bnd.annotation.metatype;version="1.44.1",aQute.bnd.ant,aQute.bnd.build.model;version="2.6.0",aQute.bnd.build.model.clauses;version=2,aQute.bnd.build.model.conversions,aQute.bnd.compatibility,aQute.bnd.component,aQute.bnd.component.error;version="1.0.0",aQute.bnd.differ;version="1.1.0",aQute.bnd.enroute.commands,aQute.bnd.filerepo;version="1.0",aQute.bnd.gradle,aQute.bnd.help;version="1.1",aQute.bnd.indexer,aQute.bnd.indexer.analyzers,aQute.bnd.main;version="0.9",aQute.bnd.make,aQute.bnd.make.calltree,aQute.bnd.make.component,aQute.bnd.make.coverage,aQute.bnd.make.metatype,aQute.bnd.maven,aQute.bnd.obr,aQute.bnd.osgi.eclipse,aQute.bnd.properties;version="2.0",aQute.bnd.resource.repository,aQute.bnd.signing,aQute.bnd.testing;version="1.0",aQute.bnd.url;version="1.0",aQute.configurable;version="1.0.0",aQute.lib.deployer,embedded-repo.jar,org.osgi.service.component.annotations;version="1.3",org.osgi.service.coordinator;version="1.0",templates,aQute.lib.base64;version="1.2.0",aQute.lib.collections;version="1.2.0",aQute.lib.converter;version="2.0.1",aQute.lib.filter;version="1.1.0",aQute.lib.getopt;version="1.0.0",aQute.lib.hex;version="1.1.0",aQute.lib.io;version="1.4.0",aQute.lib.json;version="3.0.0",aQute.lib.justif;version="1.1.0",aQute.lib.persistentmap;version="1.1.0",aQute.lib.settings;version="1.2.0",aQute.lib.strings;version="1.1.0",aQute.lib.tag;version="1.1",aQute.libg.classdump;version="1.0",aQute.libg.command;version="3.0.0",aQute.libg.cryptography;version="1.1.0",aQute.libg.filelock;version="1.0.0",aQute.libg.filters;version="1.0",aQute.libg.forker;version="1.0",aQute.libg.generics;version="1.0",aQute.libg.glob;version="1.1.1",aQute.libg.map;version="1.2.0",aQute.libg.qtokens;version="1.0",aQute.libg.reporter;version="1.5",aQute.libg.sed;version="1.1.0",aQute.libg.tuple;version="1.0",aQute.lib.markdown
+Require-Capability                       osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))"
+Tool                                     Bnd-2.4.1.201406261752
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/eclipse.html b/org.bndtools.help/docs/commands/eclipse.html new file mode 100644 index 0000000000..2a2db04e9a --- /dev/null +++ b/org.bndtools.help/docs/commands/eclipse.html @@ -0,0 +1,40 @@ + + + + +eclipse + + + +

eclipse

+

Synopsis:

+
   eclipse [options]  ...
+
+ +

Options:

+ +

Available sub-commands

+ +

sync

+

Synchronized the ./cnf/.settings directory to all the projects

+

Synopsis:

+
   sync
+
+ + +

Examples

+
$ bnd eclipse
+Classpath    [/Ws/bnd/biz.aQute.bnd/bin]
+Dependents   []
+Sourcepath   [/Ws/bnd/biz.aQute.bnd/src, /Ws/bnd/biz.aQute.bnd/test]
+Output       /Ws/bnd/biz.aQute.bnd/bin
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/ees.html b/org.bndtools.help/docs/commands/ees.html new file mode 100644 index 0000000000..cea2713f72 --- /dev/null +++ b/org.bndtools.help/docs/commands/ees.html @@ -0,0 +1,14 @@ + + + + +ees + + + +

ees

+

Synopsis:

+
   ees  <<jar-file>...>
+
+ + diff --git a/org.bndtools.help/docs/commands/export.html b/org.bndtools.help/docs/commands/export.html new file mode 100644 index 0000000000..5fc4039d4b --- /dev/null +++ b/org.bndtools.help/docs/commands/export.html @@ -0,0 +1,24 @@ + + + + +export + + + +

export

+

Synopsis:

+
   export [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/exportreport.html b/org.bndtools.help/docs/commands/exportreport.html new file mode 100644 index 0000000000..ac3d482358 --- /dev/null +++ b/org.bndtools.help/docs/commands/exportreport.html @@ -0,0 +1,90 @@ + + + + +exportreport + + + +

exportreport

+

Synopsis:

+
   exportreport  <[list | export | jarexport | readme | jarreadme]> ...
+
+ +

Available sub-commands

+ +

export

+

Export the user defined reports.

+

Synopsis:

+
   export [options]  ...
+
+ +
Options:
+ +

jarexport

+

Export a custom report of a Jar.

+

Synopsis:

+
   jarexport [options]  <jar path> <output path>
+
+ +
Options:
+ +

jarreadme

+

Export a readme file of a Jar (template can be parametrized with system properties starting with 'bnd.reporter.*').

+

Synopsis:

+
   jarreadme [options]  <jar path> <output path>
+
+ +
Options:
+ +

list

+

List the user defined reports.

+

Synopsis:

+
   list [options]  ...
+
+ +
Options:
+ +

readme

+

Export the user defined reports.

+

Synopsis:

+
   readme [options]  ...
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/extract.html b/org.bndtools.help/docs/commands/extract.html new file mode 100644 index 0000000000..31f8bfaa06 --- /dev/null +++ b/org.bndtools.help/docs/commands/extract.html @@ -0,0 +1,27 @@ + + + + +extract + + + +

extract

+

Synopsis:

+
   extract [options]  ...
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd extract -c generated/tmp generated/biz.aQute.bnd.jar
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/find.html b/org.bndtools.help/docs/commands/find.html new file mode 100644 index 0000000000..541fee870f --- /dev/null +++ b/org.bndtools.help/docs/commands/find.html @@ -0,0 +1,38 @@ + + + + +find + + + +

find

+

Synopsis:

+
   find [options]  <[file]...>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd find -e *service* generated/*.jar
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service-4.1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.action-2.0.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.classparser-1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.diff-1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.extension-1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.progress-1.0.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.repository-1.2
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.resolve.hook-1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.bnd.service.url-1.2
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: org.osgi.service.bindex-1.0
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: aQute.service.reporter-1.0.1
+>/Ws/bnd/biz.aQute.bnd/generated/biz.aQute.bnd.jar: org.osgi.service.repository-1.0
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/flatten.html b/org.bndtools.help/docs/commands/flatten.html new file mode 100644 index 0000000000..51d30a667e --- /dev/null +++ b/org.bndtools.help/docs/commands/flatten.html @@ -0,0 +1,14 @@ + + + + +flatten + + + +

flatten

+

Synopsis:

+
   flatten  <input> <output>
+
+ + diff --git a/org.bndtools.help/docs/commands/generate.html b/org.bndtools.help/docs/commands/generate.html new file mode 100644 index 0000000000..765265b323 --- /dev/null +++ b/org.bndtools.help/docs/commands/generate.html @@ -0,0 +1,23 @@ + + + + +generate + + + +

generate

+

Synopsis:

+
   generate [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/generatemanual.html b/org.bndtools.help/docs/commands/generatemanual.html new file mode 100644 index 0000000000..7294ce121c --- /dev/null +++ b/org.bndtools.help/docs/commands/generatemanual.html @@ -0,0 +1,14 @@ + + + + +generatemanual + + + +

generatemanual

+

Synopsis:

+
   generatemanual  <path>
+
+ + diff --git a/org.bndtools.help/docs/commands/gmd.html b/org.bndtools.help/docs/commands/gmd.html new file mode 100644 index 0000000000..2bb398ce96 --- /dev/null +++ b/org.bndtools.help/docs/commands/gmd.html @@ -0,0 +1,14 @@ + + + + +gmd + + + +

gmd

+

Synopsis:

+
   gmd  ...
+
+ + diff --git a/org.bndtools.help/docs/commands/graph.html b/org.bndtools.help/docs/commands/graph.html new file mode 100644 index 0000000000..f50fbf7621 --- /dev/null +++ b/org.bndtools.help/docs/commands/graph.html @@ -0,0 +1,24 @@ + + + + +graph + + + +

graph

+

Synopsis:

+
   graph  ...
+
+ +

Available sub-commands

+ +

roots

+

Find the roots in a set of bundles. A root is a resource that is present but not dependent on by any other resource in the set

+

Synopsis:

+
   roots  <filespec...>
+
+ + diff --git a/org.bndtools.help/docs/commands/grep.html b/org.bndtools.help/docs/commands/grep.html new file mode 100644 index 0000000000..b641595e6b --- /dev/null +++ b/org.bndtools.help/docs/commands/grep.html @@ -0,0 +1,30 @@ + + + + +grep + + + +

grep

+

Synopsis:

+
   grep [options]  <pattern> <file...>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd grep -h "*" "settings" generated/*.jar
+            generated/biz.aQute.bnd.jar :      Private-Package ...ute.lib.[settings]...
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/index.html b/org.bndtools.help/docs/commands/index.html new file mode 100644 index 0000000000..e3e4868b6d --- /dev/null +++ b/org.bndtools.help/docs/commands/index.html @@ -0,0 +1,90 @@ + + + + +Commands Reference + + + +

Commands Reference

+ + + diff --git a/org.bndtools.help/docs/commands/info.html b/org.bndtools.help/docs/commands/info.html new file mode 100644 index 0000000000..403f047873 --- /dev/null +++ b/org.bndtools.help/docs/commands/info.html @@ -0,0 +1,57 @@ + + + + +info + + + +

info

+

Synopsis:

+
   info [options]
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd info -b
+found password 
+Build                                    [/Ws/bnd/biz.aQute.bnd/bin, /Ws/bnd/aQute.libg/generated/aQute.libg.jar, /Ws/bnd/biz.aQute.bndlib/bin, /Ws/bnd/cnf/repo/org.apache.tools.ant/org.apache.tools.ant-1.6.5.jar, /Ws/bnd/cnf/repo/org.osgi.service.component.annotations/org.osgi.service.component.annotations-6.0.0.jar, /Ws/bnd/cnf/repo/osgi.cmpn/osgi.cmpn-4.3.1.jar, /Ws/bnd/cnf/repo/osgi.core/osgi.core-4.3.1.jar, /Ws/bnd/cnf/repo/org.osgi.impl.bundle.bindex/org.osgi.impl.bundle.bindex-2.2.0.jar, /Ws/bnd/cnf/repo/osgi.r5/osgi.r5-1.0.1.jar]
+
+Class path                               []
+
+Depends on                               [aQute.libg, biz.aQute.bndlib, biz.aQute.junit, biz.aQute.launcher]
+
+Run                                      []
+
+Run path                                 [/Ws/bnd/cnf/repo/org.eclipse.osgi/org.eclipse.osgi-3.6.0.jar, /Ws/bnd/cnf/repo/com.springsource.junit/com.springsource.junit-3.8.2.jar]
+
+Source                                   [/Ws/bnd/biz.aQute.bnd/src]
+
+biz.aQute.bnd (master)$ bnd info -bcdrsv
+found password 
+Build                                    [/Ws/bnd/biz.aQute.bnd/bin, /Ws/bnd/aQute.libg/generated/aQute.libg.jar, /Ws/bnd/biz.aQute.bndlib/bin, /Ws/bnd/cnf/repo/org.apache.tools.ant/org.apache.tools.ant-1.6.5.jar, /Ws/bnd/cnf/repo/org.osgi.service.component.annotations/org.osgi.service.component.annotations-6.0.0.jar, /Ws/bnd/cnf/repo/osgi.cmpn/osgi.cmpn-4.3.1.jar, /Ws/bnd/cnf/repo/osgi.core/osgi.core-4.3.1.jar, /Ws/bnd/cnf/repo/org.osgi.impl.bundle.bindex/org.osgi.impl.bundle.bindex-2.2.0.jar, /Ws/bnd/cnf/repo/osgi.r5/osgi.r5-1.0.1.jar]
+
+Class path                               []
+
+Depends on                               [aQute.libg, biz.aQute.bndlib, biz.aQute.junit, biz.aQute.launcher]
+
+Run                                      []
+
+Run path                                 [/Ws/bnd/cnf/repo/org.eclipse.osgi/org.eclipse.osgi-3.6.0.jar, /Ws/bnd/cnf/repo/com.springsource.junit/com.springsource.junit-3.8.2.jar]
+
+Source                                   [/Ws/bnd/biz.aQute.bnd/src]
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/junit.html b/org.bndtools.help/docs/commands/junit.html new file mode 100644 index 0000000000..de6b303ba1 --- /dev/null +++ b/org.bndtools.help/docs/commands/junit.html @@ -0,0 +1,26 @@ + + + + +junit + + + +

junit

+

Synopsis:

+
   junit [options]  <testclass[:method]...>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/macro.html b/org.bndtools.help/docs/commands/macro.html new file mode 100644 index 0000000000..7e8df0cd7c --- /dev/null +++ b/org.bndtools.help/docs/commands/macro.html @@ -0,0 +1,27 @@ + + + + +macro + + + +

macro

+

Synopsis:

+
   macro [options]  <<macro>> <[...]>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd macro p
+biz.aQute.bnd
+biz.aQute.bnd (master)$
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/maven.html b/org.bndtools.help/docs/commands/maven.html new file mode 100644 index 0000000000..ce74c7b8a0 --- /dev/null +++ b/org.bndtools.help/docs/commands/maven.html @@ -0,0 +1,104 @@ + + + + +maven ( 'settings' | 'bundle' + + + +

maven ( 'settings' | 'bundle'

+

Synopsis:

+
   maven  ...
+
+ + +
maven 
+[-temp <dir>]            use as temp directory
+settings                 show maven settings
+bundle                   turn a bundle into a maven bundle
+    [-properties <file>]   provide properties, properties starting with javadoc are options for javadoc, like javadoc-tag=...
+    [-javadoc <file|url>]  where to find the javadoc (zip/dir), otherwise generated
+    [-source <file|url>]   where to find the source (zip/dir), otherwise from OSGI-OPT/src
+    [-scm <url>]           required scm in pom, otherwise from Bundle-SCM
+    [-url <url>]           required project url in pom
+    [-bsn bsn]             overrides bsn
+    [-version <version>]   overrides version
+    [-developer <email>]   developer email
+    [-nodelete]            do not delete temp files
+    [-passphrase <gpgp passphrase>] signer password
+        <file|url>
+
+ +

Options

+

Examples

+
biz.aQute.bnd (master)$ bnd maven settings
+<?xml version="1.0" encoding="UTF-8"?>
+<settings xmlns="http://maven.apache.org/settings/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+    <!-- <localRepository>C:/Users/franklan/.m2/repository</localRepository> -->
+    <pluginGroups>
+        <!-- pluginGroup
+        | Specifies a further group identifier to use for plugin lookup.
+    <pluginGroup>com.your.plugins</pluginGroup>
+    -->
+    </pluginGroups>
+    <servers>
+        <server>
+            <id>deploymentRepo</id>
+            <username>deployment</username>
+            <password>deployment123</password>
+    <!-- <privateKey>c://config//Frank_Langel.p12</privateKey>    -->
+        </server>
+    </servers>
+    <mirrors>
+        <mirror>
+        <id>nexus</id>
+            <mirrorOf>*</mirrorOf>
+            <url>https://svn.myfarm365.de/nexus/content/groups/public</url>
+    <privateKey>/Users/aqute/Desktop/Peter_Kriens.p12</privateKey>
+        </mirror>
+    </mirrors>
+    <profiles>
+        <profile>
+                <id>nexus</id>
+                <!--Enable snapshots for the built in central repo to direct -->
+                <!--all requests to nexus via the mirror -->
+                <repositories>
+                    <repository>
+                        <id>central</id>
+                        <url>http://central</url> <!-- URL wird nicht verwendet, da mirror alles zu nexus weiterleitet -->
+                        <releases>
+                            <enabled>true</enabled>
+                            <updatePolicy>always</updatePolicy>
+                        </releases>
+                        <snapshots>
+                            <enabled>true</enabled>
+                            <updatePolicy>always</updatePolicy>
+                        </snapshots>
+                    </repository>
+                </repositories>
+                <pluginRepositories>
+                    <pluginRepository>
+                        <url>http://central</url> <!-- URL wird nicht verwendet, da mirror alles zu nexus weiterleitet -->
+                        <id>central</id>
+                        <releases>
+                            <enabled>true</enabled>
+                            <updatePolicy>always</updatePolicy>
+                        </releases>
+                        <snapshots>
+                            <enabled>true</enabled>
+                            <updatePolicy>always</updatePolicy>
+                        </snapshots>
+                    </pluginRepository>
+                </pluginRepositories>
+            </profile>
+
+        </profiles>
+        <activeProfiles>
+                <activeProfile>nexus</activeProfile>
+        </activeProfiles>
+</settings>
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/mbr.html b/org.bndtools.help/docs/commands/mbr.html new file mode 100644 index 0000000000..50c7520339 --- /dev/null +++ b/org.bndtools.help/docs/commands/mbr.html @@ -0,0 +1,67 @@ + + + + +mbr + + + +

mbr

+

Synopsis:

+
   mbr [options]  ...
+
+ +

Options:

+ +

Available sub-commands

+ +

check

+

For each archive in the index, show the available higher versions

+

Synopsis:

+
   check [options]  <archive-glob...>
+
+ +
Options:
+ +

repos

+

List the repositories in this workspace

+

Synopsis:

+
   repos
+
+ +

update

+

For each archive in the index, update to a higher version if available in the repository

+

Synopsis:

+
   update [options]  <archive-glob...>
+
+ +
Options:
+ +

verify

+

Verify the repositories, this checks if a GAV is defined in multiple repositories or if there are multiple revisions for the same program

+

Synopsis:

+
   verify [options]  <archive-glob...>
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/nexus.html b/org.bndtools.help/docs/commands/nexus.html new file mode 100644 index 0000000000..f67f6f9be0 --- /dev/null +++ b/org.bndtools.help/docs/commands/nexus.html @@ -0,0 +1,109 @@ + + + + +nexus + + + +

nexus

+

Synopsis:

+
   nexus [options]  <sub-cmd> ...
+
+ +

Options:

+ +

Available sub-commands

+ +

createstaging

+

Create a staging repo

+

Synopsis:

+
   createstaging [options]  <profileId>
+
+ +
Options:
+ +

delete

+

Synopsis:

+
   delete [options]  <repositoryId> <remotepath_or_gav>
+
+ +
Options:
+ +

fetch

+

Synopsis:

+
   fetch [options]  <repositoryId> <remotepath_or_gav>
+
+ +
Options:
+ +

files

+

Synopsis:

+
   files [options]  <files...>
+
+ +
Options:
+ +

index

+

Synopsis:

+
   index [options]  ...
+
+ +
Options:
+ +

sign

+

Artifact signing subcommand.

+

Synopsis:

+
   sign [options]  <path...>
+
+ +
Options:
+ +

upload

+

Synopsis:

+
   upload [options]  <repositoryId> <remotepath_or_gav> <file>
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/package.html b/org.bndtools.help/docs/commands/package.html new file mode 100644 index 0000000000..5524609d75 --- /dev/null +++ b/org.bndtools.help/docs/commands/package.html @@ -0,0 +1,20 @@ + + + + +package + + + +

package

+

Synopsis:

+
   package [options]  <<bnd|bndrun>> <[...]>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/packagetoresource.html b/org.bndtools.help/docs/commands/packagetoresource.html new file mode 100644 index 0000000000..bae59501ba --- /dev/null +++ b/org.bndtools.help/docs/commands/packagetoresource.html @@ -0,0 +1,14 @@ + + + + +packagetoresource + + + +

packagetoresource

+

Synopsis:

+
   packagetoresource  ...
+
+ + diff --git a/org.bndtools.help/docs/commands/plugins.html b/org.bndtools.help/docs/commands/plugins.html new file mode 100644 index 0000000000..1b027e637b --- /dev/null +++ b/org.bndtools.help/docs/commands/plugins.html @@ -0,0 +1,37 @@ + + + + +plugins + + + +

plugins

+

Synopsis:

+
   plugins [options]  ...
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd plugins
+found password 
+000 aQute.bnd.build.Workspace
+001 java.util.concurrent.ThreadPoolExecutor@2685c106[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
+002 java.util.Random@174384ac
+003 aQute.bnd.maven.support.Maven@51bb4422
+004 aQute.lib.settings.Settings@5d763e19
+005 bnd-cache
+006 aQute.bnd.resource.repository.ResourceRepositoryImpl@67528259
+007 aQute.bnd.osgi.Processor
+008 /Ws/bnd/cnf/repo                         r/w=true
+009 /Ws/bnd/dist/bundles                     r/w=true
+010 aQute.bnd.signing.JartoolSigner@2dac2cb7
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/print.html b/org.bndtools.help/docs/commands/print.html new file mode 100644 index 0000000000..a786d52be5 --- /dev/null +++ b/org.bndtools.help/docs/commands/print.html @@ -0,0 +1,113 @@ + + + + +print + + + +

print

+

Synopsis:

+
   print [options]  <jar-file...>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd print generated/biz.aQute.bnd.jar 
+[MANIFEST biz.aQute.bnd]
+Bnd-LastModified                         1404918434023                           
+Bundle-Copyright                         Copyright (c) aQute (2000, 2014). All Rights Reserved.
+Bundle-Description                       This command line utility is the Swiss army knife of OSGi. It provides you with a breadth
+Bundle-DocURL                            http://www.aQute.biz/Code/Bnd           
+Bundle-License                           http://www.opensource.org/licenses/apache2.0.php; description="Apache License, Version 2.0"; link=http://www.apache.org/licenses/LICENSE-2.0.html
+Bundle-ManifestVersion                   2                                       
+Bundle-Name                              biz.aQute.bnd                           
+Bundle-SCM                               git://github.com/bndtools/bnd.git       
+Bundle-SymbolicName                      biz.aQute.bnd                           
+Bundle-Vendor                            aQute SARL http://www.aQute.biz         
+Bundle-Version                           2.4.0.201407091507                      
+Conditional-Package                      aQute.libg.*,aQute.lib.*,aQute.configurable
+Created-By                               1.8.0 (Oracle Corporation)              
+Export-Package                           aQute.bnd.service;version="4.1.0";uses:="aQute.bnd.build,aQute.bnd.osgi,aQute.bnd.version,aQute.service.reporter",aQute.bnd.service.action;version="2.0.0";uses:="aQute.bnd.build",aQute.bnd.service.classparser;version="1.0";uses:="aQute.bnd.osgi",aQute.bnd.service.diff;version="1.0";uses:="aQute.bnd.osgi",aQute.bnd.service.extension;version="1.0";uses:="aQute.bnd.build",aQute.bnd.service.progress;version="1.0.0",aQute.bnd.service.repository;version="1.2";uses:="aQute.bnd.service,aQute.bnd.version,aQute.service.reporter,org.osgi.resource",aQute.bnd.service.resolve.hook;version="1.0";uses:="org.osgi.resource",aQute.bnd.service.url;version="1.2",aQute.bnd.header;version="1.3.0";uses:="aQute.bnd.version,aQute.service.reporter",aQute.bnd.osgi;version="2.3.0";uses:="aQute.bnd.build,aQute.bnd.header,aQute.bnd.service,aQute.bnd.util.dto,aQute.bnd.version,aQute.service.reporter",aQute.bnd.build;version="2.4.0";uses:="aQute.bnd.maven.support,aQute.bnd.osgi,aQute.bnd.service,aQute.bnd.service.action,aQute.bnd.version,aQute.service.reporter",aQute.bnd.version;version="1.1.0",aQute.bnd.maven.support;version="2.0";uses:="aQute.bnd.service,aQute.bnd.version,aQute.service.reporter,javax.xml.xpath,org.w3c.dom",org.osgi.service.bindex;version="1.0",aQute.service.reporter;version="1.0.1",aQute.bnd.osgi.resource;version="1.4.0";uses:="aQute.bnd.header,aQute.bnd.util.dto,org.osgi.resource",org.osgi.service.repository;version="1.0";uses:="org.osgi.resource",org.osgi.resource;version="1.0",aQute.bnd.util.dto;version="1.0"
+Git-Descriptor                           2.4.0.M1-66-gc1ad07d-dirty              
+Git-SHA                                  c1ad07dfeb4704ce590bd93c1405d7bfe8bef131
+Import-Package                           org.apache.tools.ant;resolution:=optional,org.apache.tools.ant.taskdefs;resolution:=optional,org.apache.tools.ant.types;resolution:=optional,aQute.bnd.service;version="[4.1,5)",aQute.bnd.service.action;version="[2.0,2.1)",aQute.bnd.service.diff;version="[1.0,2)",aQute.bnd.service.progress;version="[1.0,2)",aQute.bnd.service.repository;version="[1.2,2)",aQute.bnd.service.url;version="[1.2,2)",aQute.bnd.version;version="[1.1,2)",aQute.service.reporter;version="[1.0,2)",javax.crypto,javax.crypto.spec,javax.naming,javax.net.ssl,javax.script,javax.xml.namespace,javax.xml.parsers,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.stream,javax.xml.xpath,org.osgi.framework;version="[1.6,2)",org.osgi.resource;version="[1.0,2)",org.osgi.service.log;version="[1.3,2)",org.w3c.dom,org.xml.sax,org.xml.sax.helpers,junit.framework;resolution:=optional;version="[3.8,4)"
+Main-Class                               aQute.bnd.main.bnd                      
+Manifest-Version                         1.0                                     
+Private-Package                          aQute.bnd.annotation;version="1.43.2",aQute.bnd.annotation.component;version="1.43.1",aQute.bnd.annotation.headers;version="1.0",aQute.bnd.annotation.licenses;version="1.0",aQute.bnd.annotation.metatype;version="1.44.1",aQute.bnd.ant,aQute.bnd.build.model;version="2.6.0",aQute.bnd.build.model.clauses;version=2,aQute.bnd.build.model.conversions,aQute.bnd.compatibility,aQute.bnd.component,aQute.bnd.component.error;version="1.0.0",aQute.bnd.differ;version="1.1.0",aQute.bnd.enroute.commands,aQute.bnd.filerepo;version="1.0",aQute.bnd.gradle,aQute.bnd.help;version="1.1",aQute.bnd.indexer,aQute.bnd.indexer.analyzers,aQute.bnd.main;version="0.9",aQute.bnd.make,aQute.bnd.make.calltree,aQute.bnd.make.component,aQute.bnd.make.coverage,aQute.bnd.make.metatype,aQute.bnd.maven,aQute.bnd.obr,aQute.bnd.osgi.eclipse,aQute.bnd.properties;version="2.0",aQute.bnd.resource.repository,aQute.bnd.signing,aQute.bnd.testing;version="1.0",aQute.bnd.url;version="1.0",aQute.configurable;version="1.0.0",aQute.lib.deployer,embedded-repo.jar,org.osgi.service.component.annotations;version="1.3",org.osgi.service.coordinator;version="1.0",templates,aQute.lib.base64;version="1.2.0",aQute.lib.collections;version="1.2.0",aQute.lib.converter;version="2.0.1",aQute.lib.filter;version="1.1.0",aQute.lib.getopt;version="1.0.0",aQute.lib.hex;version="1.1.0",aQute.lib.io;version="1.4.0",aQute.lib.json;version="3.0.0",aQute.lib.justif;version="1.1.0",aQute.lib.persistentmap;version="1.1.0",aQute.lib.settings;version="1.2.0",aQute.lib.strings;version="1.1.0",aQute.lib.tag;version="1.1",aQute.libg.classdump;version="1.0",aQute.libg.command;version="3.0.0",aQute.libg.cryptography;version="1.1.0",aQute.libg.filelock;version="1.0.0",aQute.libg.filters;version="1.0",aQute.libg.forker;version="1.0",aQute.libg.generics;version="1.0",aQute.libg.glob;version="1.1.1",aQute.libg.map;version="1.2.0",aQute.libg.qtokens;version="1.0",aQute.libg.reporter;version="1.5",aQute.libg.sed;version="1.1.0",aQute.libg.tuple;version="1.0",aQute.lib.markdown
+Require-Capability                       osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))"
+Tool                                     Bnd-2.4.1.201406261752
+
+[IMPEXP]
+Import-Package
+  aQute.bnd.service                      {version=[4.1,5)}
+  aQute.bnd.service.action               {version=[2.0,2.1)}
+  aQute.bnd.service.diff                 {version=[1.0,2)}
+  aQute.bnd.service.progress             {version=[1.0,2)}
+  aQute.bnd.service.repository           {version=[1.2,2)}
+  aQute.bnd.service.url                  {version=[1.2,2)}
+  aQute.bnd.version                      {version=[1.1,2)}
+  aQute.service.reporter                 {version=[1.0,2)}
+  javax.crypto                           
+  javax.crypto.spec                      
+  javax.naming                           
+  javax.net.ssl                          
+  javax.script                           
+  javax.xml.namespace                    
+  javax.xml.parsers                      
+  javax.xml.transform                    
+  javax.xml.transform.dom                
+  javax.xml.transform.stream             
+  javax.xml.xpath                        
+  junit.framework                        {resolution:=optional, version=[3.8,4)}
+  org.apache.tools.ant                   {resolution:=optional}
+  org.apache.tools.ant.taskdefs          {resolution:=optional}
+  org.apache.tools.ant.types             {resolution:=optional}
+  org.osgi.framework                     {version=[1.6,2)}
+  org.osgi.resource                      {version=[1.0,2)}
+  org.osgi.service.log                   {version=[1.3,2)}
+  org.w3c.dom                            
+  org.xml.sax                            
+  org.xml.sax.helpers                    
+Export-Package
+  aQute.bnd.build                        {version=2.4.0}
+  aQute.bnd.header                       {version=1.3.0}
+  aQute.bnd.maven.support                {version=2.0}
+  aQute.bnd.osgi                         {version=2.3.0}
+  aQute.bnd.osgi.resource                {version=1.4.0}
+  aQute.bnd.service                      {version=4.1.0, imported-as=[4.1,5)}
+  aQute.bnd.service.action               {version=2.0.0, imported-as=[2.0,2.1)}
+  aQute.bnd.service.classparser          {version=1.0}
+  aQute.bnd.service.diff                 {version=1.0, imported-as=[1.0,2)}
+  aQute.bnd.service.extension            {version=1.0}
+  aQute.bnd.service.progress             {version=1.0.0, imported-as=[1.0,2)}
+  aQute.bnd.service.repository           {version=1.2, imported-as=[1.2,2)}
+  aQute.bnd.service.resolve.hook         {version=1.0}
+  aQute.bnd.service.url                  {version=1.2, imported-as=[1.2,2)}
+  aQute.bnd.util.dto                     {version=1.0}
+  aQute.bnd.version                      {version=1.1.0, imported-as=[1.1,2)}
+  aQute.service.reporter                 {version=1.0.1, imported-as=[1.0,2)}
+  org.osgi.resource                      {version=1.0, imported-as=[1.0,2)}
+  org.osgi.service.bindex                {version=1.0}
+  org.osgi.service.repository            {version=1.0}
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/profile.html b/org.bndtools.help/docs/commands/profile.html new file mode 100644 index 0000000000..6460b5e060 --- /dev/null +++ b/org.bndtools.help/docs/commands/profile.html @@ -0,0 +1,33 @@ + + + + +profile + + + +

profile

+

Synopsis:

+
   profile  <create> ...
+
+ +

Available sub-commands

+ +

create

+

Synopsis:

+
   create [options]  ...
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/project.html b/org.bndtools.help/docs/commands/project.html new file mode 100644 index 0000000000..1fe3eaea94 --- /dev/null +++ b/org.bndtools.help/docs/commands/project.html @@ -0,0 +1,30 @@ + + + + +project + + + +

project

+

Synopsis:

+
   project [options]  ...
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd project
+Name         biz.aQute.bnd
+Actions      [build, test, run, clean, release, refresh, deploy]
+Directory    /Ws/bnd/biz.aQute.bnd
+Depends on   [aQute.libg, biz.aQute.bndlib, biz.aQute.junit, biz.aQute.launcher]
+Sub builders [biz.aQute.bnd]
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/properties.html b/org.bndtools.help/docs/commands/properties.html new file mode 100644 index 0000000000..8c67bc9d43 --- /dev/null +++ b/org.bndtools.help/docs/commands/properties.html @@ -0,0 +1,22 @@ + + + + +properties + + + +

properties

+

Synopsis:

+
   properties [options]
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/release.html b/org.bndtools.help/docs/commands/release.html new file mode 100644 index 0000000000..58f9a7f405 --- /dev/null +++ b/org.bndtools.help/docs/commands/release.html @@ -0,0 +1,22 @@ + + + + +release + + + +

release

+

Synopsis:

+
   release [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/remote.html b/org.bndtools.help/docs/commands/remote.html new file mode 100644 index 0000000000..ab916d08d3 --- /dev/null +++ b/org.bndtools.help/docs/commands/remote.html @@ -0,0 +1,102 @@ + + + + +remote + + + +

remote

+

Synopsis:

+
   remote [options]  ...
+
+ +

Options:

+ +

Available sub-commands

+ +

distro

+

Create a distro jar (or xml) from a remote agent

+

Synopsis:

+
   distro [options]  <bsn> <[version]>
+
+ +
Options:
+ +

framework

+

Get the framework info

+

Synopsis:

+
   framework
+
+ +

install

+

Communicate with the remote framework to install or update bundle

+

Synopsis:

+
   install [options]  <filespec...>
+
+ +
Options:
+ +

list

+

Communicate with the remote framework to list the installed bundles

+

Synopsis:

+
   list [options]  ...
+
+ +
Options:
+ +

ping

+

Ping the remote framework

+

Synopsis:

+
   ping
+
+ +

revisions

+

Get the bundle revisions

+

Synopsis:

+
   revisions  <bundleid...>
+
+ +

start

+

Communicate with the remote framework to perform bundle operation

+

Synopsis:

+
   start  <bundleId...>
+
+ +

stop

+

Communicate with the remote framework to perform bundle operation

+

Synopsis:

+
   stop  <bundleId...>
+
+ +

uninstall

+

Communicate with the remote framework to perform bundle operation

+

Synopsis:

+
   uninstall  <bundleId...>
+
+ + diff --git a/org.bndtools.help/docs/commands/remove.html b/org.bndtools.help/docs/commands/remove.html new file mode 100644 index 0000000000..1f6155f499 --- /dev/null +++ b/org.bndtools.help/docs/commands/remove.html @@ -0,0 +1,38 @@ + + + + +remove + + + +

remove

+

Synopsis:

+
   remove  <what> <[name]...>
+
+ +

Available sub-commands

+ +

plugin

+

Remove a plugin from the workspace

+

Synopsis:

+
   plugin  <alias...>
+
+ +

project

+

Remove a project from workspace

+

Synopsis:

+
   project  <name> ...
+
+ +

workspace

+

Remove workspace

+

Synopsis:

+
   workspace  <name> ...
+
+ + diff --git a/org.bndtools.help/docs/commands/repo.html b/org.bndtools.help/docs/commands/repo.html new file mode 100644 index 0000000000..f42d1d742a --- /dev/null +++ b/org.bndtools.help/docs/commands/repo.html @@ -0,0 +1,159 @@ + + + + +repo + + + +

repo

+

Synopsis:

+
   repo [options]  <sub-cmd> ...
+
+ +

Options:

+ +

Available sub-commands

+ +

copy

+

Synopsis:

+
   copy [options]  <source> <dest> <bsn[:version]...>
+
+ +
Options:
+ +

diff

+

Show the diff tree of a single repo or compare 2 repos. A diff tree is a detailed tree of all aspects of a bundle, including its packages, types, methods, fields, and modifiers.

+

Synopsis:

+
   diff [options]  <newer repo> <[older repo]>
+
+ +
Options:
+ +

get

+

Get an artifact from a repository.

+

Synopsis:

+
   get [options]  <bsn> <[range]>
+
+ +
Options:
+ +

index

+

Synopsis:

+
   index [options]  ...
+
+ +
Options:
+ +

list

+

List all artifacts from the current repositories with their versions

+

Synopsis:

+
   list [options]
+
+ +
Options:
+ +

put

+

Put an artifact into the repository after it has been verified.

+

Synopsis:

+
   put [options]  <<jar>...>
+
+ +
Options:
+ +

refresh

+

Refresh refreshable repositories

+

Synopsis:

+
   refresh [options]
+
+ +
Options:
+ +

repos

+

List the current repositories

+

Synopsis:

+
   repos
+
+ +

sync

+

Synopsis:

+
   sync [options]  ...
+
+ +
Options:
+ +

topom

+

Create a POM out of a bnd repository

+

Synopsis:

+
   topom [options]  <repo> <name>
+
+ +
Options:
+ +

versions

+

Displays a sorted set of versions for a given bsn that can be found in the current repositories.

+

Synopsis:

+
   versions  <bsn>
+
+ + diff --git a/org.bndtools.help/docs/commands/resolve.html b/org.bndtools.help/docs/commands/resolve.html new file mode 100644 index 0000000000..3cb5cfb5d7 --- /dev/null +++ b/org.bndtools.help/docs/commands/resolve.html @@ -0,0 +1,99 @@ + + + + +resolve + + + +

resolve

+

Synopsis:

+
   resolve [options]  <<path>...>
+
+ +

Options:

+ +

Available sub-commands

+ +

dot

+

Create a dot file

+

Synopsis:

+
   dot [options]  <bndrun-file>
+
+ +
Options:
+ +

repos

+

Synopsis:

+
   repos [options]  ...
+
+ +
Options:
+ +

resolve

+

Resolve a bndrun file

+

Synopsis:

+
   resolve [options]  <<path>...>
+
+ +
Options:
+ +

validate

+

Validate an OBR file by trying to resolve each entry against itself

+

Synopsis:

+
   validate [options]  <[index-path]>
+
+ +
Options:
+ + + diff --git a/org.bndtools.help/docs/commands/run.html b/org.bndtools.help/docs/commands/run.html new file mode 100644 index 0000000000..a768d316b2 --- /dev/null +++ b/org.bndtools.help/docs/commands/run.html @@ -0,0 +1,20 @@ + + + + +run + + + +

run

+

Synopsis:

+
   run [options]  <[bndrun]>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/runtests.html b/org.bndtools.help/docs/commands/runtests.html new file mode 100644 index 0000000000..7f77f22260 --- /dev/null +++ b/org.bndtools.help/docs/commands/runtests.html @@ -0,0 +1,31 @@ + + + + +runtests + + + +

runtests

+

Synopsis:

+
   runtests [options]  ...
+
+ +

Options:

+ + +

Examples

+
bnd runtests --tests org.osgi.test.cases.tracker.junit.BundleTrackerTests:testSubclass,org.osgi.test.cases.tracker.junit.BundleTrackerTests:testModified org.osgi.test.cases.tracker.bnd
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/schema.html b/org.bndtools.help/docs/commands/schema.html new file mode 100644 index 0000000000..25b7fa1486 --- /dev/null +++ b/org.bndtools.help/docs/commands/schema.html @@ -0,0 +1,20 @@ + + + + +schema + + + +

schema

+

Synopsis:

+
   schema [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/select.html b/org.bndtools.help/docs/commands/select.html new file mode 100644 index 0000000000..9d144f4fec --- /dev/null +++ b/org.bndtools.help/docs/commands/select.html @@ -0,0 +1,32 @@ + + + + +select + + + +

select

+

Synopsis:

+
   select [options]  <<jar-path>> <[...]>
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd select -h name generated/*.jar
+biz.aQute.bnd.jar
+biz.aQute.bnd (master)$ bnd select -h size generated/*.jar
+2604654
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/settings.html b/org.bndtools.help/docs/commands/settings.html new file mode 100644 index 0000000000..a2a6f07d79 --- /dev/null +++ b/org.bndtools.help/docs/commands/settings.html @@ -0,0 +1,26 @@ + + + + +settings + + + +

settings

+

Synopsis:

+
   settings [options]  <<key>[=<value>]...>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/shell.html b/org.bndtools.help/docs/commands/shell.html new file mode 100644 index 0000000000..a70d744349 --- /dev/null +++ b/org.bndtools.help/docs/commands/shell.html @@ -0,0 +1,48 @@ + + + + +shell [options] + + + +

shell [options]

+

Synopsis:

+
   shell [options]  ...
+
+ +

Options:

+ + +

Description

+

The shell function in bnd is primarily intended to exercise macros. Although the macro command made it possible to test a single macro, the awful interaction between the (ba)sh character interpretations for $ and quotes made this quite hard to use in practice. the shell therefore directly talks the macro language as you write it in a bnd.bnd file. Additionally, all bnd commands are also available.

+
$ bnd shell
+Base Project com.example.project
+> p
+com.example.project
+> now
+Fri Sep 28 11:29:02 CEST 2018
+>
+
+ +

When you start the shell bnd will try to find a project. If the -p options is specified it will first look in that directory, otherwise it will look in the current working directory. If no project is found, it will try to find the workspace set by bnd. If no workspace can be found, bnd will use the bnd defaults as properties.

+

Properties

+

A project inherits all properties from the workspace. So when bnd has a project in scope then all macros and properties are available defined in the project's bnd.bnd file, the ./cnf/build.bnd file, and any files in ./cnf/ext/*.bnd. For example, javac.source is a property set by the workspace:

+
> javac.source
+1.8
+>
+
+ +

This raises the question: What properties are there? The shell also supports bnd commands and there is a properties command. However, there are a large number of properties so lets limit it to the properties that start with java:

+
> properties -k java*
+javac.compliance                         1.8
+javac.source                             1.8
+javac.target                             1.8
+>
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/source.html b/org.bndtools.help/docs/commands/source.html new file mode 100644 index 0000000000..c602ad9cea --- /dev/null +++ b/org.bndtools.help/docs/commands/source.html @@ -0,0 +1,19 @@ + + + + +source + + + +

source

+

Synopsis:

+
   source [options]  <<jar path>> <<source path>>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/sync.html b/org.bndtools.help/docs/commands/sync.html new file mode 100644 index 0000000000..2e8e51cc7a --- /dev/null +++ b/org.bndtools.help/docs/commands/sync.html @@ -0,0 +1,19 @@ + + + + +sync + + + +

sync

+

Synopsis:

+
   sync [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/syntax.html b/org.bndtools.help/docs/commands/syntax.html new file mode 100644 index 0000000000..53fe0c3aa3 --- /dev/null +++ b/org.bndtools.help/docs/commands/syntax.html @@ -0,0 +1,31 @@ + + + + +syntax + + + +

syntax

+

Synopsis:

+
   syntax [options]  <header|instruction> ...
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd syntax Bundle-Version
+
+[Bundle-Version]
+    The Bundle-Version header specifies the version of this bundle.
+
+    Pattern                               : [0-9]{1,9}(\.[0-9]{1,9}(\.[0-9]{1,9}(\.[0-9A-Za-z_-]+)?)?)?
+    Example                               : Bundle-Version: 1.23.4.build200903221000
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/test.html b/org.bndtools.help/docs/commands/test.html new file mode 100644 index 0000000000..ec832452de --- /dev/null +++ b/org.bndtools.help/docs/commands/test.html @@ -0,0 +1,26 @@ + + + + +test + + + +

test

+

Synopsis:

+
   test [options]  <testclass[:method]...>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/type.html b/org.bndtools.help/docs/commands/type.html new file mode 100644 index 0000000000..0aace2dc3b --- /dev/null +++ b/org.bndtools.help/docs/commands/type.html @@ -0,0 +1,20 @@ + + + + +type + + + +

type

+

Synopsis:

+
   type [options]  ...
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/verify.html b/org.bndtools.help/docs/commands/verify.html new file mode 100644 index 0000000000..6493a9ede2 --- /dev/null +++ b/org.bndtools.help/docs/commands/verify.html @@ -0,0 +1,14 @@ + + + + +verify + + + +

verify

+

Synopsis:

+
   verify  <<jar path>> <[...]>
+
+ + diff --git a/org.bndtools.help/docs/commands/version.html b/org.bndtools.help/docs/commands/version.html new file mode 100644 index 0000000000..5baf002b2b --- /dev/null +++ b/org.bndtools.help/docs/commands/version.html @@ -0,0 +1,33 @@ + + + + +version + + + +

version

+

Synopsis:

+
   version [options]
+
+ +

Options:

+ + +

Examples

+
biz.aQute.bnd (master)$ bnd version -x
+Version                                  2.4.0.201407091507
+From                                     Wed Jul 09 17:07:14 CEST 2014
+License                                  Apache License, Version 2.0
+Copyright                                Copyright (c) aQute (2000, 2014). All Rights Reserved.
+Git-SHA                                  c1ad07dfeb4704ce590bd93c1405d7bfe8bef131
+Git-Descriptor                           2.4.0.M1-66-gc1ad07d-dirty
+Sources                                  git://github.com/bndtools/bnd.git
+biz.aQute.bnd (master)$
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/view.html b/org.bndtools.help/docs/commands/view.html new file mode 100644 index 0000000000..35ff6aac0e --- /dev/null +++ b/org.bndtools.help/docs/commands/view.html @@ -0,0 +1,19 @@ + + + + +view + + + +

view

+

Synopsis:

+
   view [options]  <<jar-file>> <<resource>> <[...]>
+
+ +

Options:

+ + + diff --git a/org.bndtools.help/docs/commands/wrap.html b/org.bndtools.help/docs/commands/wrap.html new file mode 100644 index 0000000000..83d3215e10 --- /dev/null +++ b/org.bndtools.help/docs/commands/wrap.html @@ -0,0 +1,35 @@ + + + + +wrap + + + +

wrap

+

Synopsis:

+
   wrap [options]  <<jar-file>> <[...]>
+
+ +

Options:

+ + +

The wrap command takes an existing JAR file and guesses the manifest headers that will make this JAR useful for an OSGi Service Platform. If the output file is not overridden, the name of the input file is used with a .bar extension. The default bnd file for the header calculation is:

+
Export-Package: * 
+Import-Package: <packages inside the target jar>
+
+ +

If the target bundle has a manifest, the headers are merged with the properties.

+

The defaults can be overridden with a specific properties file.

+

Examples

+

bnd wrap -classpath osgi.jar *.jar

+



+ + diff --git a/org.bndtools.help/docs/commands/xmlrepodiff.html b/org.bndtools.help/docs/commands/xmlrepodiff.html new file mode 100644 index 0000000000..8c708c60b9 --- /dev/null +++ b/org.bndtools.help/docs/commands/xmlrepodiff.html @@ -0,0 +1,161 @@ + + + + +xmlrepodiff + + + +

xmlrepodiff

+

Synopsis:

+
   xmlrepodiff [options]  <newer XML resource repository> <older XML resource repository>
+
+ +

Options:

+ + +

Examples

+
MAJOR      REPOSITORY <repository>
+ MAJOR      RESOURCE_ID org.apache.felix.configadmin
+  MAJOR      CAPABILITIES <capabilities>
+   MAJOR      CAPABILITY bnd.maven:org.apache.felix:org.apache.felix.configadmin
+    REMOVED    ATTRIBUTE  maven-version:1.9.10
+    ADDED      ATTRIBUTE  maven-version:1.9.22
+   REMOVED    CAPABILITY osgi.content:77B03B938E796C0512D9AD89ACF287CCE09C14A159CA05B6CB74DDA17E7AB3FA
+    REMOVED    ATTRIBUTE  mime:application/vnd.osgi.bundle
+    REMOVED    ATTRIBUTE  size:155630
+    REMOVED    ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/apache/felix/org.apache.felix.configadmin/1.9.10/org.apache.felix.configadmin-1.9.10.jar
+   ADDED      CAPABILITY osgi.content:B349E16D60DA66B6DA70AB3E056677A9D6A0B8953DF84ECD63B10AA5EF3C5865
+    ADDED      ATTRIBUTE  mime:application/vnd.osgi.bundle
+    ADDED      ATTRIBUTE  size:168301
+    ADDED      ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/apache/felix/org.apache.felix.configadmin/1.9.22/org.apache.felix.configadmin-1.9.22.jar
+   MAJOR      CAPABILITY osgi.identity:org.apache.felix.configadmin
+    REMOVED    ATTRIBUTE  version:1.9.10
+    ADDED      ATTRIBUTE  version:1.9.22
+   MAJOR      CAPABILITY osgi.wiring.bundle:org.apache.felix.configadmin
+    REMOVED    ATTRIBUTE  bundle-version:1.9.10
+    ADDED      ATTRIBUTE  bundle-version:1.9.22
+   MAJOR      CAPABILITY osgi.wiring.host:org.apache.felix.configadmin
+    REMOVED    ATTRIBUTE  bundle-version:1.9.10
+    ADDED      ATTRIBUTE  bundle-version:1.9.22
+   MAJOR      CAPABILITY osgi.wiring.package:org.apache.felix.cm
+    REMOVED    ATTRIBUTE  bundle-version:1.9.10
+    ADDED      ATTRIBUTE  bundle-version:1.9.22
+   MAJOR      CAPABILITY osgi.wiring.package:org.apache.felix.cm.file
+    REMOVED    ATTRIBUTE  bundle-version:1.9.10
+    ADDED      ATTRIBUTE  bundle-version:1.9.22
+   MAJOR      CAPABILITY osgi.wiring.package:org.osgi.service.cm
+    REMOVED    ATTRIBUTE  bundle-version:1.9.10
+    ADDED      ATTRIBUTE  bundle-version:1.9.22
+  REMOVED    VERSION    1.9.10
+  ADDED      VERSION    1.9.22
+ MAJOR      RESOURCE_ID org.apache.felix.eventadmin
+  MAJOR      REQUIREMENTS <requirements>
+   MAJOR      REQUIREMENT osgi.ee:JavaSE
+    REMOVED    DIRECTIVE  filter:(&(osgi.ee=JavaSE)(version=1.7))
+    ADDED      DIRECTIVE  filter:(&(osgi.ee=JavaSE)(version=1.8))
+  MAJOR      CAPABILITIES <capabilities>
+   MAJOR      CAPABILITY bnd.maven:org.apache.felix:org.apache.felix.eventadmin
+    REMOVED    ATTRIBUTE  maven-version:1.5.0
+    ADDED      ATTRIBUTE  maven-version:1.6.2
+   ADDED      CAPABILITY osgi.content:445A90F6E31CDE9635C474CEA286273481D2E6EE293B52D8FC42ED8E927B5604
+    ADDED      ATTRIBUTE  mime:application/vnd.osgi.bundle
+    ADDED      ATTRIBUTE  size:83611
+    ADDED      ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/apache/felix/org.apache.felix.eventadmin/1.6.2/org.apache.felix.eventadmin-1.6.2.jar
+   REMOVED    CAPABILITY osgi.content:A433A9020E1EAD82494AA6611E8A644F88733BD0278F349D6BEA3B2E448DDD71
+    REMOVED    ATTRIBUTE  mime:application/vnd.osgi.bundle
+    REMOVED    ATTRIBUTE  size:81529
+    REMOVED    ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/apache/felix/org.apache.felix.eventadmin/1.5.0/org.apache.felix.eventadmin-1.5.0.jar
+   MAJOR      CAPABILITY osgi.identity:org.apache.felix.eventadmin
+    REMOVED    ATTRIBUTE  version:1.5.0
+    ADDED      ATTRIBUTE  version:1.6.2
+   MAJOR      CAPABILITY osgi.wiring.bundle:org.apache.felix.eventadmin
+    REMOVED    ATTRIBUTE  bundle-version:1.5.0
+    ADDED      ATTRIBUTE  bundle-version:1.6.2
+   MAJOR      CAPABILITY osgi.wiring.host:org.apache.felix.eventadmin
+    REMOVED    ATTRIBUTE  bundle-version:1.5.0
+    ADDED      ATTRIBUTE  bundle-version:1.6.2
+   MAJOR      CAPABILITY osgi.wiring.package:org.osgi.service.event
+    REMOVED    ATTRIBUTE  bundle-version:1.5.0
+    ADDED      ATTRIBUTE  bundle-version:1.6.2
+  REMOVED    VERSION    1.5.0
+  ADDED      VERSION    1.6.2
+ REMOVED    RESOURCE_ID org.osgi.util.promise
+  REMOVED    REQUIREMENTS <requirements>
+   REMOVED    REQUIREMENT osgi.ee:JavaSE
+    REMOVED    DIRECTIVE  filter:(&(osgi.ee=JavaSE)(version=1.7))
+   REMOVED    REQUIREMENT osgi.wiring.package:org.osgi.util.function
+    REMOVED    DIRECTIVE  filter:(&(osgi.wiring.package=org.osgi.util.function)(version>=1.1.0)(!(version>=2.0.0)))
+  REMOVED    CAPABILITIES <capabilities>
+   REMOVED    CAPABILITY bnd.maven:org.osgi:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  maven-classifier:
+    REMOVED    ATTRIBUTE  maven-extension:jar
+    REMOVED    ATTRIBUTE  maven-repository:Runtime
+    REMOVED    ATTRIBUTE  maven-version:1.1.1
+   REMOVED    CAPABILITY osgi.content:4F85BECCD281CC1A4E735BD266A0DD3DB11651D3D0DDE001E6BFA55DBDFDEE83
+    REMOVED    ATTRIBUTE  mime:application/vnd.osgi.bundle
+    REMOVED    ATTRIBUTE  size:75587
+    REMOVED    ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/osgi/org.osgi.util.promise/1.1.1/org.osgi.util.promise-1.1.1.jar
+   REMOVED    CAPABILITY osgi.identity:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  copyright:Copyright (c) OSGi Alliance (2000, 2018). All Rights Reserved.
+    REMOVED    ATTRIBUTE  description:OSGi Companion Code for org.osgi.util.promise Version 1.1.1
+    REMOVED    ATTRIBUTE  documentation:https://www.osgi.org/
+    REMOVED    ATTRIBUTE  license:Apache-2.0; link="http://www.apache.org/licenses/LICENSE-2.0"; description="Apache License, Version 2.0"
+    REMOVED    ATTRIBUTE  type:osgi.bundle
+    REMOVED    ATTRIBUTE  version:1.1.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.bundle:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  bundle-version:1.1.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.host:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  bundle-version:1.1.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.package:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  bnd.hashes:-1923478059
+    REMOVED    ATTRIBUTE  bundle-symbolic-name:org.osgi.util.promise
+    REMOVED    ATTRIBUTE  bundle-version:1.1.1.201810101357
+    REMOVED    ATTRIBUTE  version:1.1.1
+    REMOVED    DIRECTIVE  uses:org.osgi.util.function
+  REMOVED    VERSION    1.1.1.201810101357
+ REMOVED    RESOURCE_ID org.osgi.util.pushstream
+  REMOVED    REQUIREMENTS <requirements>
+   REMOVED    REQUIREMENT osgi.ee:JavaSE/compact1
+    REMOVED    DIRECTIVE  filter:(&(osgi.ee=JavaSE/compact1)(version=1.8))
+   REMOVED    REQUIREMENT osgi.wiring.package:org.osgi.util.function
+    REMOVED    DIRECTIVE  filter:(&(osgi.wiring.package=org.osgi.util.function)(version>=1.1.0)(!(version>=2.0.0)))
+   REMOVED    REQUIREMENT osgi.wiring.package:org.osgi.util.promise
+    REMOVED    DIRECTIVE  filter:(&(osgi.wiring.package=org.osgi.util.promise)(version>=1.1.0)(!(version>=2.0.0)))
+  REMOVED    CAPABILITIES <capabilities>
+   REMOVED    CAPABILITY bnd.maven:org.osgi:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  maven-classifier:
+    REMOVED    ATTRIBUTE  maven-extension:jar
+    REMOVED    ATTRIBUTE  maven-repository:Runtime
+    REMOVED    ATTRIBUTE  maven-version:1.0.1
+   REMOVED    CAPABILITY osgi.content:1E0C9D435A107444A4461788E62BDDC94715E444AFDBC54417593ECA4BB50CE2
+    REMOVED    ATTRIBUTE  mime:application/vnd.osgi.bundle
+    REMOVED    ATTRIBUTE  size:132226
+    REMOVED    ATTRIBUTE  url:file:/Users/amit/.m2/repository/org/osgi/org.osgi.util.pushstream/1.0.1/org.osgi.util.pushstream-1.0.1.jar
+   REMOVED    CAPABILITY osgi.identity:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  copyright:Copyright (c) OSGi Alliance (2000, 2018). All Rights Reserved.
+    REMOVED    ATTRIBUTE  description:OSGi Companion Code for org.osgi.util.pushstream Version 1.0.1
+    REMOVED    ATTRIBUTE  documentation:https://www.osgi.org/
+    REMOVED    ATTRIBUTE  license:Apache-2.0; link="http://www.apache.org/licenses/LICENSE-2.0"; description="Apache License, Version 2.0"
+    REMOVED    ATTRIBUTE  type:osgi.bundle
+    REMOVED    ATTRIBUTE  version:1.0.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.bundle:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  bundle-version:1.0.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.host:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  bundle-version:1.0.1.201810101357
+   REMOVED    CAPABILITY osgi.wiring.package:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  bnd.hashes:-1923478059
+    REMOVED    ATTRIBUTE  bundle-symbolic-name:org.osgi.util.pushstream
+    REMOVED    ATTRIBUTE  bundle-version:1.0.1.201810101357
+    REMOVED    ATTRIBUTE  version:1.0.1
+    REMOVED    DIRECTIVE  uses:org.osgi.util.function,org.osgi.util.promise
+  REMOVED    VERSION    1.0.1.201810101357
+
+ +



+ + diff --git a/org.bndtools.help/docs/commands/xref.html b/org.bndtools.help/docs/commands/xref.html new file mode 100644 index 0000000000..516d03644b --- /dev/null +++ b/org.bndtools.help/docs/commands/xref.html @@ -0,0 +1,156 @@ + + + + +xref + + + +

xref

+

Synopsis:

+
   xref [options]  <<jar path>> <[...]>
+
+ +

Options:

+ + +

Examples

+
   biz.aQute.bnd (master)$ bnd xref generated/*.jar
+                              aQute.bnd.annotation > 
+                    aQute.bnd.annotation.component > 
+                      aQute.bnd.annotation.headers > 
+                     aQute.bnd.annotation.licenses > 
+                     aQute.bnd.annotation.metatype > 
+                                     aQute.bnd.ant > aQute.service.reporter
+                                                     org.apache.tools.ant
+                                                     aQute.libg.reporter
+                                                     org.apache.tools.ant.taskdefs
+                                                     aQute.bnd.osgi
+                                                     aQute.bnd.build
+                                                     aQute.libg.qtokens
+                                                     org.apache.tools.ant.types
+                                                     aQute.bnd.osgi.eclipse
+                                                     aQute.bnd.service.progress
+                                                     aQute.bnd.service
+                                                     aQute.bnd.version
+                                                     aQute.bnd.build.model
+                                                     aQute.bnd.build.model.clauses
+                                   aQute.bnd.build > aQute.service.reporter
+                                                     aQute.bnd.osgi
+                                                     aQute.bnd.service
+                                                     aQute.libg.command
+                                                     aQute.libg.sed
+                                                     aQute.bnd.version
+                                                     aQute.bnd.service.action
+                                                     aQute.bnd.header
+                                                     aQute.lib.io
+                                                     aQute.libg.reporter
+                                                     aQute.bnd.osgi.eclipse
+                                                     aQute.bnd.help
+                                                     aQute.lib.strings
+                                                     aQute.libg.generics
+                                                     aQute.bnd.maven.support
+                                                     aQute.libg.glob
+                                                     aQute.lib.converter
+                                                     aQute.lib.collections
+                                                     aQute.bnd.differ
+                                                     aQute.bnd.service.diff
+                                                     aQute.bnd.service.repository
+                                                     aQute.lib.deployer
+                                                     javax.naming
+                                                     aQute.lib.hex
+                                                     aQute.bnd.resource.repository
+                                                     aQute.bnd.url
+                                                     aQute.lib.settings
+                                                     aQute.bnd.service.url
+                                                     aQute.bnd.service.extension
+                             aQute.bnd.build.model > aQute.bnd.build.model.conversions
+                                                     aQute.libg.tuple
+                                                     aQute.bnd.build.model.clauses
+                                                     aQute.bnd.header
+                                                     aQute.bnd.properties
+                                                     aQute.bnd.build
+                                                     aQute.bnd.version
+                                                     aQute.lib.io
+                                                     org.osgi.resource
+                                                     aQute.bnd.osgi
+                     aQute.bnd.build.model.clauses > aQute.bnd.header
+                 aQute.bnd.build.model.conversions > aQute.bnd.header
+                                                     aQute.libg.tuple
+                                                     aQute.bnd.osgi
+                                                     aQute.bnd.build.model
+                                                     aQute.bnd.build.model.clauses
+                                                     org.osgi.resource
+                                                     aQute.bnd.osgi.resource
+                                                     aQute.libg.qtokens
+                           aQute.bnd.compatibility > aQute.bnd.osgi
+                               aQute.bnd.component > aQute.bnd.osgi
+                                                     aQute.service.reporter
+                                                     aQute.lib.collections
+                                                     org.osgi.service.component.annotations
+                                                     aQute.bnd.version
+                                                     aQute.bnd.component.error
+                                                     aQute.lib.tag
+                                                     aQute.bnd.header
+                                                     aQute.bnd.service
+                         aQute.bnd.component.error > 
+                                  aQute.bnd.differ > aQute.bnd.header
+                                                     aQute.bnd.service.diff
+                                                     aQute.bnd.osgi
+                                                     aQute.bnd.version
+                                                     aQute.service.reporter
+                                                     aQute.libg.generics
+                                                     aQute.libg.cryptography
+                                                     aQute.lib.hex
+                                                     aQute.lib.io
+                                                     aQute.lib.collections
+                                                     aQute.bnd.annotation
+                                                     aQute.bnd.service
+                        aQute.bnd.enroute.commands > aQute.lib.getopt
+                                                     aQute.bnd.osgi
+                                                     aQute.service.reporter
+                                                     aQute.bnd.main
+                                                     aQute.bnd.build
+                                                     aQute.lib.io
+                                aQute.bnd.filerepo > aQute.bnd.version
+                                  aQute.bnd.header > aQute.bnd.version
+                                                     aQute.bnd.osgi
+                                                     aQute.service.reporter
+                                                     aQute.libg.generics
+                                                     aQute.libg.qtokens
+                                                     aQute.lib.collections
+                                    aQute.bnd.help > aQute.bnd.osgi
+
+ +

Nested JARs

+

By default, xref only analyzes classes directly contained in the provided JAR files. Many OSGi bundles contain nested JARs that are referenced via the Bundle-ClassPath manifest header. To analyze these nested JARs as well, use the --nested option:

+
   bnd xref --nested mybundle.jar
+
+ +

This will: +1. Parse the Bundle-ClassPath manifest header +2. Extract and analyze any embedded JAR files +3. Analyze directories referenced in the Bundle-ClassPath +4. Include cross-references from all sources in the output

+

For example, given a bundle with the following structure:

+
mybundle.jar
+├── META-INF/MANIFEST.MF (Bundle-ClassPath: .,lib/internal.jar)
+├── com/example/Main.class
+└── lib/internal.jar
+    └── com/example/internal/Helper.class
+
+ +

Without --nested, only com.example.Main would be analyzed. With --nested, both com.example.Main and com.example.internal.Helper classes are included in the cross-reference analysis.

+



+ + diff --git a/org.bndtools.help/docs/heads/.bnd.html b/org.bndtools.help/docs/heads/.bnd.html new file mode 100644 index 0000000000..8224aafa88 --- /dev/null +++ b/org.bndtools.help/docs/heads/.bnd.html @@ -0,0 +1,58 @@ + + + + +.bnd + + + +

.bnd

+ +

Options

+ +

Options

+ + + diff --git a/org.bndtools.help/docs/heads/automatic_module_name.html b/org.bndtools.help/docs/heads/automatic_module_name.html new file mode 100644 index 0000000000..30cbbc81a1 --- /dev/null +++ b/org.bndtools.help/docs/heads/automatic_module_name.html @@ -0,0 +1,19 @@ + + + + +Automatic-Module-Name + + + +

Automatic-Module-Name

+ + + diff --git a/org.bndtools.help/docs/heads/bin.html b/org.bndtools.help/docs/heads/bin.html new file mode 100644 index 0000000000..903f4aa24f --- /dev/null +++ b/org.bndtools.help/docs/heads/bin.html @@ -0,0 +1,19 @@ + + + + +bin + + + +

bin

+ + + diff --git a/org.bndtools.help/docs/heads/bnd.html b/org.bndtools.help/docs/heads/bnd.html new file mode 100644 index 0000000000..6b3dea46ae --- /dev/null +++ b/org.bndtools.help/docs/heads/bnd.html @@ -0,0 +1,56 @@ + + + + +.bnd + + + +

.bnd

+ +

Options

+ + + diff --git a/org.bndtools.help/docs/heads/bnd_addxmltotest.html b/org.bndtools.help/docs/heads/bnd_addxmltotest.html new file mode 100644 index 0000000000..3fae26eadd --- /dev/null +++ b/org.bndtools.help/docs/heads/bnd_addxmltotest.html @@ -0,0 +1,46 @@ + + + + +Bnd-AddXmlToTest RESOURCE ( ',' RESOURCE ) + + + +

Bnd-AddXmlToTest RESOURCE ( ',' RESOURCE )

+ + +

Bnd-AddXmlToTest

+

The Bnd-AddXmlToTest header allows you to include additional XML resources from the tested bundle in the output of a test report. This can be useful for adding custom metadata, configuration, or other relevant XML files to your test results.

+

How It Works

+

When a test is executed, the test framework inspects the Bnd-AddXmlToTest header in the bundle under test. If present, it treats the value as a comma- or space-separated list of resource paths. For each specified resource:

+ +

In addition to including these resources, the test report also contains metadata about the test environment, such as: +- The hostname where the test ran +- The symbolic name and location of the tested bundle +- The timestamp and framework version +- System properties at the time of the test +- Information about all bundles in the framework, including their state, version, and symbolic name

+

This mechanism provides a flexible way to enrich your test reports with bundle-specific XML data, making it easier to diagnose issues or provide additional context for test results.

+

Example

+

To use this feature, add the following header to your bundle’s manifest:

+
Bnd-AddXmlToTest: config.xml, extra-info.xml
+
+ +

When the tests run, both config.xml and extra-info.xml (if present in the bundle) will be included in the test report output.

+
+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bnd_lastmodified.html b/org.bndtools.help/docs/heads/bnd_lastmodified.html new file mode 100644 index 0000000000..9e9c1b57ba --- /dev/null +++ b/org.bndtools.help/docs/heads/bnd_lastmodified.html @@ -0,0 +1,22 @@ + + + + +Bnd-LastModified LONG + + + +

Bnd-LastModified LONG

+ + +

Bnd-LastModified

+

The Bnd-LastModified header is automatically added by bnd to the bundle manifest. It contains a timestamp (in milliseconds since the epoch) that represents the aggregated last modified time of all resources included in the bundle. This value is useful for tracking when the bundle was last built or updated, and can help with cache invalidation or deployment automation.

+

The timestamp is generated at build time and reflects the most recent modification among all files and resources that are part of the bundle. This ensures that any change to the bundle's contents will result in a new, updated timestamp in the manifest.

+

This header is set by bnd and should not be manually modified. It is primarily intended for tooling and automation purposes.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_activationpolicy.html b/org.bndtools.help/docs/heads/bundle_activationpolicy.html new file mode 100644 index 0000000000..80a3793b45 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_activationpolicy.html @@ -0,0 +1,34 @@ + + + + +Bundle-ActivationPolicy ::= policy ( ';' directive )* + + + +

Bundle-ActivationPolicy ::= policy ( ';' directive )*

+ + +

Bundle-ActivationPolicy

+

The Bundle-ActivationPolicy header specifies how the OSGi framework should activate the bundle once it has been started. The most common value for this header is lazy, which indicates that the bundle should be started in lazy activation mode. In this mode, the bundle's activator is not called until the first class from the bundle is loaded.

+

This header can also include additional directives, such as include and exclude, to further control activation behavior. The header is typically used as follows:

+
Bundle-ActivationPolicy: lazy
+
+ +

For more details, see the OSGi Specification.

+

If the header is set incorrectly (for example, with no argument or with too many arguments), bnd will issue a warning. The value should be set to lazy for standard lazy activation.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_activator.html b/org.bndtools.help/docs/heads/bundle_activator.html new file mode 100644 index 0000000000..4b467b7f05 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_activator.html @@ -0,0 +1,32 @@ + + + + +Bundle-Activator CLASS + + + +

Bundle-Activator CLASS

+ + +

Bundle-Activator

+

The Bundle-Activator header specifies the fully qualified name of the class that implements the org.osgi.framework.BundleActivator interface. This class is used by the OSGi framework to start and stop the bundle. When the bundle is started, the framework creates an instance of this class and calls its start method. When the bundle is stopped, the stop method is called.

+

The activator class must be included in the bundle and accessible on the bundle classpath. If the class is missing, not accessible, or not properly implemented, bnd will issue a warning or error during analysis.

+

Example:

+
Bundle-Activator: com.example.MyActivator
+
+ +

If the activator is not specified, the bundle will not have custom start/stop behavior.

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_blueprint.html b/org.bndtools.help/docs/heads/bundle_blueprint.html new file mode 100644 index 0000000000..2a13ba9eed --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_blueprint.html @@ -0,0 +1,30 @@ + + + + +Bundle-Blueprint RESOURE (',' RESOURCE ) + + + +

Bundle-Blueprint RESOURE (',' RESOURCE )

+ + +

Bundle-Blueprint

+

The Bundle-Blueprint header is used to specify the location of Blueprint XML files within the bundle. These XML files define Blueprint dependency injection containers for OSGi. The header can list one or more resource paths, separated by commas. bnd will process these files and include them in the bundle as needed.

+

Example:

+
Bundle-Blueprint: OSGI-INF/blueprint/context.xml, META-INF/spring/context.xml
+
+ +

This header is typically used in bundles that provide OSGi Blueprint services or use Spring DM. The specified XML files must be present in the bundle at the given locations.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_category.html b/org.bndtools.help/docs/heads/bundle_category.html new file mode 100644 index 0000000000..7fbcc78f5f --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_category.html @@ -0,0 +1,33 @@ + + + + +Bundle-Category STRING (',' STRING ) + + + +

Bundle-Category STRING (',' STRING )

+ + +

Bundle-Category

+

The Bundle-Category header allows you to specify one or more categories for your bundle. These categories can be used by tools and repositories to group and filter bundles. The header can be set using the BundleCategory annotation or directly in the manifest.

+

Example:

+
Bundle-Category: utility, database
+
+ +

Categories are free-form strings and can be customized as needed. This header is optional and is mainly used for documentation and discovery purposes.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_classpath.html b/org.bndtools.help/docs/heads/bundle_classpath.html new file mode 100644 index 0000000000..049c365c2c --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_classpath.html @@ -0,0 +1,31 @@ + + + + +Bundle-ClassPath ::= entry ( ',' entry )* + + + +

Bundle-ClassPath ::= entry ( ',' entry )*

+ + +

Bundle-ClassPath

+

The Bundle-ClassPath header defines the internal class path for the bundle. It is a comma-separated list of JAR file paths or directories (inside the bundle) that contain classes and resources. The special entry . refers to the root of the bundle JAR and is the default if the header is not specified.

+

All files or directories listed in the Bundle-ClassPath must be present in the bundle. You can use the Include-Resource instruction to include additional JARs or directories. In most cases, it is recommended to avoid using Bundle-ClassPath unless necessary, as it can complicate class loading. Instead, use the @ option in Include-Resource to unroll JARs into the main bundle.

+

Example:

+
Bundle-ClassPath: ., lib/extra.jar
+
+ +

This header is important for advanced scenarios where you need to include additional classpath entries inside your bundle.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_contactaddress.html b/org.bndtools.help/docs/heads/bundle_contactaddress.html new file mode 100644 index 0000000000..30d25d2ba9 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_contactaddress.html @@ -0,0 +1,19 @@ + + + + +Bundle-ContactAddress + + + +

Bundle-ContactAddress

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_contributors.html b/org.bndtools.help/docs/heads/bundle_contributors.html new file mode 100644 index 0000000000..ca6da20b43 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_contributors.html @@ -0,0 +1,172 @@ + + + + +Bundle-Contributors ... + + + +

Bundle-Contributors ...

+ +

Options

+ + +

Bundle-Contributors

+

The Bundle-Contributors header lists contributors to the bundle, as defined in the Maven POM or via annotations. This header is not standardized by OSGi but is used for documentation and tracking purposes.

+

Example:

+
Bundle-Contributors: John Doe;roles='developer';organization='Example Corp.'
+
+ +

This header is optional and is mainly used for informational purposes.

+
/*
+ * Bundle-Contributors header
+ */
+
+private void doBundleContributors(BundleContributors annotation) throws IOException {
+    StringBuilder sb = new StringBuilder(annotation.value());
+    if (annotation.name() != null) {
+        sb.append(";name='");
+        escape(sb, annotation.name());
+        sb.append("'");
+    }
+    if (annotation.roles() != null) {
+        sb.append(";roles='");
+        escape(sb,annotation.roles());
+        sb.append("'");
+    }
+    if (annotation.organizationUrl() != null) {
+        sb.append(";organizationUrl='");
+        escape(sb,annotation.organizationUrl());
+        sb.append("'");
+    }
+    if (annotation.organization() != null) {
+        sb.append(";organization='");
+        escape(sb,annotation.organization());
+        sb.append("'");
+    }
+    if (annotation.timezone() != 0)
+        sb.append(";timezone=").append(annotation.timezone());
+    add(Constants.BUNDLE_CONTRIBUTORS, sb.toString());
+}
+
+
+        /**
+     * Maven defines contributors and developers in the POM. This annotation will
+     * generate a (not standardized by OSGi) Bundle-Contributors header.
+     * <p>
+     * This annotation can be used directly on a type or it can 'color' an
+     * annotation. This coloring allows custom annotations that define a specific
+     * contributor. For example:
+     * 
+     * <pre>
+     *   {@code @}BundleContributor("Peter.Kriens@aQute.biz")
+     *   {@code @}interface pkriens {}
+     *   
+     *   {@code @}pkriens
+     *   public class MyFoo {
+     *     ...
+     *   }
+     * </pre>
+     * 
+     * Duplicates are removed before the header is generated and the coloring does
+     * not create an entry in the header, only an annotation on an actual type is
+     * counted. This makes it possible to make a library of contributors without
+     * then adding them all to the header.
+     * <p>
+     * See <a href=https://maven.apache.org/pom.html#Developers>Maven POM reference</a>
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Target({
+            ElementType.ANNOTATION_TYPE, ElementType.TYPE
+    })
+    public @interface BundleContributors {
+
+        /**
+         * The email address of the developer.
+         */
+        String value();
+
+        /**
+         * The display name of the developer. If not specified, the {@link #value()}
+         * is used.
+         */
+        String name() default "";
+
+        /**
+         * The roles this contributor plays in the development.
+         */
+        String[] roles() default {};
+
+        /**
+         * The name of the organization where the contributor works for.
+         */
+        String organization() default "";
+
+        /**
+         * The url of the organization where the contributor works for.
+         */
+        String organizationUrl() default "";
+
+        /**
+         * Time offset in hours from UTC without Daylight savings
+         */
+        int timezone() default 0;
+    }
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_copyright.html b/org.bndtools.help/docs/heads/bundle_copyright.html new file mode 100644 index 0000000000..641aca4ddb --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_copyright.html @@ -0,0 +1,30 @@ + + + + +Bundle-Copyright STRING + + + +

Bundle-Copyright STRING

+ + +

Bundle-Copyright

+

The Bundle-Copyright header specifies the copyright statement for the bundle. This information can be set using the BundleCopyright annotation or directly in the manifest. It is intended for informational purposes and does not affect bundle behavior.

+

Example:

+
Bundle-Copyright: Copyright (c) 2025 Example Corp.
+
+ +

This header is optional and is typically used to document the legal ownership of the bundle's contents.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_description.html b/org.bndtools.help/docs/heads/bundle_description.html new file mode 100644 index 0000000000..449605390b --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_description.html @@ -0,0 +1,30 @@ + + + + +Bundle-Description STRING + + + +

Bundle-Description STRING

+ + +

Bundle-Description

+

The Bundle-Description header provides a short, human-readable description of the bundle. This description is intended to help users and tools understand the purpose or functionality of the bundle at a glance.

+

Example:

+
Bundle-Description: Provides OSGi-based logging services for applications.
+
+ +

This header is optional but recommended for clarity and documentation purposes.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_developers.html b/org.bndtools.help/docs/heads/bundle_developers.html new file mode 100644 index 0000000000..1aca30686c --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_developers.html @@ -0,0 +1,128 @@ + + + + +Bundle-Developers ... + + + +

Bundle-Developers ...

+ + +

Bundle-Developers

+

The Bundle-Developers header lists developers of the bundle, as defined in the Maven POM or via annotations. This header is not standardized by OSGi but is used for documentation and tracking purposes.

+

Example:

+
Bundle-Developers: Jane Smith;roles='lead';organization='Example Corp.'
+
+ +

This header is optional and is mainly used for informational purposes.

+
/*
+ * Bundle-Developers header
+ */
+private void doBundleDevelopers(BundleDevelopers annotation) throws IOException {
+    StringBuilder sb = new StringBuilder(annotation.value());
+    if (annotation.name() != null) {
+        sb.append(";name='");
+        escape(sb, annotation.name());
+        sb.append("'");
+    }
+    if (annotation.roles() != null) {
+        sb.append(";roles='");
+        escape(sb,annotation.roles());
+        sb.append("'");
+    }
+    if (annotation.organizationUrl() != null) {
+        sb.append(";organizationUrl='");
+        escape(sb,annotation.organizationUrl());
+        sb.append("'");
+    }
+    if (annotation.organization() != null) {
+        sb.append(";organization='");
+        escape(sb,annotation.organization());
+        sb.append("'");
+    }
+    if (annotation.timezone() != 0)
+        sb.append(";timezone=").append(annotation.timezone());
+
+    add(Constants.BUNDLE_DEVELOPERS, sb.toString());
+}
+
+
+        /**
+     * Maven defines developers and developers in the POM. This annotation will
+     * generate a (not standardized by OSGi) Bundle-Developers header.
+     * <p>
+     * A deve
+     * <p>
+     * This annotation can be used directly on a type or it can 'color' an
+     * annotation. This coloring allows custom annotations that define a specific
+     * developer. For example:
+     * 
+     * <pre>
+     *   @BundleContributor("Peter.Kriens@aQute.biz")
+     *   @interface pkriens {}
+     *   
+     *   @pkriens
+     *   public class MyFoo {
+     *     ...
+     *   }
+     * </pre>
+     * 
+     * Duplicates are removed before the header is generated and the coloring does
+     * not create an entry in the header, only an annotation on an actual type is
+     * counted. This makes it possible to make a library of developers without
+     * then adding them all to the header.
+     * <p>
+     * {@see https://maven.apache.org/pom.html#Developers}
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Target({
+            ElementType.ANNOTATION_TYPE, ElementType.TYPE
+    })
+    public @interface BundleDevelopers {
+
+        /**
+         * The email address of the developer.
+         */
+        String value();
+
+        /**
+         * The display name of the developer. If not specified, the {@link #value()}
+         * is used.
+         */
+        String name() default "";
+
+        /**
+         * The roles this developer plays in the development.
+         */
+        String[] roles() default {};
+
+        /**
+         * The name of the organization where the developer works for.
+         */
+        String organization() default "";
+
+        /**
+         * The url of the organization where the developer works for.
+         */
+        String organizationUrl() default "";
+
+        /**
+         * Time offset in hours from UTC without Daylight savings
+         */
+        int timezone() default 0;
+    }
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_docurl.html b/org.bndtools.help/docs/heads/bundle_docurl.html new file mode 100644 index 0000000000..b3bd60cc43 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_docurl.html @@ -0,0 +1,38 @@ + + + + +Bundle-DocURL STRING + + + +

Bundle-DocURL STRING

+ + +

Bundle-DocURL

+

The Bundle-DocURL header specifies a URL that points to documentation for the bundle. This can be a website, wiki page, or any other resource that provides more information about the bundle's usage, features, or configuration.

+

Example:

+
Bundle-DocURL: https://docs.example.com/my-bundle
+
+ +

Providing this header is optional but highly recommended for discoverability and support.

+
/*
+ * Bundle-DocURL header
+ */
+private void doBundleDocURL(BundleDocURL annotation) {
+    add(Constants.BUNDLE_DOCURL, annotation.value());
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_icon.html b/org.bndtools.help/docs/heads/bundle_icon.html new file mode 100644 index 0000000000..de887d73a6 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_icon.html @@ -0,0 +1,35 @@ + + + + +Bundle-Icon + + + +

Bundle-Icon

+ +

Options

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_license.html b/org.bndtools.help/docs/heads/bundle_license.html new file mode 100644 index 0000000000..07a7e6b02a --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_license.html @@ -0,0 +1,65 @@ + + + + +Bundle-License ::= '<<[EXTERNAL]>>' | ( license ( ',' license ) * ) + + + +

Bundle-License ::= '<<[EXTERNAL]>>' | ( license ( ',' license ) * )

+ +

Options

+ + +

Bundle-License

+

The Bundle-License header provides machine-readable license information for the bundle. It can list one or more licenses, separated by commas, and may include additional attributes such as a description or a link to the license text.

+

Example:

+
Bundle-License: Apache-2.0;description='Apache License, Version 2.0';link='https://www.apache.org/licenses/LICENSE-2.0'
+
+ +

This header is optional but recommended for clarity and compliance. It helps users and tools understand the licensing terms of the bundle.

+
    /*
+ * Bundle-License header
+ */
+private void doLicense(BundleLicense annotation) {
+    StringBuilder sb = new StringBuilder(annotation.name());
+    if (!annotation.description().equals(""))
+        sb.append(";description='").append(annotation.description().replaceAll("'", "\\'")).append("'");
+    if (!annotation.link().equals(""))
+        sb.append(";link='").append(annotation.link().replaceAll("'", "\\'")).append("'");
+    add(Constants.BUNDLE_LICENSE, sb.toString());
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_localization.html b/org.bndtools.help/docs/heads/bundle_localization.html new file mode 100644 index 0000000000..bfe80429f6 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_localization.html @@ -0,0 +1,22 @@ + + + + +Bundle-Localization + + + +

Bundle-Localization

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_manifestversion.html b/org.bndtools.help/docs/heads/bundle_manifestversion.html new file mode 100644 index 0000000000..29049d9f3c --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_manifestversion.html @@ -0,0 +1,33 @@ + + + + +Bundle-ManifestVersion ::= 2 + + + +

Bundle-ManifestVersion ::= 2

+ + +

Bundle-ManifestVersion

+

The Bundle-ManifestVersion header is always set to 2 for OSGi R4 and later bundles. This value is required by the OSGi specification and cannot be changed or omitted. It ensures compatibility with the OSGi framework.

+

Example:

+
Bundle-ManifestVersion: 2
+
+ +

This header is automatically set by bnd and should not be modified manually.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_name.html b/org.bndtools.help/docs/heads/bundle_name.html new file mode 100644 index 0000000000..b8d10035a1 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_name.html @@ -0,0 +1,40 @@ + + + + +Bundle-Name STRING + + + +

Bundle-Name STRING

+ + +

Bundle-Name

+

The Bundle-Name header defines a short, human-readable name for the bundle. This name is intended for display in user interfaces and tools. If the Bundle-Name is not set, it will default to the value of the Bundle-SymbolicName header.

+

Example:

+
Bundle-Name: My Example Bundle
+
+ +

This header is optional but recommended for clarity and usability.

+

If the Bundle-Name is not set, it will default to the Bundle-SymbolicName.

+
        //
+        // Use the same name for the bundle name as BSN when
+        // the bundle name is not set
+        //
+        if (main.getValue(BUNDLE_NAME) == null) {
+            main.putValue(BUNDLE_NAME, bsn);
+        }
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_nativecode.html b/org.bndtools.help/docs/heads/bundle_nativecode.html new file mode 100644 index 0000000000..e7d49c77ab --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_nativecode.html @@ -0,0 +1,83 @@ + + + + +Bundle-NativeCode ::= nativecode ( ',' nativecode )* ( ',' optional ) ? + + + +

Bundle-NativeCode ::= nativecode ( ',' nativecode )* ( ',' optional ) ?

+ +

Options

+ + +

Bundle-NativeCode

+

The Bundle-NativeCode header specifies native code libraries that are included in the bundle and may be loaded by the OSGi framework. This header lists one or more native code clauses, each describing the path to a native library and optional attributes such as operating system, processor, language, or version constraints.

+

Example:

+
Bundle-NativeCode: lib/linux-x86/libfoo.so;osname=Linux;processor=x86, lib/win32-x86/foo.dll;osname=Windows;processor=x86
+
+ +

A wildcard (*) can be used as the last entry to indicate that the bundle can run without native code if no match is found. If a required native library is missing or not found in the JAR, bnd will issue an error.

+

This header is used for bundles that need to provide platform-specific native libraries alongside Java code.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_requiredexecutionenvironment.html b/org.bndtools.help/docs/heads/bundle_requiredexecutionenvironment.html new file mode 100644 index 0000000000..70c5397e4a --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_requiredexecutionenvironment.html @@ -0,0 +1,61 @@ + + + + +Bundle-RequiredExecutionEnvironment ::= ee-name ( ',' ee-name )* + + + +

Bundle-RequiredExecutionEnvironment ::= ee-name ( ',' ee-name )*

+ + +

Bundle-RequiredExecutionEnvironment

+

The Bundle-RequiredExecutionEnvironment header lists the execution environments required by the bundle, separated by commas. These environments must be present on the OSGi framework for the bundle to resolve. This header is deprecated in recent OSGi specifications.

+

Example:

+
Bundle-RequiredExecutionEnvironment: JavaSE-1.8, OSGi/Minimum-1.2
+
+ +

This header is optional and mainly used for legacy compatibility.

+
    verifyListHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, EENAME, false);
+
+    final static Pattern    EENAME  = Pattern.compile("CDC-1\\.0/Foundation-1\\.0" + "|CDC-1\\.1/Foundation-1\\.1"
+                                        + "|OSGi/Minimum-1\\.[1-9]" + "|JRE-1\\.1" + "|J2SE-1\\.2" + "|J2SE-1\\.3"
+                                        + "|J2SE-1\\.4" + "|J2SE-1\\.5" + "|JavaSE-1\\.6" + "|JavaSE-1\\.7"
+                                        + "|JavaSE-1\\.8" + "|PersonalJava-1\\.1" + "|PersonalJava-1\\.2"
+                                        + "|CDC-1\\.0/PersonalBasis-1\\.0" + "|CDC-1\\.0/PersonalJava-1\\.0");
+    final static EE[]           ees                             = {
+        new EE("CDC-1.0/Foundation-1.0", V1_3, V1_1),
+        new EE("CDC-1.1/Foundation-1.1", V1_3, V1_2),
+        new EE("OSGi/Minimum-1.0", V1_3, V1_1),
+        new EE("OSGi/Minimum-1.1", V1_3, V1_2),
+        new EE("JRE-1.1", V1_1, V1_1), //
+        new EE("J2SE-1.2", V1_2, V1_1), //
+        new EE("J2SE-1.3", V1_3, V1_1), //
+        new EE("J2SE-1.4", V1_3, V1_2), //
+        new EE("J2SE-1.5", V1_5, V1_5), //
+        new EE("JavaSE-1.6", V1_6, V1_6), //
+        new EE("PersonalJava-1.1", V1_1, V1_1), //
+        new EE("JavaSE-1.7", V1_7, V1_7), //
+        new EE("JavaSE-1.8", V1_8, V1_8), //
+        new EE("PersonalJava-1.1", V1_1, V1_1), //
+        new EE("PersonalJava-1.2", V1_1, V1_1), new EE("CDC-1.0/PersonalBasis-1.0", V1_3, V1_1),
+        new EE("CDC-1.0/PersonalJava-1.0", V1_3, V1_1), new EE("CDC-1.1/PersonalBasis-1.1", V1_3, V1_2),
+        new EE("CDC-1.1/PersonalJava-1.1", V1_3, V1_2)
+                                                            };
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_scm.html b/org.bndtools.help/docs/heads/bundle_scm.html new file mode 100644 index 0000000000..035f5d3913 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_scm.html @@ -0,0 +1,19 @@ + + + + +Bundle-SCM + + + +

Bundle-SCM

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_symbolicname.html b/org.bndtools.help/docs/heads/bundle_symbolicname.html new file mode 100644 index 0000000000..e1e779def7 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_symbolicname.html @@ -0,0 +1,109 @@ + + + + +Bundle-SymbolicName ::= symbolic-name ( ';' parameter ) * + + + +

Bundle-SymbolicName ::= symbolic-name ( ';' parameter ) *

+ +

Options

+ + +

Bundle-SymbolicName

+

The Bundle-SymbolicName header specifies a unique, non-localizable name for the bundle. This name, together with the version, must uniquely identify a bundle, even if it is installed multiple times in a framework. The symbolic name should follow the reverse domain name convention (e.g., com.example.mybundle).

+

If not set, bnd will use the name of the main bnd file or, if the file is called bnd.bnd, the name of its directory. The ${project} variable can also be used to set this value.

+

Example:

+
Bundle-SymbolicName: com.example.mybundle
+
+ +

This header is required for all OSGi bundles.

+

The Bundle-SymbolicName header can be set by the user. The default is the name of the main bnd file, or if the main bnd file is called bnd.bnd, it will be the name of the directory of the bnd file. An interesting variable is ${project} that will be set to this default name.

+
        private void verifySymbolicName() {
+    Parameters bsn = parseHeader(main.get(Analyzer.BUNDLE_SYMBOLICNAME));
+    if (!bsn.isEmpty()) {
+        if (bsn.size() > 1)
+            error("More than one BSN specified " + bsn);
+
+        String name = bsn.keySet().iterator().next();
+        if (!isBsn(name)) {
+            error("Symbolic Name has invalid format: " + name);
+        }
+    }
+}
+
+        /**
+ * @param name
+ * @return
+ */
+public static boolean isBsn(String name) {
+    return SYMBOLICNAME.matcher(name).matches();
+}
+
+
+public final static String  SYMBOLICNAME_STRING             = "[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*";
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/bundle_updatelocation.html b/org.bndtools.help/docs/heads/bundle_updatelocation.html new file mode 100644 index 0000000000..bda120909f --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_updatelocation.html @@ -0,0 +1,19 @@ + + + + +Bundle-UpdateLocation + + + +

Bundle-UpdateLocation

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_vendor.html b/org.bndtools.help/docs/heads/bundle_vendor.html new file mode 100644 index 0000000000..c3303cf5e3 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_vendor.html @@ -0,0 +1,19 @@ + + + + +Bundle-Vendor + + + +

Bundle-Vendor

+ + + diff --git a/org.bndtools.help/docs/heads/bundle_version.html b/org.bndtools.help/docs/heads/bundle_version.html new file mode 100644 index 0000000000..a6a7011014 --- /dev/null +++ b/org.bndtools.help/docs/heads/bundle_version.html @@ -0,0 +1,61 @@ + + + + +Bundle-Version ::= version + + + +

Bundle-Version ::= version

+ + +

Bundle-Version

+

The Bundle-Version header specifies the version of the bundle. If this header is not provided, a default version of 0 will be set. The version must follow the OSGi versioning scheme: major.minor.micro.qualifier.

+

Example:

+
Bundle-Version: 1.2.3
+
+ +

This header is important for managing updates and dependencies between bundles.

+

The version of the bundle. If no such header is provided, a version of 0 will be set.

+
    verifyHeader(Constants.BUNDLE_VERSION, VERSION, true);
+        public final static Pattern VERSION                         = Pattern.compile(VERSION_STRING);
+        public final static String  VERSION_STRING                  = "[0-9]{1,9}(\\.[0-9]{1,9}(\\.[0-9]{1,9}(\\.[0-9A-Za-z_-]+)?)?)?";
+
+
+        /**
+ * Intercept the call to analyze and cleanup versions after we have analyzed
+ * the setup. We do not want to cleanup if we are going to verify.
+ */
+
+@Override
+public void analyze() throws Exception {
+    super.analyze();
+    cleanupVersion(getImports(), null);
+    cleanupVersion(getExports(), getVersion());
+    String version = getProperty(BUNDLE_VERSION);
+    if (version != null) {
+        version = cleanupVersion(version);
+        if (version.endsWith(".SNAPSHOT")) {
+            version = version.replaceAll("SNAPSHOT$", getProperty(SNAPSHOT, "SNAPSHOT"));
+        }
+        setProperty(BUNDLE_VERSION, version);
+    }
+}
+
+
+                if (main.getValue(BUNDLE_VERSION) == null)
+            main.putValue(BUNDLE_VERSION, "0");
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/conditional_package.html b/org.bndtools.help/docs/heads/conditional_package.html new file mode 100644 index 0000000000..aa3b2f802f --- /dev/null +++ b/org.bndtools.help/docs/heads/conditional_package.html @@ -0,0 +1,72 @@ + + + + +Conditional-Package PACKAGE-SPEC ( ',' PACKAGE-SPEC ) * + + + +

Conditional-Package PACKAGE-SPEC ( ',' PACKAGE-SPEC ) *

+ + +

Conditional-Package

+

This instruction is equal to using -conditionalpackage except for the fact that the header in addition will be copied into the generated bundle manifest (like all headers beginning with a capital letter).

+

The Conditional-Package header allows you to specify package patterns that, when referred to by your code, will be included in the bundle if they match the given specifications. This is useful for conditionally including packages from the classpath based on actual usage.

+

Example:

+
Conditional-Package: com.example.optional.*
+
+ +

bnd will recursively add matching packages until no more additions are found. This header is useful for advanced packaging scenarios.

+
/**
+ * Answer extra packages. In this case we implement conditional package. Any
+ */
+@Override
+protected Jar getExtra() throws Exception {
+    Parameters conditionals = getParameters(CONDITIONAL_PACKAGE);
+    conditionals.putAll(getParameters(CONDITIONALPACKAGE));
+    if (conditionals.isEmpty())
+        return null;
+    trace("do Conditional Package %s", conditionals);
+    Instructions instructions = new Instructions(conditionals);
+
+    Collection<PackageRef> referred = instructions.select(getReferred().keySet(), false);
+    referred.removeAll(getContained().keySet());
+
+    Jar jar = new Jar("conditional-import");
+    addClose(jar);
+    for (PackageRef pref : referred) {
+        for (Jar cpe : getClasspath()) {
+            Map<String,Resource> map = cpe.getDirectories().get(pref.getPath());
+            if (map != null) {
+                copy(jar, cpe, pref.getPath(), false);
+                // Now use copy so that bnd.info is processed, next line
+                // should be
+                // removed in the future TODO
+                // jar.addDirectory(map, false);
+                break;
+            }
+        }
+    }
+    if (jar.getDirectories().size() == 0) {
+        trace("extra dirs %s", jar.getDirectories());
+        return null;
+    }
+    return jar;
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/created_by.html b/org.bndtools.help/docs/heads/created_by.html new file mode 100644 index 0000000000..b5476ced2f --- /dev/null +++ b/org.bndtools.help/docs/heads/created_by.html @@ -0,0 +1,27 @@ + + + + +Created-By STRING + + + +

Created-By STRING

+ + +

Created-By

+

The Created-By header in the bundle manifest records the Java version and vendor used to build the bundle. This information is automatically added by bnd during the build process. It can be useful for tracking the build environment, diagnosing compatibility issues, or auditing builds.

+

The value typically looks like:

+
Created-By: 17.0.8 (Eclipse Adoptium)
+
+ +

This header is set by bnd and should not be manually changed.

+

Prose Explanation

+

The Created-By header is important for understanding the context in which a Java bundle was created. It provides insight into the Java Development Kit (JDK) version and the vendor's implementation details. This can be critical when you are trying to debug issues, ensure compatibility with other Java components, or verify that the bundle was built using a trusted JDK vendor.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/dynamicimport_package.html b/org.bndtools.help/docs/heads/dynamicimport_package.html new file mode 100644 index 0000000000..f2a9c04d3c --- /dev/null +++ b/org.bndtools.help/docs/heads/dynamicimport_package.html @@ -0,0 +1,94 @@ + + + + +DynamicImport-Package ::= dynamic-description ( ',' dynamic-description )* + + + +

DynamicImport-Package ::= dynamic-description ( ',' dynamic-description )*

+ +

Options

+ + +

DynamicImport-Package

+

The DynamicImport-Package header allows a bundle to declare packages that should be imported dynamically at runtime, rather than being resolved at deployment time. This is useful for cases where the set of required packages is not known in advance.

+

The header contains a comma-separated list of package names, which can include wildcards and directives. For example:

+
DynamicImport-Package: com.example.*, org.osgi.service.*
+
+ +

Packages listed here will be resolved by the OSGi framework when they are first referenced by the bundle. Use this feature sparingly, as it can make dependency management less predictable.

+
/**
+ * <pre>
+ *          DynamicImport-Package ::= dynamic-description
+ *              ( ',' dynamic-description )*
+ *              
+ *          dynamic-description::= wildcard-names ( ';' parameter )*
+ *          wildcard-names ::= wildcard-name ( ';' wildcard-name )*
+ *          wildcard-name ::= package-name 
+ *                         | ( package-name '.*' ) // See 1.4.2
+ *                         | '*'
+ * </pre>
+ */
+private void verifyDynamicImportPackage() {
+    verifyListHeader(Constants.DYNAMICIMPORT_PACKAGE, WILDCARDPACKAGE, true);
+    String dynamicImportPackage = get(Constants.DYNAMICIMPORT_PACKAGE);
+    if (dynamicImportPackage == null)
+        return;
+
+    Parameters map = main.getDynamicImportPackage();
+    for (String name : map.keySet()) {
+        name = name.trim();
+        if (!verify(name, WILDCARDPACKAGE))
+            error(Constants.DYNAMICIMPORT_PACKAGE + " header contains an invalid package name: " + name);
+
+        Map<String,String> sub = map.get(name);
+        if (r3 && sub.size() != 0) {
+            error("DynamicPackage-Import has attributes on import: " + name
+                    + ". This is however, an <=R3 bundle and attributes on this header were introduced in R4. ");
+        }
+    }
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/export_package.html b/org.bndtools.help/docs/heads/export_package.html new file mode 100644 index 0000000000..18afe97fab --- /dev/null +++ b/org.bndtools.help/docs/heads/export_package.html @@ -0,0 +1,245 @@ + + + + +Export-Package ::= export ( ',' export)* + + + +

Export-Package ::= export ( ',' export)*

+ +

Options

+ + +

Export-Package

+

The Export-Package header declares which Java packages in the bundle are made available to other bundles. You can use patterns, wildcards, and directives to control which packages are exported and how.

+

Example:

+
Export-Package: !com.*, *
+
+ +

This example exports all packages except those starting with com.

+

Note: By default bnd automatically calculates Import-Package references for exported packages. This is called package substitution +You can use the -noimport:=true directive which instructs bnd to not calculate Import-Package references for exported packages.

+

Example:

+

` +Export-Package: com.*;-noimport:=true

+

With the -nosubstitution: true instruction, this substitution behavior can be disabled globally.

+

See also: -exportcontents.

+

The bnd definition allows the specification to be done using ''patterns'', a modified regular expression. All patterns in the definition are matched against every package on the [ class path][#CLASSPATH ]. If the pattern is a negating pattern (starts with !) and it is matched, then the package is completely excluded.

+

Normal patterns cause the package to be included in the resulting bundle. Patterns can include both directives and attributes, these items will be copied to the output. The list is ordered, earlier patterns take effect before later patterns.

+

Examples

+

The following examples copies everything on the class path except for packages starting with com. If the source packages have an associated version (from their manifest of packageinfo file), then this version is automatically added to the clauses.

+
Export-Package= !com.*, *
+
+ +

Exports are automatically imported. This features can be disabled with a special directive on the export instruction: -noimport:=true. For example:

+
Export-Package= com.acme.impl.*;-noimport:=true, *
+
+ +

Bnd will automatically calculate the uses: directive. This directive is used by the OSGi framework to create a consistent class space for a bundle. The Export-Package statement allows this directive to be overridden on a package basis by specifying the directive in an Export-Package instruction.

+
Export-package = com.acme.impl.*;uses="my.special.import"
+
+ +

However, in certain cases it is necessary to augment the uses clause. It is therefore possible to use the special name <<USES>> in the clause. Bnd will replace this special name with the calculated uses set. Bnd will remove any extraneous commas when the <<USES>> is empty.

+
Export-package = com.acme.impl.*;uses:="my.special.import,<<USES>>"
+
+ +

Directives that are not part of the OSGi specification will give a warning unless they are prefixed with a 'x-'.

+

Attribute and Directive Ordering

+

When bnd processes the Export-Package header, it automatically ensures consistent ordering of attributes and directives within each package clause. Attributes (keys without a trailing colon) are placed before directives (keys with a trailing colon), and both groups are sorted alphabetically. This ensures reproducible builds and easier comparison of manifest files.

+

For more details, see OSGi Header Attribute and Directive Ordering.

+
        //
+        // EXPORTS
+        //
+        {
+            Set<Instruction> unused = Create.set();
+
+            Instructions filter = new Instructions(getExportPackage());
+            filter.append(getExportContents());
+
+            exports = filter(filter, contained, unused);
+
+            if (!unused.isEmpty()) {
+                warning("Unused " + Constants.EXPORT_PACKAGE + " instructions: %s ", unused);
+            }
+
+            // See what information we can find to augment the
+            // exports. I.e. look on the classpath
+            augmentExports(exports);
+        }
+
+    /**
+ * Check if the given resource is in scope of this bundle. That is, it
+ * checks if the Include-Resource includes this resource or if it is a class
+ * file it is on the class path and the Export-Package or Private-Package
+ * include this resource.
+ *
+ * @param f
+ * @return
+ */
+public boolean isInScope(Collection<File> resources) throws Exception {
+    Parameters clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
+    clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
+    clauses.putAll(parseHeader(getProperty(Constants.PRIVATEPACKAGE)));
+    if (isTrue(getProperty(Constants.UNDERTEST))) {
+        clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES, "test;presence:=optional")));
+    }
+
+    Collection<String> ir = getIncludedResourcePrefixes();
+
+    Instructions instructions = new Instructions(clauses);
+
+    for (File r : resources) {
+        String cpEntry = getClasspathEntrySuffix(r);
+
+        if (cpEntry != null) {
+
+            if (cpEntry.equals("")) // Meaning we actually have a CPE
+                return true;
+
+            String pack = Descriptors.getPackage(cpEntry);
+            Instruction i = matches(instructions, pack, null, r.getName());
+            if (i != null)
+                return !i.isNegated();
+        }
+
+        // Check if this resource starts with one of the I-C header
+        // paths.
+        String path = r.getAbsolutePath();
+        for (String p : ir) {
+            if (path.startsWith(p))
+                return true;
+        }
+    }
+    return false;
+}
+
+    /**
+ * Verify that the exports only use versions.
+ */
+private void verifyExports() {
+    if (isStrict()) {
+        Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
+        Set<String> noexports = new HashSet<String>();
+
+        for (Entry<String,Attrs> e : map.entrySet()) {
+
+            String version = e.getValue().get(Constants.VERSION_ATTRIBUTE);
+            if (version == null) {
+                noexports.add(e.getKey());
+            } else {
+                if (!VERSION.matcher(version).matches()) {
+                    Location location;
+                    if (VERSIONRANGE.matcher(version).matches()) {
+                        location = error(
+                                "Export Package %s version is a range: %s; Exports do not allow for ranges.",
+                                e.getKey(), version).location();
+                    } else {
+                        location = error("Export Package %s version has invalid syntax: %s", e.getKey(), version)
+                                .location();
+                    }
+                    location.header = Constants.EXPORT_PACKAGE;
+                    location.context = e.getKey();
+                }
+            }
+
+            if (e.getValue().containsKey(Constants.SPECIFICATION_VERSION)) {
+                Location location = error(
+                        "Export Package %s uses deprecated specification-version instead of version", e.getKey())
+                        .location();
+                location.header = Constants.EXPORT_PACKAGE;
+                location.context = e.getKey();
+            }
+
+            String mandatory = e.getValue().get(Constants.MANDATORY_DIRECTIVE);
+            if (mandatory != null) {
+                Set<String> missing = new HashSet<String>(split(mandatory));
+                missing.removeAll(e.getValue().keySet());
+                if (!missing.isEmpty()) {
+                    Location location = error("Export Package %s misses mandatory attribute: %s", e.getKey(),
+                            missing).location();
+                    location.header = Constants.EXPORT_PACKAGE;
+                    location.context = e.getKey();
+                }
+            }
+        }
+
+        if (!noexports.isEmpty()) {
+            Location location = error("Export Package clauses without version range: %s", noexports).location();
+            location.header = Constants.EXPORT_PACKAGE;
+        }
+    }
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/export_service.html b/org.bndtools.help/docs/heads/export_service.html new file mode 100644 index 0000000000..d87378683d --- /dev/null +++ b/org.bndtools.help/docs/heads/export_service.html @@ -0,0 +1,22 @@ + + + + +Export-Service + + + +

Export-Service

+ + + diff --git a/org.bndtools.help/docs/heads/fragment_host.html b/org.bndtools.help/docs/heads/fragment_host.html new file mode 100644 index 0000000000..b64ea7f8e7 --- /dev/null +++ b/org.bndtools.help/docs/heads/fragment_host.html @@ -0,0 +1,58 @@ + + + + +Fragment-Host ::= bundle-description + + + +

Fragment-Host ::= bundle-description

+ +

Options

+ + +

Fragment-Host

+

The Fragment-Host header specifies the symbolic name of the host bundle(s) for a fragment bundle. A fragment is attached to its host at runtime and shares the same class loader. When a fragment is attached, some headers (such as Import-Package) are merged with those of the host.

+

Example:

+
Fragment-Host: com.example.hostbundle
+
+ +

bnd will automatically subtract any packages found in the host from the fragment's imports. This header is required for all fragment bundles.

+

The Fragment-Host manifest header links the fragment to its potential hosts. A fragment bundle is loaded in the +same class loader as the host that it will be attached to in runtime. When a fragment is attached to its host, +then some headers are merged. One of those headers is the Import Package header.

+

bnd will calculate the references without taking the host into account. If the fragment uses packages from the host, +quite likely, then these would result in imports. For this reason, bnd will subtract any package that can be found +in the host from the import.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/ignore_package.html b/org.bndtools.help/docs/heads/ignore_package.html new file mode 100644 index 0000000000..a7e229774c --- /dev/null +++ b/org.bndtools.help/docs/heads/ignore_package.html @@ -0,0 +1,22 @@ + + + + +Ignore-Package + + + +

Ignore-Package

+ + + diff --git a/org.bndtools.help/docs/heads/import_package.html b/org.bndtools.help/docs/heads/import_package.html new file mode 100644 index 0000000000..a6750c1bb4 --- /dev/null +++ b/org.bndtools.help/docs/heads/import_package.html @@ -0,0 +1,114 @@ + + + + +Import-Package ::= import ( ',' import )* + + + +

Import-Package ::= import ( ',' import )*

+ +

Options

+ + +

Import-Package

+

The Import-Package header lists the Java packages that the bundle requires from other bundles. By default, bnd will import all referred packages, but you can use patterns and negations to control which packages are imported.

+

Example:

+
Import-Package: !com.example.internal.*, *
+
+ +

This example imports all referred packages except those starting with com.example.internal. You can also add explicit imports for packages not directly referred to by your code.

+

bnd will attempt to find the exported version of imported packages and will use the exported version unless a specific version or range is specified. This header is important for managing dependencies between bundles.

+

The Import-Package header lists the packages that are required by the contained packages. The default for this header is *, resulting in importing all referred packages. This header therefore rarely has to be specified. However, in certain cases there is an unwanted import. The import is caused by code that the author knows can never be reached. This import can be removed by using a negating pattern. A pattern is inserted in the import as an extra import when it contains no wildcards and there is no referral to that package. This can be used to add an import statement for a package that is not referred to by your code but is still needed, for example, because the class is loaded by name.

+

For example:

+
Import-Package: !org.apache.commons.log4j, com.acme.*,\
+ com.foo.extra
+
+ +

During processing, bnd will attempt to find the exported version of imported packages. If no version or version range is specified on the import instruction, the exported version will then be used though the micro part and the qualifier are dropped. That is, when the exporter is 1.2.3.build123, then the import version will be 1.2. If a specific version (range) is specified, this will override any found version. This default an be overridden with the -consumerpolicy or -providerpolicy instruction (also see Versioning).

+

If an explicit version is given, then ${@} can be used to substitute the found version in a range. In those cases, the range macro can be very useful to calculate ranges and drop specific parts of the version. For example:

+
Import-Package: org.osgi.framework;version="[1.3,2.0)"
+Import-Package: org.osgi.framework;version="${@}"
+Import-Package: org.osgi.framework;version="${range;[==,=+);${@}}"
+
+ +

You can reference the Bundle-SymbolicName and Bundle-Version of the exporter on the classpath by using the ${@bundlesymbolicname} and ${@bundleversion} values. In those cases, the range macro can be very useful to calculate ranges and drop specific parts of the bundle version. For example:

+
Import-Package: org.eclipse.jdt.ui;bundle-symbolic-name="${@bundlesymbolicname}";\
+ bundle-version="${range;[==,+);${@bundleversion}}"
+
+ +

Packages with directive resolution:=dynamic will be removed from Import-Package and added to the DynamicImport-Package header after being processed like any other Import-Package entry. For example:

+
Import-Package: org.slf4j.*;resolution:=dynamic, *
+
+ +

If an imported package uses mandatory attributes, then bnd will attempt to add those attributes to the import statement. However, in certain (bizarre!) cases this is not wanted. It is therefore possible to remove an attribute from the import clause. This is done with the -remove-attribute directive or by setting the value of an attribute to !. The parameter of the -remove-attribute directive is an instruction and can use the standard options with !, *, ?, etc.

+
Import-Package: org.eclipse.core.runtime;-remove-attribute:="common",*
+
+ +

Or

+
Import-Package: org.eclipse.core.runtime;common=!,*
+
+ +

Directives that are not part of the OSGi specification will give a warning unless they are prefixed with x-.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/index.html b/org.bndtools.help/docs/heads/index.html new file mode 100644 index 0000000000..62bd79dd76 --- /dev/null +++ b/org.bndtools.help/docs/heads/index.html @@ -0,0 +1,68 @@ + + + + +Manifest Headers Reference + + + +

Manifest Headers Reference

+ + + diff --git a/org.bndtools.help/docs/heads/javac.encoding.html b/org.bndtools.help/docs/heads/javac.encoding.html new file mode 100644 index 0000000000..77a8127ded --- /dev/null +++ b/org.bndtools.help/docs/heads/javac.encoding.html @@ -0,0 +1,19 @@ + + + + +javac.encoding + + + +

javac.encoding

+ + + diff --git a/org.bndtools.help/docs/heads/javac.html b/org.bndtools.help/docs/heads/javac.html new file mode 100644 index 0000000000..58b34d8631 --- /dev/null +++ b/org.bndtools.help/docs/heads/javac.html @@ -0,0 +1,14 @@ + + + + +javac + + + +

javac

+ + + diff --git a/org.bndtools.help/docs/heads/javac.profile.html b/org.bndtools.help/docs/heads/javac.profile.html new file mode 100644 index 0000000000..675260ffbb --- /dev/null +++ b/org.bndtools.help/docs/heads/javac.profile.html @@ -0,0 +1,19 @@ + + + + +javac.profile + + + +

javac.profile

+ + + diff --git a/org.bndtools.help/docs/heads/javac.source.html b/org.bndtools.help/docs/heads/javac.source.html new file mode 100644 index 0000000000..20219620af --- /dev/null +++ b/org.bndtools.help/docs/heads/javac.source.html @@ -0,0 +1,19 @@ + + + + +javac.source + + + +

javac.source

+ + + diff --git a/org.bndtools.help/docs/heads/javac.target.html b/org.bndtools.help/docs/heads/javac.target.html new file mode 100644 index 0000000000..3a80367d9c --- /dev/null +++ b/org.bndtools.help/docs/heads/javac.target.html @@ -0,0 +1,19 @@ + + + + +javac.target + + + +

javac.target

+ + + diff --git a/org.bndtools.help/docs/heads/meta_persistence.html b/org.bndtools.help/docs/heads/meta_persistence.html new file mode 100644 index 0000000000..cbe6e83994 --- /dev/null +++ b/org.bndtools.help/docs/heads/meta_persistence.html @@ -0,0 +1,69 @@ + + + + +Meta-Persistence ::= ( RESOURCE ( ',' RESOURCE )* )? + + + +

Meta-Persistence ::= ( RESOURCE ( ',' RESOURCE )* )?

+ + +

Meta-Persistence

+

The Meta-Persistence header marks a bundle as a JPA (Java Persistence API) persistence bundle. It lists one or more resource paths (typically XML files) that describe the persistence units. If this header is not present, the bundle is not considered a persistence bundle and should be ignored by JPA providers.

+

Example:

+
Meta-Persistence: META-INF/persistence.xml
+
+ +

bnd will verify that the listed resources exist in the bundle. This header is required for JPA persistence bundles.

+
/**
+ * Verify the Meta-Persistence header
+ * 
+ * @throws Exception
+ */
+
+public void verifyMetaPersistence() throws Exception {
+    List<String> list = new ArrayList<String>();
+    String mp = dot.getManifest().getMainAttributes().getValue(META_PERSISTENCE);
+    for (String location : OSGiHeader.parseHeader(mp).keySet()) {
+        String[] parts = location.split("!/");
+
+        Resource resource = dot.getResource(parts[0]);
+        if (resource == null)
+            list.add(location);
+        else {
+            if (parts.length > 1) {
+                Jar jar = new Jar("", resource.openInputStream());
+                try {
+                    resource = jar.getResource(parts[1]);
+                    if (resource == null)
+                        list.add(location);
+                }
+                catch (Exception e) {
+                    list.add(location);
+                }
+                finally {
+                    jar.close();
+                }
+            }
+        }
+    }
+    if (list.isEmpty())
+        return;
+
+    error(Constants.META_PERSISTENCE + " refers to resources not in the bundle: %s", list).header(Constants.META_PERSISTENCE);
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/private_package.html b/org.bndtools.help/docs/heads/private_package.html new file mode 100644 index 0000000000..ca80b5cfbf --- /dev/null +++ b/org.bndtools.help/docs/heads/private_package.html @@ -0,0 +1,155 @@ + + + + +Private-Package PACKAGE-SPEC ( ',' PACKAGE-SPEC )* + + + +

Private-Package PACKAGE-SPEC ( ',' PACKAGE-SPEC )*

+ + +

Private-Package

+

The Private-Package header specifies which packages should be included in the bundle but not exported. The syntax and behavior are similar to the Export-Package header, but these packages are private to the bundle and not visible to other bundles.

+

Example:

+
Private-Package: com.example.internal.*
+
+ +

If a package is selected by both the export and private package headers, the export takes precedence. bnd will merge split packages by default, but you can control this with the -split-package: directive.

+

Private Package

+

The method of inclusion is identical to the Export-Package header, the only difference is, is that these packages are not exported. This header will be copied to the manifest. If a package is selected by the export and private package headers, then the export takes precedence.

+

Private-Package= com.*

+

Split packages

+

Bnd traverse the packages on the classpath and copies them to the output based on the instructions given by the Export-Package and Private-Package headers. This opens up for the possibility that there are multiple packages with the same name on the class path. It is better to avoid this situation because it means there is no cohesive definition of the package and it is just, eh, messy. However, there are valid cases that packages should be merged from different sources. For example, when a standard package needs to be merged with implementation code like the osgi packages sometimes (unfortunately) do. Without any extra instructions, bnd will merge multiple packages where the last one wins if the packages contain duplicate resources, but it will give a warning to notify the unwanted case of split packages.

+

The -split-package: directive on the Export-Package/Private-Package clause allows fine grained control over what should be done with split packages. The following values are architected:

+

||merge-first||Merge split packages but do not add resources that come later in the classpath. That is, the first resource wins. This is the default, although the default will generate a warning|| +||merge-last||Merge split packages but overwrite resources that come earlier in the classpath. That is, the last resource wins.|| +||first||Do not merge, only use the first package found|| +||error||Generate an error when a split package is detected||

+

For example:

+

Private-Package: test.pack;-split-package:=merge-first

+
private void doExpand(Jar dot) {
+
+    // Build an index of the class path that we can then
+    // use destructively
+    MultiMap<String,Jar> packages = new MultiMap<String,Jar>();
+    for (Jar srce : getClasspath()) {
+        dot.updateModified(srce.lastModified, srce + " (" + srce.lastModifiedReason + ")");
+        for (Entry<String,Map<String,Resource>> e : srce.getDirectories().entrySet()) {
+            if (e.getValue() != null)
+                packages.add(e.getKey(), srce);
+        }
+    }
+
+    Parameters privatePackages = getPrivatePackage();
+    if (isTrue(getProperty(Constants.UNDERTEST))) {
+        String h = getProperty(Constants.TESTPACKAGES, "test;presence:=optional");
+        privatePackages.putAll(parseHeader(h));
+    }
+
+    if (!privatePackages.isEmpty()) {
+        Instructions privateFilter = new Instructions(privatePackages);
+        Set<Instruction> unused = doExpand(dot, packages, privateFilter);
+
+        if (!unused.isEmpty()) {
+            warning("Unused " + Constants.PRIVATE_PACKAGE + " instructions, no such package(s) on the class path: %s", unused);
+        }
+    }
+
+    Parameters exportedPackage = getExportPackage();
+    if (!exportedPackage.isEmpty()) {
+        Instructions exportedFilter = new Instructions(exportedPackage);
+
+        // We ignore unused instructions for exports, they should show
+        // up as errors during analysis. Otherwise any overlapping
+        // packages with the private packages should show up as
+        // unused
+
+        doExpand(dot, packages, exportedFilter);
+    }
+}
+
+
+
+
+
+
+    /**
+ * Allow any local initialization by subclasses before we build.
+ */
+public void init() throws Exception {
+    begin();
+    doRequireBnd();
+
+    // Check if we have sensible setup
+
+    if (getClasspath().size() == 0
+            && (getProperty(EXPORT_PACKAGE) != null || getProperty(EXPORT_PACKAGE) != null || getProperty(PRIVATE_PACKAGE) != null || getProperty(PRIVATEPACKAGE) != null))
+        warning("Classpath is empty. " + Constants.PRIVATE_PACKAGE + " (-privatepackage) and " + EXPORT_PACKAGE + " can only expand from the classpath when there is one");
+
+}
+
+
+
+    /**
+ * Check if the given resource is in scope of this bundle. That is, it
+ * checks if the Include-Resource includes this resource or if it is a class
+ * file it is on the class path and the Export-Package or Private-Package
+ * include this resource.
+ *
+ * @param f
+ * @return
+ */
+public boolean isInScope(Collection<File> resources) throws Exception {
+    Parameters clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
+    clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
+    clauses.putAll(parseHeader(getProperty(Constants.PRIVATEPACKAGE)));
+    if (isTrue(getProperty(Constants.UNDERTEST))) {
+        clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES, "test;presence:=optional")));
+    }
+
+    Collection<String> ir = getIncludedResourcePrefixes();
+
+    Instructions instructions = new Instructions(clauses);
+
+    for (File r : resources) {
+        String cpEntry = getClasspathEntrySuffix(r);
+
+        if (cpEntry != null) {
+
+            if (cpEntry.equals("")) // Meaning we actually have a CPE
+                return true;
+
+            String pack = Descriptors.getPackage(cpEntry);
+            Instruction i = matches(instructions, pack, null, r.getName());
+            if (i != null)
+                return !i.isNegated();
+        }
+
+        // Check if this resource starts with one of the I-C header
+        // paths.
+        String path = r.getAbsolutePath();
+        for (String p : ir) {
+            if (path.startsWith(p))
+                return true;
+        }
+    }
+    return false;
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/provide_capability.html b/org.bndtools.help/docs/heads/provide_capability.html new file mode 100644 index 0000000000..0162474c67 --- /dev/null +++ b/org.bndtools.help/docs/heads/provide_capability.html @@ -0,0 +1,201 @@ + + + + +Provide-Capability ::= capability (',' capability )* + + + +

Provide-Capability ::= capability (',' capability )*

+ +

Options

+ + +

Provide-Capability

+

The Provide-Capability header declares that a bundle provides one or more OSGi capabilities. Capabilities are used by the OSGi framework to match requirements from other bundles. Each capability can include a namespace, attributes, and directives.

+

Example:

+
Provide-Capability: osgi.service;objectClass=com.example.MyService;version=1.0.0
+
+ +

This header is used for advanced modularity and service scenarios, and is typically generated by annotations or build tooling.

+
        Parameters capabilities = new Parameters(annotationHeaders.getHeader(PROVIDE_CAPABILITY));
+
+
+    /*
+ * Provide-Capability header
+ */
+private void doProvideCapability(ProvideCapability annotation) {
+    StringBuilder sb = new StringBuilder(annotation.ns());
+    if (annotation.name() != null)
+        sb.append(";").append(annotation.ns()).append("='").append(annotation.name()).append("'");
+    if (annotation.uses() != null)
+        sb.append(";").append("uses:='").append(Strings.join(",", annotation.uses())).append("'");
+    if (annotation.mandatory() != null)
+        sb.append(";").append("mandatory:='").append(Strings.join(",", annotation.mandatory())).append("'");
+    if (annotation.version() != null)
+        sb.append(";").append("version:Version='").append(annotation.version()).append("'");
+    if (annotation.value() != null)
+        sb.append(";").append(annotation.value());
+    if (annotation.effective() != null)
+        sb.append(";effective:='").append(annotation.effective()).append("'");
+
+    add(Constants.PROVIDE_CAPABILITY, sb.toString());
+}
+
+
+
+
+        package aQute.bnd.annotation.headers;
+
+    import java.lang.annotation.*;
+
+    /**
+     * Define a Provide Capability clause in the manifest.
+     * <p>
+     * Since this annotation can only be applied once, it is possible to create an annotation
+     * that models a specific capability. For example:
+     * <pre>
+     * interface Webserver {
+     *      @ProvideCapability(ns="osgi.extender", name="aQute.webserver", version = "${@version}")
+     *      @interface Provide {}
+     * 
+     *      @RequireCapability(ns="osgi.extender", filter="(&(osgi.extender=aQute.webserver)${frange;${@version}})")
+     *      @interface Require {}
+     * }
+     * 
+     * Webserver.@Provide
+     * public class MyWebserver {
+     * }
+     * </pre>
+     * 
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Target({
+            ElementType.ANNOTATION_TYPE, ElementType.TYPE
+    })
+    public @interface ProvideCapability {
+        /**
+         * Appended at the end of the clause (after a ';'). Can be used to add
+         * additional attributes and directives.
+         */
+        String value() default "";
+
+        /**
+         * The capability namespace. For example: {@code osgi.contract}.
+         */
+        String ns();
+
+        /**
+         * The name of the capability. If this is set, a property will be added as
+         * {ns}={name}. This is the custom pattern for OSGi namespaces. Leaving this
+         * unfilled, requires the {@link #value()} to be used to specify the name of
+         * the capability, if needed. For example {@code aQute.sse}.
+         */
+        String name() default "";
+
+        /**
+         * The version of the capability. This must be a valid OSGi version.
+         */
+        String version() default "";
+
+        /**
+         * Effective time. Specifies the time a capability is available, either
+         * resolve (default) or another name. The OSGi framework resolver only
+         * considers Capabilities without an effective directive or
+         * effective:=resolve. Capabilities with other values for the effective
+         * directive can be considered by an external agent.
+         */
+        String effective() default "resolve";
+
+        /**
+         * The uses directive lists package names that are used by this Capability.
+         * This information is intended to be used for <em>uses constraints</em>,
+         */
+        String[] uses() default {};
+
+        /**
+         * Mandatory attributes. Forces the resolver to only satisfy filters that
+         * refer to all listed attributes.
+         */
+        String[] mandatory() default {};
+    }
+
+
+
+                verifyDirectives(Constants.PROVIDE_CAPABILITY, "effective:|uses:", null, null);
+
+
+
+
+        private void verifyCapabilities() {
+    Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.PROVIDE_CAPABILITY));
+    for (String key : map.keySet()) {
+        Attrs attrs = map.get(key);
+        verify(attrs, "cardinality:", CARDINALITY_PATTERN, false, "Requirement %s cardinality not correct", key);
+        verify(attrs, "resolution:", RESOLUTION_PATTERN, false, "Requirement %s resolution not correct", key);
+
+        if (key.equals("osgi.extender")) {
+            verify(attrs, "osgi.extender", SYMBOLICNAME, true,
+                    "Extender %s must always have the osgi.extender attribute set", key);
+            verify(attrs, "version", VERSION, true, "Extender %s must always have a version", key);
+        } else if (key.equals("osgi.serviceloader")) {
+            verify(attrs, "register:", PACKAGEPATTERN, false,
+                    "Service Loader extender register: directive not a fully qualified Java name");
+        } else if (key.equals("osgi.contract")) {
+            verify(attrs, "osgi.contract", SYMBOLICNAME, true,
+                    "Contracts %s must always have the osgi.contract attribute set", key);
+
+        } else if (key.equals("osgi.service")) {
+            verify(attrs, "objectClass", MULTIPACKAGEPATTERN, true,
+                    "osgi.service %s must have the objectClass attribute set", key);
+
+        } else if (key.equals("osgi.ee")) {
+            // TODO
+        } else if (key.startsWith("osgi.wiring.") || key.startsWith("osgi.identity")) {
+            error("osgi.wiring.* namespaces must not be specified with generic requirements/capabilities");
+        }
+
+        verifyAttrs(attrs);
+
+        if (attrs.containsKey("filter:"))
+            error("filter: directive is intended for Requirements, not Capability %s", key);
+        if (attrs.containsKey("cardinality:"))
+            error("cardinality: directive is intended for Requirements, not Capability %s", key);
+        if (attrs.containsKey("resolution:"))
+            error("resolution: directive is intended for Requirements, not Capability %s", key);
+    }
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/require_bundle.html b/org.bndtools.help/docs/heads/require_bundle.html new file mode 100644 index 0000000000..6270d6dc0d --- /dev/null +++ b/org.bndtools.help/docs/heads/require_bundle.html @@ -0,0 +1,110 @@ + + + + +Require-Bundle ::= bundle-description ( ',' bundle-description )* + + + +

Require-Bundle ::= bundle-description ( ',' bundle-description )*

+ +

Options

+ + +

Require-Bundle

+

The Require-Bundle header specifies that the bundle requires all exported packages from another bundle. This effectively imports the public interface of the required bundle, making its packages available to the requiring bundle.

+

Example:

+
Require-Bundle: com.example.otherbundle
+
+ +

This header is less common in OSGi and can make dependency management more complex. Prefer using Import-Package when possible.

+
+
    verifyDirectives(Constants.REQUIRE_BUNDLE, "visibility:|resolution:", SYMBOLICNAME, "bsn");
+
+
+
+        //
+    // If there is a Require bundle, all bets are off and
+    // we cannot verify anything
+    //
+
+    if (domain.getRequireBundle().isEmpty() && domain.get("ExtensionBundle-Activator") == null
+            && (domain.getFragmentHost()== null || domain.getFragmentHost().getKey().equals("system.bundle"))) {
+
+        if (!unresolvedReferences.isEmpty()) {
+            // Now we want to know the
+            // classes that are the culprits
+            Set<String> culprits = new HashSet<String>();
+            for (Clazz clazz : analyzer.getClassspace().values()) {
+                if (hasOverlap(unresolvedReferences, clazz.getReferred()))
+                    culprits.add(clazz.getAbsolutePath());
+            }
+
+            if (analyzer instanceof Builder)
+                warning("Unresolved references to %s by class(es) %s on the " + Constants.BUNDLE_CLASSPATH + ": %s",
+                        unresolvedReferences, culprits, analyzer.getBundleClasspath().keySet());
+            else
+                error("Unresolved references to %s by class(es) %s on the " + Constants.BUNDLE_CLASSPATH + ": %s",
+                        unresolvedReferences, culprits, analyzer.getBundleClasspath().keySet());
+            return;
+        }
+    } else if (isPedantic())
+        warning("Use of " + Constants.REQUIRE_BUNDLE + ", ExtensionBundle-Activator, or a system bundle fragment makes it impossible to verify unresolved references");
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/require_capability.html b/org.bndtools.help/docs/heads/require_capability.html new file mode 100644 index 0000000000..c3913a2f02 --- /dev/null +++ b/org.bndtools.help/docs/heads/require_capability.html @@ -0,0 +1,225 @@ + + + + +Require-Capability ::= requirement ( ',' requirement )* + + + +

Require-Capability ::= requirement ( ',' requirement )*

+ +

Options

+ + +

Require-Capability

+

The Require-Capability header declares that a bundle requires one or more OSGi capabilities to be present in the runtime environment. Each requirement can specify a namespace, filter, and other attributes or directives.

+

Example:

+
Require-Capability: osgi.extender;filter:='(osgi.extender=osgi.component)'
+
+ +

This header is used for advanced modularity and service scenarios, and is typically generated by annotations or build tooling.

+
            Parameters requirements = new Parameters(annotationHeaders.getHeader(REQUIRE_CAPABILITY));
+        Parameters capabilities = new Parameters(annotationHeaders.getHeader(PROVIDE_CAPABILITY));
+
+        //
+        // Do any contracts contracts
+        //
+        contracts.addToRequirements(requirements);
+
+        //
+        // We want to add the minimum EE as a requirement
+        // based on the class version
+        //
+
+        if (!isTrue(getProperty(NOEE)) //
+                && !ees.isEmpty() // no use otherwise
+                && since(About._2_3) // we want people to not have to
+                                        // automatically add it
+                && !requirements.containsKey(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE) // and
+                                                                                                            // it
+                                                                                                            // should
+                                                                                                            // not
+                                                                                                            // be
+                                                                                                            // there
+                                                                                                            // already
+        ) {
+
+            JAVA highest = ees.last();
+            Attrs attrs = new Attrs();
+
+            String filter = doEEProfiles(highest);
+
+            attrs.put(Constants.FILTER_DIRECTIVE, filter);
+
+            //
+            // Java 1.8 introduced profiles.
+            // If -eeprofile= auto | (<profile>="...")+ is set then
+            // we add a
+
+            requirements.add(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, attrs);
+        }
+
+        if (!requirements.isEmpty())
+            main.putValue(REQUIRE_CAPABILITY, requirements.toString());
+
+
+    /*
+ * Require-Capability header
+ */
+private void doRequireCapability(RequireCapability annotation) {
+    StringBuilder sb = new StringBuilder(annotation.ns());
+    if (annotation.filter() != null)
+        sb.append(";filter:='").append(annotation.filter()).append("'");
+    if (annotation.effective() != null)
+        sb.append(";effective:='").append(annotation.effective()).append("'");
+    if (annotation.resolution() != null)
+        sb.append(";resolution:='").append(annotation.resolution()).append("'");
+
+    if (annotation.value() != null)
+        sb.append(";").append(annotation.value());
+
+    add(Constants.REQUIRE_CAPABILITY, sb.toString());
+}
+
+
+package aQute.bnd.annotation.headers;
+
+    import java.lang.annotation.*;
+
+    /**
+     * The Bundle’s Require-Capability header
+     * 
+     * {@link About}
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Target({
+            ElementType.ANNOTATION_TYPE, ElementType.TYPE
+    })
+    public @interface RequireCapability {
+        String value() default "";
+
+        /**
+         * The capability namespace. For example: {@code osgi.contract}.
+         */
+        String ns();
+
+        /**
+         * Specifies the time a Requirement is considered, either 'resolve'
+         * (default) or another name. The OSGi framework resolver only considers
+         * Requirements without an effective directive or effective:=resolve. Other
+         * Requirements can be considered by an external agent. Additional names for
+         * the effective directive should be registered with the OSGi Alliance. See
+         * <a href="https://www.osgi.org/developer/specifications/reference/">OSGi Reference
+         * Page</a>
+         */
+        String effective() default "resolve";
+
+        /**
+         * A filter expression that is asserted on the Capabilities belonging to the
+         * given namespace. The matching of the filter against the Capability is
+         * done on one Capability at a time. A filter like {@code (&(a=1)(b=2))}
+         * matches only a Capability that specifies both attributes at the required
+         * value, not two capabilties that each specify one of the attributes
+         * correctly. A filter is optional, if no filter directive is specified the
+         * Requirement always matches.
+         */
+        String filter();
+
+        /**
+         * A mandatory Requirement forbids the bundle to resolve when the
+         * Requirement is not satisfied; an optional Requirement allows a bundle to
+         * resolve even if the Requirement is not satisfied. No wirings are created
+         * when this Requirement cannot be resolved, this can result in Class Not
+         * Found Exceptions when the bundle attempts to use a package that was not
+         * resolved because it was optional.
+         */
+        Resolution resolution() default Resolution.mandatory;
+
+    }
+
+
+        private void verifyRequirements() {
+    Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.REQUIRE_CAPABILITY));
+    for (String key : map.keySet()) {
+        Attrs attrs = map.get(key);
+        verify(attrs, "filter:", FILTERPATTERN, false, "Requirement %s filter not correct", key);
+
+        String filter = attrs.get("filter:");
+        if (filter != null) {
+            String verify = new Filter(filter).verify();
+            if (verify != null)
+                error("Invalid filter syntax in requirement %s=%s. Reason %s", key, attrs, verify);
+        }
+        verify(attrs, "cardinality:", CARDINALITY_PATTERN, false, "Requirement %s cardinality not correct", key);
+        verify(attrs, "resolution:", RESOLUTION_PATTERN, false, "Requirement %s resolution not correct", key);
+
+        if (key.equals("osgi.extender")) {
+            // No requirements on extender
+        } else if (key.equals("osgi.serviceloader")) {
+            verify(attrs, "register:", PACKAGEPATTERN, false,
+                    "Service Loader extender register: directive not a fully qualified Java name");
+        } else if (key.equals("osgi.contract")) {
+
+        } else if (key.equals("osgi.service")) {
+
+        } else if (key.equals("osgi.ee")) {
+
+        } else if (key.startsWith("osgi.wiring.") || key.startsWith("osgi.identity")) {
+            error("osgi.wiring.* namespaces must not be specified with generic requirements/capabilities");
+        }
+
+        verifyAttrs(attrs);
+
+        if (attrs.containsKey("mandatory:"))
+            error("mandatory: directive is intended for Capabilities, not Requirement %s", key);
+
+        if (attrs.containsKey("uses:"))
+            error("uses: directive is intended for Capabilities, not Requirement %s", key);
+    }
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/service_component.html b/org.bndtools.help/docs/heads/service_component.html new file mode 100644 index 0000000000..b4591fff5d --- /dev/null +++ b/org.bndtools.help/docs/heads/service_component.html @@ -0,0 +1,385 @@ + + + + +Service-Component ::= RESOURCE ( ',' RESOURCE ) + + + +

Service-Component ::= RESOURCE ( ',' RESOURCE )

+ + +

Service-Component

+

The Service-Component header lists XML files that describe Declarative Services (DS) components in the bundle. These XML documents must be present in the bundle and are used by the OSGi framework to register and manage components at runtime.

+

Example:

+
Service-Component: OSGI-INF/components.xml
+
+ +

This header is required for bundles that use OSGi Declarative Services.

+
/**
+ * Analyze the class space for any classes that have an OSGi annotation for DS.
+ */
+public class DSAnnotations implements AnalyzerPlugin {
+
+    public boolean analyzeJar(Analyzer analyzer) throws Exception {
+        Parameters header = OSGiHeader.parseHeader(analyzer.getProperty(Constants.DSANNOTATIONS));
+        if (header.size() == 0)
+            return false;
+
+        Instructions instructions = new Instructions(header);
+        Collection<Clazz> list = analyzer.getClassspace().values();
+        String sc = analyzer.getProperty(Constants.SERVICE_COMPONENT);
+        List<String> names = new ArrayList<String>();
+        if (sc != null && sc.trim().length() > 0)
+            names.add(sc);
+
+        for (Clazz c: list) {
+            for (Instruction instruction : instructions.keySet()) {
+
+                if (instruction.matches(c.getFQN())) {
+                    if (instruction.isNegated())
+                        break;
+                    ComponentDef definition = AnnotationReader.getDefinition(c, analyzer);
+                    if (definition != null) {
+                        definition.sortReferences();
+                        definition.prepare(analyzer);
+                        String name = "OSGI-INF/" + definition.name + ".xml";
+                        names.add(name);
+                        analyzer.getJar().putResource(name, new TagResource(definition.getTag()));
+                    }
+                }
+            }
+        }
+        sc = Processor.append(names.toArray(new String[names.size()]));
+        analyzer.setProperty(Constants.SERVICE_COMPONENT, sc);
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "DSAnnotations";
+    }
+}
+
+            package aQute.bnd.make.component;
+
+        import java.io.*;
+        import java.util.*;
+        import java.util.Map.Entry;
+
+        import aQute.bnd.annotation.component.*;
+        import aQute.bnd.component.*;
+        import aQute.bnd.header.*;
+        import aQute.bnd.make.metatype.*;
+        import aQute.bnd.osgi.*;
+        import aQute.bnd.osgi.Clazz.QUERY;
+        import aQute.bnd.osgi.Descriptors.TypeRef;
+        import aQute.bnd.service.*;
+        import aQute.lib.tag.*;
+
+        /**
+         * This class is an analyzer plugin. It looks at the properties and tries to
+         * find out if the Service-Component header contains the bnd shortut syntax. If
+         * not, the header is copied to the output, if it does, an XML file is created
+         * and added to the JAR and the header is modified appropriately.
+         */
+        public class ServiceComponent implements AnalyzerPlugin {
+
+            public boolean analyzeJar(Analyzer analyzer) throws Exception {
+
+                ComponentMaker m = new ComponentMaker(analyzer);
+
+                Map<String,Map<String,String>> l = m.doServiceComponent();
+
+                analyzer.setProperty(Constants.SERVICE_COMPONENT, Processor.printClauses(l));
+
+                analyzer.getInfo(m, Constants.SERVICE_COMPONENT + ": ");
+                m.close();
+
+                return false;
+            }
+
+            private static class ComponentMaker extends Processor {
+                Analyzer    analyzer;
+
+                ComponentMaker(Analyzer analyzer) {
+                    super(analyzer);
+                    this.analyzer = analyzer;
+                }
+
+                /**
+                 * Iterate over the Service Component entries. There are two cases:
+                 * <ol>
+                 * <li>An XML file reference</li>
+                 * <li>A FQN/wildcard with a set of attributes</li>
+                 * </ol>
+                 * An XML reference is immediately expanded, an FQN/wildcard is more
+                 * complicated and is delegated to
+                 * {@link #componentEntry(Map, String, Map)}.
+                 * 
+                 * @throws Exception
+                 */
+                Map<String,Map<String,String>> doServiceComponent() throws Exception {
+                    Map<String,Map<String,String>> serviceComponents = newMap();
+                    String header = getProperty(SERVICE_COMPONENT);
+                    Parameters sc = parseHeader(header);
+
+                    for (Entry<String,Attrs> entry : sc.entrySet()) {
+                        String name = entry.getKey();
+                        Map<String,String> info = entry.getValue();
+
+                        try {
+                            if (name.indexOf('/') >= 0 || name.endsWith(".xml")) {
+                                // Normal service component, we do not process it
+                                serviceComponents.put(name, EMPTY);
+                            } else {
+                                componentEntry(serviceComponents, name, info);
+                            }
+                        }
+                        catch (Exception e) {
+                            e.printStackTrace();
+                            error("Invalid " + Constants.SERVICE_COMPONENT + " header: %s %s, throws %s", name, info, e);
+                            throw e;
+                        }
+                    }
+                    return serviceComponents;
+                }
+
+                /**
+                 * Parse an entry in the Service-Component header. This header supports
+                 * the following types:
+                 * <ol>
+                 * <li>An FQN + attributes describing a component</li>
+                 * <li>A wildcard expression for finding annotated components.</li>
+                 * </ol>
+                 * The problem is the distinction between an FQN and a wildcard because
+                 * an FQN can also be used as a wildcard. If the info specifies
+                 * {@link Constants#NOANNOTATIONS} then wildcards are an error and the
+                 * component must be fully described by the info. Otherwise the
+                 * FQN/wildcard is expanded into a list of classes with annotations. If
+                 * this list is empty, the FQN case is interpreted as a complete
+                 * component definition. For the wildcard case, it is checked if any
+                 * matching classes for the wildcard have been compiled for a class file
+                 * format that does not support annotations, this can be a problem with
+                 * JSR14 who silently ignores annotations. An error is reported in such
+                 * a case.
+                 * 
+                 * @param serviceComponents
+                 * @param name
+                 * @param info
+                 * @throws Exception
+                 * @throws IOException
+                 */
+                private void componentEntry(Map<String,Map<String,String>> serviceComponents, String name,
+                        Map<String,String> info) throws Exception, IOException {
+
+                    boolean annotations = !Processor.isTrue(info.get(NOANNOTATIONS));
+                    boolean fqn = Verifier.isFQN(name);
+
+                    if (annotations) {
+
+                        // Annotations possible!
+
+                        Collection<Clazz> annotatedComponents = analyzer.getClasses("", QUERY.ANNOTATED.toString(),
+                                Component.class.getName(), //
+                                QUERY.NAMED.toString(), name //
+                                );
+
+                        if (fqn) {
+                            if (annotatedComponents.isEmpty()) {
+
+                                // No annotations, fully specified in header
+
+                                createComponentResource(serviceComponents, name, info);
+                            } else {
+
+                                // We had a FQN so expect only one
+
+                                for (Clazz c : annotatedComponents) {
+                                    annotated(serviceComponents, c, info);
+                                }
+                            }
+                        } else {
+
+                            // We did not have an FQN, so expect the use of wildcards
+
+                            if (annotatedComponents.isEmpty())
+                                checkAnnotationsFeasible(name);
+                            else
+                                for (Clazz c : annotatedComponents) {
+                                    annotated(serviceComponents, c, info);
+                                }
+                        }
+                    } else {
+                        // No annotations
+                        if (fqn)
+                            createComponentResource(serviceComponents, name, info);
+                        else
+                            error("Set to %s but entry %s is not an FQN ", NOANNOTATIONS, name);
+
+                    }
+                }
+
+                /**
+                 * Check if annotations are actually feasible looking at the class
+                 * format. If the class format does not provide annotations then it is
+                 * no use specifying annotated components.
+                 * 
+                 * @param name
+                 * @return
+                 * @throws Exception
+                 */
+                private Collection<Clazz> checkAnnotationsFeasible(String name) throws Exception {
+                    Collection<Clazz> not = analyzer.getClasses("", QUERY.NAMED.toString(), name //
+                            );
+
+                    if (not.isEmpty()) {
+                        if ("*".equals(name))
+                            return not;
+                        error("Specified %s but could not find any class matching this pattern", name);
+                    }
+
+                    for (Clazz c : not) {
+                        if (c.getFormat().hasAnnotations())
+                            return not;
+                    }
+
+                    warning("Wildcards are used (%s) requiring annotations to decide what is a component. Wildcard maps to classes that are compiled with java.target < 1.5. Annotations were introduced in Java 1.5",
+                            name);
+
+                    return not;
+                }
+
+                void annotated(Map<String,Map<String,String>> components, Clazz c, Map<String,String> info) throws Exception {
+                    // Get the component definition
+                    // from the annotations
+                    Map<String,String> map = ComponentAnnotationReader.getDefinition(c, this);
+
+                    // Pick the name, the annotation can override
+                    // the name.
+                    String localname = map.get(COMPONENT_NAME);
+                    if (localname == null)
+                        localname = c.getFQN();
+
+                    // Override the component info without manifest
+                    // entries. We merge the properties though.
+
+                    String merged = Processor.merge(info.remove(COMPONENT_PROPERTIES), map.remove(COMPONENT_PROPERTIES));
+                    if (merged != null && merged.length() > 0)
+                        map.put(COMPONENT_PROPERTIES, merged);
+                    map.putAll(info);
+                    createComponentResource(components, localname, map);
+                }
+
+                private void createComponentResource(Map<String,Map<String,String>> components, String name,
+                        Map<String,String> info) throws Exception {
+
+                    // We can override the name in the parameters
+                    if (info.containsKey(COMPONENT_NAME))
+                        name = info.get(COMPONENT_NAME);
+
+                    // Assume the impl==name, but allow override
+                    String impl = name;
+                    if (info.containsKey(COMPONENT_IMPLEMENTATION))
+                        impl = info.get(COMPONENT_IMPLEMENTATION);
+
+                    TypeRef implRef = analyzer.getTypeRefFromFQN(impl);
+                    // Check if such a class exists
+                    analyzer.referTo(implRef);
+
+                    boolean designate = designate(name, info.get(COMPONENT_DESIGNATE), false)
+                            || designate(name, info.get(COMPONENT_DESIGNATEFACTORY), true);
+
+                    // If we had a designate, we want a default configuration policy of
+                    // require.
+                    if (designate && info.get(COMPONENT_CONFIGURATION_POLICY) == null)
+                        info.put(COMPONENT_CONFIGURATION_POLICY, "require");
+
+                    // We have a definition, so make an XML resources
+                    Resource resource = createComponentResource(name, impl, info);
+                    analyzer.getJar().putResource("OSGI-INF/" + name + ".xml", resource);
+
+                    components.put("OSGI-INF/" + name + ".xml", EMPTY);
+
+                }
+
+                /**
+                 * Create a Metatype and Designate record out of the given
+                 * configurations.
+                 * 
+                 * @param name
+                 * @param config
+                 * @throws Exception 
+                 */
+                private boolean designate(String name, String config, boolean factory) throws Exception {
+                    if (config == null)
+                        return false;
+
+                    for (String c : Processor.split(config)) {
+                        TypeRef ref = analyzer.getTypeRefFromFQN(c);
+                        Clazz clazz = analyzer.findClass(ref);
+                        if (clazz != null) {
+                            analyzer.referTo(ref);
+                            MetaTypeReader r = new MetaTypeReader(clazz, analyzer);
+                            r.setDesignate(name, factory);
+                            String rname = "OSGI-INF/metatype/" + name + ".xml";
+
+                            analyzer.getJar().putResource(rname, r);
+                        } else {
+                            analyzer.error("Cannot find designated configuration class %s for component %s", c, name);
+                        }
+                    }
+                    return true;
+                }
+
+                /**
+                 * Create the resource for a DS component.
+                 * 
+                 * @param list
+                 * @param name
+                 * @param info
+                 * @throws UnsupportedEncodingException
+                 */
+                Resource createComponentResource(String name, String impl, Map<String, String> info)
+                        throws Exception {
+                    HeaderReader hr = new HeaderReader(analyzer);
+                    Tag tag = hr.createComponentTag(name, impl, info);
+                    hr.close();
+                    return new TagResource(tag);
+                }
+            }
+
+        }
+
+
+
+
+
+
+                private void verifyComponent() {
+    String serviceComponent = main.get(Constants.SERVICE_COMPONENT);
+    if (serviceComponent != null) {
+        Parameters map = parseHeader(serviceComponent);
+        for (String component : map.keySet()) {
+            if (component.indexOf("*") < 0 && !dot.exists(component)) {
+                error(Constants.SERVICE_COMPONENT + " entry can not be located in JAR: " + component);
+            } else {
+                // validate component ...
+            }
+        }
+    }
+}
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/src.html b/org.bndtools.help/docs/heads/src.html new file mode 100644 index 0000000000..d71351527d --- /dev/null +++ b/org.bndtools.help/docs/heads/src.html @@ -0,0 +1,19 @@ + + + + +src + + + +

src

+ + + diff --git a/org.bndtools.help/docs/heads/target_dir.html b/org.bndtools.help/docs/heads/target_dir.html new file mode 100644 index 0000000000..0598a7e94a --- /dev/null +++ b/org.bndtools.help/docs/heads/target_dir.html @@ -0,0 +1,22 @@ + + + + +target-dir + + + +

target-dir

+ + +

The target-dir header is also useful to avoid conflicts between different build tools.

+



+ + diff --git a/org.bndtools.help/docs/heads/test_cases.html b/org.bndtools.help/docs/heads/test_cases.html new file mode 100644 index 0000000000..23cf74b454 --- /dev/null +++ b/org.bndtools.help/docs/heads/test_cases.html @@ -0,0 +1,180 @@ + + + + +Test-Cases CLASS ( ',' CLASS ) * + + + +

Test-Cases CLASS ( ',' CLASS ) *

+ + +

Test-Cases

+

The Test-Cases header specifies one or more test classes to be automatically executed by the bnd JUnit tester. This header is used to configure which tests should run when the bundle is tested in an OSGi environment.

+

Example:

+
Test-Cases: com.example.MyTest, com.example.AnotherTest
+
+ +

This header is typically set by build tooling or annotations and is required for automatic test execution with bnd's JUnit integration.

+
private void checkForTesting(Project project, Properties properties) throws Exception {
+
+    //
+    // Only run junit when we have a test src directory
+    //
+
+    boolean junit = project.getTestSrc().isDirectory() && !Processor.isTrue(project.getProperty(Constants.NOJUNIT));
+    boolean junitOsgi = project.getProperties().getProperty(Constants.TESTCASES) != null
+            && !Processor.isTrue(project.getProperty(Constants.NOJUNITOSGI));
+
+    if (junit)
+        properties.setProperty("project.junit", "true");
+    if (junitOsgi)
+        properties.setProperty("project.osgi.junit", "true");
+}
+
+public void test(List<String> tests) throws Exception {
+
+    String testcases = getProperties().getProperty(Constants.TESTCASES);
+    if (testcases == null) {
+        warning("No %s set", Constants.TESTCASES);
+        return;
+    }
+    clear();
+
+    ProjectTester tester = getProjectTester();
+    if ( tests != null) {
+        trace("Adding tests %s", tests);
+        for ( String test : tests) {
+            tester.addTest(test);
+        }
+    }
+    tester.setContinuous(isTrue(getProperty(Constants.TESTCONTINUOUS)));
+    tester.prepare();
+
+    if (!isOk()) {
+        return;
+    }
+    int errors = tester.test();
+    if (errors == 0) {
+        System.err.println("No Errors");
+    } else {
+        if (errors > 0) {
+            System.err.println(errors + " Error(s)");
+
+        } else
+            System.err.println("Error " + errors);
+    }
+}
+
+    void automatic() throws IOException {
+    String testerDir = context.getProperty(TESTER_DIR);
+    if (testerDir == null)
+        testerDir = "testdir";
+
+    final File reportDir = new File(testerDir);
+    final List<Bundle> queue = new Vector<Bundle>();
+    if (!reportDir.exists() && !reportDir.mkdirs()) {
+        throw new IOException("Could not create directory " + reportDir);
+    }
+    trace("using %s, needed creation %s", reportDir, reportDir.mkdirs());
+
+    trace("adding Bundle Listener for getting test bundle events");
+    context.addBundleListener(new SynchronousBundleListener() {
+        public void bundleChanged(BundleEvent event) {
+            if (event.getType() == BundleEvent.STARTED) {
+                checkBundle(queue, event.getBundle());
+            }
+
+        }
+    });
+
+    for (Bundle b : context.getBundles()) {
+        checkBundle(queue, b);
+    }
+
+    trace("starting queue");
+    int result = 0;
+    outer: while (active) {
+        Bundle bundle;
+        synchronized (queue) {
+            while (queue.isEmpty() && active) {
+                try {
+                    queue.wait();
+                }
+                catch (InterruptedException e) {
+                    trace("tests bundle queue interrupted");
+                    thread.interrupt();
+                    break outer;
+                }
+            }
+        }
+        try {
+            bundle = queue.remove(0);
+            trace("received bundle to test: %s", bundle.getLocation());
+            Writer report = getReportWriter(reportDir, bundle);
+            try {
+                trace("test will run");
+                result += test(bundle, (String) bundle.getHeaders().get(aQute.bnd.osgi.Constants.TESTCASES), report);
+                trace("test ran");
+                if (queue.isEmpty() && !continuous) {
+                    trace("queue " + queue);
+                    System.exit(result);
+                }
+            }
+            finally {
+                if (report != null)
+                    report.close();
+            }
+        }
+        catch (Exception e) {
+            error("Not sure what happened anymore %s", e);
+            System.exit(254);
+        }
+    }
+}
+
+
+    void checkBundle(List<Bundle> queue, Bundle bundle) {
+    if (bundle.getState() == Bundle.ACTIVE) {
+        String testcases = (String) bundle.getHeaders().get(aQute.bnd.osgi.Constants.TESTCASES);
+        if (testcases != null) {
+            trace("found active bundle with test cases %s : %s", bundle, testcases);
+            synchronized (queue) {
+                queue.add(bundle);
+                queue.notifyAll();
+            }
+        }
+    }
+}
+
+
+
+
+    if (testcases == null) {
+
+ +

// if ( !continuous) { +// System.err.println("\nThe -testcontinuous property must be set if invoked without arguments\n"); +// System.exit(255); +// }

+
        trace("automatic testing of all bundles with " + aQute.bnd.osgi.Constants.TESTCASES + " header");
+        try {
+            automatic();
+        }
+        catch (IOException e) {
+            // ignore
+        }
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/heads/testbin.html b/org.bndtools.help/docs/heads/testbin.html new file mode 100644 index 0000000000..9311e01329 --- /dev/null +++ b/org.bndtools.help/docs/heads/testbin.html @@ -0,0 +1,19 @@ + + + + +testbin + + + +

testbin

+ + + diff --git a/org.bndtools.help/docs/heads/tester_plugin.html b/org.bndtools.help/docs/heads/tester_plugin.html new file mode 100644 index 0000000000..04c7580767 --- /dev/null +++ b/org.bndtools.help/docs/heads/tester_plugin.html @@ -0,0 +1,19 @@ + + + + +Tester-Plugin + + + +

Tester-Plugin

+ + + diff --git a/org.bndtools.help/docs/heads/testsrc.html b/org.bndtools.help/docs/heads/testsrc.html new file mode 100644 index 0000000000..3ffc3ae9a9 --- /dev/null +++ b/org.bndtools.help/docs/heads/testsrc.html @@ -0,0 +1,19 @@ + + + + +testsrc + + + +

testsrc

+ + + diff --git a/org.bndtools.help/docs/heads/tool.html b/org.bndtools.help/docs/heads/tool.html new file mode 100644 index 0000000000..e5e4de71c1 --- /dev/null +++ b/org.bndtools.help/docs/heads/tool.html @@ -0,0 +1,25 @@ + + + + +Tool STRING + + + +

Tool STRING

+ + +

Tool

+

The Tool header in the bundle manifest indicates the version of bnd that was used to build the bundle. This is automatically set by bnd during the build process and helps with tracking, debugging, and auditing builds.

+

The value is typically in the form:

+
Tool: Bnd-7.0.0
+
+ +

This header is set by bnd and should not be manually changed.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/help.css b/org.bndtools.help/docs/help.css new file mode 100644 index 0000000000..eb2ff3505e --- /dev/null +++ b/org.bndtools.help/docs/help.css @@ -0,0 +1,64 @@ +body { + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; + line-height: 1.6; + margin: 20px 40px; + max-width: 900px; + color: #333; +} +h1, h2, h3, h4 { + color: #2c3e50; +} +h1 { + border-bottom: 2px solid #3498db; + padding-bottom: 10px; +} +h2 { + border-bottom: 1px solid #bdc3c7; + padding-bottom: 5px; +} +a { + color: #3498db; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +code, pre { + font-family: "Courier New", Courier, monospace; + background-color: #f8f8f8; + border: 1px solid #ddd; + border-radius: 3px; +} +code { + padding: 2px 4px; + font-size: 90%; +} +pre { + padding: 10px; + overflow: auto; + font-size: 90%; +} +pre code { + border: none; + padding: 0; +} +table { + border-collapse: collapse; + width: 100%; + margin: 10px 0; +} +th, td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; +} +th { + background-color: #f2f2f2; +} +blockquote { + border-left: 4px solid #3498db; + margin: 0; + padding-left: 20px; + color: #666; +} diff --git a/org.bndtools.help/docs/index.html b/org.bndtools.help/docs/index.html new file mode 100644 index 0000000000..816cbb00fa --- /dev/null +++ b/org.bndtools.help/docs/index.html @@ -0,0 +1,43 @@ + + + + +bnd Documentation + + + +

bnd Documentation

+

bnd is the Swiss army knife of OSGi, used for creating and working with OSGi bundles.

+ +

Bndtools UI Manual

+ + +

User Guide

+ + +

Reference

+ + +

Full bnd documentation: https://bnd.bndtools.org
+Full Bndtools documentation: https://bndtools.org

+ + diff --git a/org.bndtools.help/docs/instructions/augment.html b/org.bndtools.help/docs/instructions/augment.html new file mode 100644 index 0000000000..6982aec45f --- /dev/null +++ b/org.bndtools.help/docs/instructions/augment.html @@ -0,0 +1,64 @@ + + + + +-augment PARAMETER ( ',' PARAMETER ) * + + + +

-augment PARAMETER ( ',' PARAMETER ) *

+ +

Directives

+ + +

The -augment instruction can be used to augment resources in the repositories. Augmenting is adding additional capabilities and requirements. When bnd resolves a project or bndrun file then, it will read this variable (it is a merge property so you can also use additional keys like -augment.xyz) and use it to decorate the repository entries.

+

The key of the PARAMETER is for the bundle symbolic name. It can contain the * wildcard character to match multiple bundles. The bundle symbolic name must be allowed as a value in a filter it is therefore not a globbing expression.

+

The following directives and attribute are architected:

+ +

To augment the repositories during a resolve, bnd will find all bundles that match the bundle symbolic name and fall within the defined range. If no range is given, only the bundle symbolic name will constrain the search. Each found bundle will then be decorated with the capabilities and requirements defined in the capability: and requirement: directive.

+

For example, we need to provide an extender capability to a bundle with the bundle symbolic name com.example.prime.

+
-augment.prime = \
+    com.example.prime; \
+        capability:='osgi.extender; \
+            osgi.extender=osgi.component; \
+            version:Version=1.2'
+
+ +

The capability: and requirement: directives follow all the rules of the Provide-Capability and Require-Capability headers respectively. For the resolver, it is as if these headers were specified in their manifests. There is one exception, the cap: and req: directives also support capabilities from the osgi.wiring.* name spaces.

+

Caveats

+

It should be realized that the augmentation is only used during resolving. These requirements & capabilities are not added to the actual bundles during runtime. The primary purpose is to ensure that the resolve can properly assemble a system; great care should be taken to not create assemblies that cannot be resolved by the framework.

+



+ + diff --git a/org.bndtools.help/docs/instructions/baseline.html b/org.bndtools.help/docs/instructions/baseline.html new file mode 100644 index 0000000000..1f95a5b82f --- /dev/null +++ b/org.bndtools.help/docs/instructions/baseline.html @@ -0,0 +1,35 @@ + + + + +-baseline selector + + + +

-baseline selector

+ + +

Baselining uses the previous revision of a project with a baseline bundle to detect any changes in semantic versioning using the rules of binary compatibility. The -baseline instruction enables baselining for one or more symbolic names, the instruction takes a selector as input. Each bundle that is being build is held against this selector and if it matches then it is baselined. The following example will baseline any bundle whose name starts with com.example..

+
-baseline: com.example.*
+
+ +

By default a bundle's baseline is the revision with the highest version in the repositories. However, the baseline can also be set with a file or version attribute on the selector.

+ +

Detected violations of the semantic versioning are reported as errors.

+

See baselining for more information.

+



+ + diff --git a/org.bndtools.help/docs/instructions/baselinerepo.html b/org.bndtools.help/docs/instructions/baselinerepo.html new file mode 100644 index 0000000000..90f32573a5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/baselinerepo.html @@ -0,0 +1,26 @@ + + + + +-baselinerepo qname + + + +

-baselinerepo qname

+ + +

The default repository for baselining is the release repository. However, this instruction can be set in the workspace to define an alternate repository. The reference qname is the name of the repository.

+
-baselinerepo: Baseline
+
+ +

See baselining for more information.

+



+ + diff --git a/org.bndtools.help/docs/instructions/bnd_driver.html b/org.bndtools.help/docs/instructions/bnd_driver.html new file mode 100644 index 0000000000..8b20c129a0 --- /dev/null +++ b/org.bndtools.help/docs/instructions/bnd_driver.html @@ -0,0 +1,22 @@ + + + + +-bnd-driver + + + +

-bnd-driver

+ + + diff --git a/org.bndtools.help/docs/instructions/builderignore.html b/org.bndtools.help/docs/instructions/builderignore.html new file mode 100644 index 0000000000..b9408872b0 --- /dev/null +++ b/org.bndtools.help/docs/instructions/builderignore.html @@ -0,0 +1,32 @@ + + + + +-builderignore PATH-SPEC ( ',' PATH-SPEC ) * + + + +

-builderignore PATH-SPEC ( ',' PATH-SPEC ) *

+ + +

Specified paths must be relative to the project. Each path represents a directory in a project to be ignored by the builder when deciding if the bundles of the project need to be built. This is processed for workspace model builds by the Bndtools builder in Eclipse and the Bnd Gradle plugin.

+

This can be useful when the workspace is configured to use different output folders for Bndtools in Eclipse and for Gradle. For example:

+
bin: ${if;${driver;gradle};build/classes/java/main;bin}
+testbin: ${if;${driver;gradle};build/classes/java/test;bin_test}
+target-dir: ${if;${driver;gradle};build/libs;generated}
+
+ +

When configuring the workspace to use different output folders for Bndtools in Eclipse and for Gradle, you should also use -builderignore to instruct the builder to ignore the other builder's output folders.

+
-builderignore: ${if;${driver;gradle};bin,bin_test,generated;build}
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/buildpath.html b/org.bndtools.help/docs/instructions/buildpath.html new file mode 100644 index 0000000000..b3e0f2dfde --- /dev/null +++ b/org.bndtools.help/docs/instructions/buildpath.html @@ -0,0 +1,51 @@ + + + + +-buildpath PATH + + + +

-buildpath PATH

+ +

Directives

+ + +

The -buildpath instruction is the main mechanism to add build-time dependencies to a project. A dependency is either another project in the workspace, or a bundle in a repository. The -buildpath is only used during compile and build time; it is never used to run projects. Because -buildpath dependencies are only used compile time it's recommended to add bundles containing only APIs; you don't need bundles containing implementations.

+

Examples

+

An example of the -buildpath could be the following, where three dependencies are defined:

+
-buildpath: \
+ some.other.workspace.project;version=project,\
+ osgi.core;version=4.3.1,\
+ osgi.cmpn;version=4.3.1
+
+ +

See Also

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/buildrepo.html b/org.bndtools.help/docs/instructions/buildrepo.html new file mode 100644 index 0000000000..85eea32570 --- /dev/null +++ b/org.bndtools.help/docs/instructions/buildrepo.html @@ -0,0 +1,40 @@ + + + + +-buildrepo repo ( ',' repo ) * + + + +

-buildrepo repo ( ',' repo ) *

+ + +

The -buildrepo instruction allows you to automatically release JARs built by a project to one or more specified repositories. After building, if -buildrepo is set, the resulting JARs are placed into the named repositories, which must already exist in the workspace. You can also provide additional properties to control the release context for each repository.

+

The syntax is as follows:

+
 -buildrepo   ::= repo ( ',' repo )*
+ repo           ::= NAME ( ';' NAME ('=' VALUE)? )*
+
+ +

The instruction provides a name of a repository, the repository must exist in the workspace. Any properties added to the name are provided as properties in the release context and thus given to the repository.

+

This feature was inspired by the Maven Bnd Repository. In the Maven development process, projects are installed in the local repository (usually ~/.m2/repository) so they can be shared with other Maven projects. Setting the -buildrepo to a Maven repository will allow a bnd workspace to participate in this process on equal footing. Every time the project is build, all its JARs are installed in the associated Maven repository.

+

For example:

+
-plugin.maven  \
+    aQute.bnd.repository.maven.provider.MavenBndRepository; \
+    name=Local
+
+-buildrepo: Local
+
+ +

The install process is taking place in-line with the build process. It is therefore recommended to only use this for local (i.e. file system based) installs.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/buildtool.html b/org.bndtools.help/docs/instructions/buildtool.html new file mode 100644 index 0000000000..e833ea4831 --- /dev/null +++ b/org.bndtools.help/docs/instructions/buildtool.html @@ -0,0 +1,113 @@ + + + + +-buildtool toolspec (EXPERIMENTAL!) + + + +

-buildtool toolspec (EXPERIMENTAL!)

+ + +

In many projects, the workspace carries the files to build it with an external tool. Gradle is the most +popular but it is also possible to use other tools. An advantage of the workspace is that there are +no specific setups required, the workspace contains all the information needed to build. For example, +the bnd command line can build it. Tools are generally used to provide additional tasks.

+

The setup files of the build tool therefore tend to be dead weight. Dead weight, that frequently needs +overlapping properties with the bnd workspace. Since the tools tend get updated frequently, there are +many software engineering advantages in installing the build tool before the project is being built. It +also makes it easier to maintain many different workspace, they no longer need to be updated when a +new release becomes available. Only the workspace cnf/build.bnd needs to be maintained.

+

Github Actions

+

TBD: a github action that will run the bnd command is foreseen

+

-buildtool instruction

+

The -buildtool instruction provides the information for the bnd command line tool to install a +build tool template from the net. It has the following attributes:

+ +

If it is not a version, it can be: + * url – The key is interpreted as a URL to a template zip file. + * file – The key is interpreted to a file local to the root of the workspace +* * – Any other attributes will be expanded in a properties file

+

Template

+

The template zip must contain a tool.bnd file. This file describes how the template should be installed. This file +can be anywhere in the zip hierarchy, its parent directory is the root. Only files from the root will be copied.

+

The tool.bnd file must contain a -tool instruction.

+
-tool \
+    .*;tool.bnd;skip=true, \
+    gradle.properties;macro=true,\
+    gradlew;exec=true, \
+    *
+
+ +

This is a normal instructions. The keys are matched against the file names relative from the root. The first matching +instruction, provides the instructions how to process the file. The following attributes are available.

+ +

The attributes must have a value, this value is ignored.

+

Example

+

We want to use Gradle 7.3 with bnd 6.1.0. We therefore add the following to the bnd workspace cnf/build file:

+
-buildtool \
+    gradle; version=7.3.0; \
+    bnd_version = 6.1.0
+    bnd_snapshot=https://bndtools.jfrog.io/bndtools/libs-snapshot-local
+
+ +

To install the tool, you can execute the bnd command buildtool:

+
$ bnd buildtool --force
+
+ +

This will download the sources at https://github.com/bndtools/workspace.tool.gradle/archive/refs/heads/7.3.0.zip. The zip file +looks something like:

+
workspace.tool.gradle/
+    tool.bnd
+    gradle/
+        wrapper/
+            gradle-wrapper.jar
+            gradle-wrapper.properties
+    gradle.properties
+    settings.gradle
+    gradlew.bat
+    gradlew
+    .gitignore
+
+ +

The tool.bnd looks like:

+
-tool \
+    .*;tool.bnd;skip=true, \
+    gradle.properties;macro=true,\
+    gradlew;exec=true, \
+    *
+
+ +

It should be clear that the gradle.properties is expanded. After the files are copied, it looks like:

+
# Appended by tool manager at 2021-12-02T14:40:55.660843Z
+version = url
+bnd_version = 6.1.0
+bnd_snapshots = https://bndtools.jfrog.io/bndtools/libs-snapshot-local
+
+ +

After the command has finished, the gradle command can be executed

+
$ ./gradlew --parallel clean build
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/bumppolicy.html b/org.bndtools.help/docs/instructions/bumppolicy.html new file mode 100644 index 0000000000..e6b128d15a --- /dev/null +++ b/org.bndtools.help/docs/instructions/bumppolicy.html @@ -0,0 +1,32 @@ + + + + +-bumppolicy + + + +

-bumppolicy

+ + +

The bump command increases the versions in a bnd project. By default, it will use a compatible policy. A compatible to increment the minor part of the version and reset the micro part. The major part will remain the same. Using the versionmask syntax this looks like:

+
=+0
+
+ +

The -bumppolicy macro can override this default. For example, the following instruction sets the policy to make only major increments.

+
+00
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/bundleannotations.html b/org.bndtools.help/docs/instructions/bundleannotations.html new file mode 100644 index 0000000000..ceb2f50e75 --- /dev/null +++ b/org.bndtools.help/docs/instructions/bundleannotations.html @@ -0,0 +1,25 @@ + + + + +-bundleannotations SELECTORS + + + +

-bundleannotations SELECTORS

+ + +

The -bundleannotations instruction tells bnd which bundle classes, if any, to search for OSGi Bundle annotations. bnd will then process those annotations into manifest headers.

+

The value of this instruction is a comma delimited list of fully qualified class names.

+

The default value of this instruction is *, which means that by default bnd will process all bundle classes looking for Bundle annotations.

+

source

+



+ + diff --git a/org.bndtools.help/docs/instructions/cdiannotations.html b/org.bndtools.help/docs/instructions/cdiannotations.html new file mode 100644 index 0000000000..54c6490ed3 --- /dev/null +++ b/org.bndtools.help/docs/instructions/cdiannotations.html @@ -0,0 +1,92 @@ + + + + +-cdiannotations SELECTORS + + + +

-cdiannotations SELECTORS

+ +

Directives

+ + +

The -cdiannotations instruction tells bnd which bundle classes, if any, to search for OSGI CDI Integration (or plain CDI) annotations. bnd will then process those classes into requirements and capabilities.

+

The value of this instruction is a comma delimited list of globs matching packages or classes by fully qualified name.

+

The default value of this instruction is *, which means that by default bnd will process all bundle classes looking for OSGI CDI Integration (or plain CDI) annotations.

+
discover
+

Each glob may specify the discover attribute which determines the bean discovery mode to apply to matches.

+

The following discover modes are supported:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
discoverBean Discovery Mode
allinclude all classes in the bundle as CDI beans
annotatedinclude classes annotated with bean defining annotations as CDI beans
annotated_by_bean (default)include classes annotated with org.osgi.service.cdi.annotations.Bean or classes in packages annotated with org.osgi.service.cdi.annotations.Beans as CDI beans. This is the default mode when discover is not specified.
nonedo not include any classes in the bundle as CDI beans
+
-cdiannotations: *;discover=all
+
+ +
noservicecapabilities
+

Each glob may specify the noservicecapabilities attribute which indicates that no service capabilities will be added for matches.

+
-cdiannotations: *;discover=annotated;noservicecapabilities=true
+
+ +
noservicerequirements
+

Each glob may specify the noservicerequirements attribute which indicates that no service requirements will be added for matches.

+
-cdiannotations: *;noservicerequirements=true
+
+ +

source

+



+ + diff --git a/org.bndtools.help/docs/instructions/check.html b/org.bndtools.help/docs/instructions/check.html new file mode 100644 index 0000000000..6824a9b6d9 --- /dev/null +++ b/org.bndtools.help/docs/instructions/check.html @@ -0,0 +1,33 @@ + + + + +-check 'ALL' | ( 'IMPORTS' | 'EXPORTS' ) * + + + +

-check 'ALL' | ( 'IMPORTS' | 'EXPORTS' ) *

+ + +

Adding extra checks to bnd will break existing builds and some people get a tad upset about that. However, some checks are actually really valuable. So this instruction is a contract. New checks that can break build will add additional enums to this list. So in theory builds should not be broken. Currently we have the following values defined

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/classpath.html b/org.bndtools.help/docs/instructions/classpath.html new file mode 100644 index 0000000000..499e2afeb4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/classpath.html @@ -0,0 +1,30 @@ + + + + +-classpath FILE (',' FILE) * + + + +

-classpath FILE (',' FILE) *

+ + +

The -classpath instruction adds class path entries to a bnd file's processing. It contains direct references to JARs through file paths or URLs. Entries on the class path are made available as imports and can be used as private or exported packages.

+
-classpath: jar/foo.jar, jar/bar.jar
+
+ +

If you need to get all JARs in a directory you could use the ${lsa} macro:

+
-classpath: ${lsa;jar/*}
+
+ +

This instruction should only be used when bnd is used in stand alone mode. In project mode (when you have a workspace), the -buildpath defines the actual class path. However, even in project mode any -classpath entries are added to the actual class path.

+



+ + diff --git a/org.bndtools.help/docs/instructions/compression.html b/org.bndtools.help/docs/instructions/compression.html new file mode 100644 index 0000000000..4d891cd668 --- /dev/null +++ b/org.bndtools.help/docs/instructions/compression.html @@ -0,0 +1,48 @@ + + + + +-compression DEFLATE | STORE + + + +

-compression DEFLATE | STORE

+ +

Directives

+ + +

When a Jar is build it has default DEFLATE compression with the default level. Using this instruction you +can override the compression method.

+
-compression: STORE
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/conditionalpackage.html b/org.bndtools.help/docs/instructions/conditionalpackage.html new file mode 100644 index 0000000000..aaa3b6ac80 --- /dev/null +++ b/org.bndtools.help/docs/instructions/conditionalpackage.html @@ -0,0 +1,55 @@ + + + + +-conditionalpackage PACKAGE-SPEC ( ',' PACKAGE-SPEC ) * + + + +

-conditionalpackage PACKAGE-SPEC ( ',' PACKAGE-SPEC ) *

+ + +

The -conditionalpackage instruction implements a feature that is either looked up in awe (when understood) or regarded with disgust. Though one has to be very careful with its use, it is a feature that can significantly reduce runtime dependencies. So what does it do? Well, it copies the content of packages from the current class path into your bundle that:

+ +

The purpose of this instruction is very much the same as static linking. Unix'es have a similar feature with static linking. It addresses the problem of util libraries. Utility libraries are extremely useful because they allow us to create primitives we can use in many places. However, in reality utility libraries are often quite, well let's say, all over the place. As a result utility libraries tend to drag in a lot of transient dependencies that are actually not all needed. As a common example, someone once used a single method from an Apache Commons library and dragged in 20 Mb of dependencies.

+

The purpose therefore of the -conditionalpackage instruction is to pick cohesive packages from a utility library and copy them in the bundle. Any dependencies of those copied packages will also be copied if they match the selectors.

+

The packages that are copied cannot be exported, they must be private. This makes it possible to rely on the exact version that the bundle is compiled against. It also ensures that no information is leaked between bundles when statics are used.

+

The given PACKAGE-SPEC follows the format outlined in Selector.

+

For example:

+
-conditionalpackage: aQute.lib*
+
+ +

will slurp any packages that have a name that matches aQute.lib* (e.g. both aQute.lib and aQute.libg) and are referred to by the current JAR's contents.

+

On the other hand the example:

+
-conditionalpackage: mypackage.example.*
+
+ +

will copy the package mypackage.example and all its sub-packages into the bundle in case they are referred to by the current JAR's contents.

+

Utility Libraries

+

A good example of a suitable library is the aQute.libg project. It is a collection of packages that each implement a single function. This ranges from a Strings class with simple String utilities, all the way to a Trajan graph analyzer and simple fork-join framework. Though some of the packages are dependent on each other, most packages have no dependencies whatsoever.

+

When preparing a library for -conditionalpackage you should take the following into account:

+ +

Objections

+

One objection that is raised against this model is that you copy code. However, this model only copies the binaries, not source code, therefore, there is no real duplication. Yes, they then say, but when there is a bug I need to fix in many places? Well, the bundles will have to be rebuild but that is generally a good idea when a dependency changes. And think about it, that bundle was tested with the buggy code, it is highly unlikely that this bug seriously affects the bundle.

+



+ + diff --git a/org.bndtools.help/docs/instructions/conduit.html b/org.bndtools.help/docs/instructions/conduit.html new file mode 100644 index 0000000000..16c3da1cba --- /dev/null +++ b/org.bndtools.help/docs/instructions/conduit.html @@ -0,0 +1,29 @@ + + + + +-conduit + + + +

-conduit

+ + +

The -conduit instruction allows a Project to act as a conduit to one or more actual JARs on the file system. That is, when the Project is build it will not build those JARs, it just returns them as the result of the project. This can be useful when a Project is moved elsewhere but must still be part of the build because, for example, it needs to be part of the release process.

+
-conduit: jar/foo.jar
+
+ +

Notice that you can use the ${lsa} macro to get the contents of a directory:

+
-conduit: ${lsa;jar/*.jar}
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/connection_settings.html b/org.bndtools.help/docs/instructions/connection_settings.html new file mode 100644 index 0000000000..6374da683c --- /dev/null +++ b/org.bndtools.help/docs/instructions/connection_settings.html @@ -0,0 +1,151 @@ + + + + +-connection-settings + + + +

-connection-settings

+ + +

This chapter discusses the connection settings of bnd that are used when bnd is asked to download or upload a file +from a remote server. The connection settings can provide a userid/password for basic authentication, proxies, and/or +the trust policy for verifying the host name of a TLS/SSL server. These settings can obviously not be part of the workspace +since they are unique to the actual user of the workspace. That is, they need to be stored outside the workspace +in a user accessible area.

+

Since Maven is very popular we've followed the same syntax for settings. The supported elements in this file are +<server> and <proxy>. Other elements are ignored.

+

Finding the Settings

+

The default order in which bnd looks for settings is:

+
`~/.bnd/connection-settings.xml`
+`~/.m2/settings.xml`
+
+ +

If you want to disable the use of default from the workspace then you can use the -connection-settings instruction +in the workspace's cnf/build.bnd file. If you set the instruction to false then it will not look for the aforementioned files.

+
-connection-settings: false
+
+ +

In this setting, you can also list additional files to parse that must be of the same syntax as the Maven settings file. The names +maven and bnd are recognized as ~/.m2/settings.xml and ~/.bnd/connection-settings.xml respectively. For example, if +we first want to look in the home directory in ~/foo/settings.xml and then in the bnd settings, we can set the -connection-settings to:

+
-connection-settings: ~/foo/settings.xml, bnd
+
+ +

In addition, you could also specify the maven settings inline. For example:

+
-connection-settings: \
+   server; \
+       id="http://server"; \
+       username="myUser"; \
+       password=${env;PASSWORD}
+
+ +

Logging

+

You can create a log file specific for the connections by specifying:

+
-connection-log: somefile.txt
+
+ +

This file will contain the detailed trace output. The file given is relative to the working directory.

+

Syntax

+

The settings files have the following XML structure:

+
<settings>
+  <proxies>
+    <proxy>
+    <id/>
+      <active>        'true' | 'false' </active>
+      <protocol>      'http'| 'direct' | 'socks' </protocol>
+      <host>          domain name </host>
+      <port>          port to use </port>
+      <username>      user name to use for the proxy </username>
+      <password>      password to use for the proxy </password>
+      <verify> true | false </verify>
+      <nonProxyHosts> glob ( '|' glob )* </nonProxyHosts>
+    </proxy>
+  </proxies>
+  <servers>
+    <server>
+      <id>default</id>
+        <username>username</username>
+        <password>password</password>
+        <verify> true | false </verify>
+        <trust> comma separated paths to X509 certificates </trust>
+        <maxConcurrentConnections>10</maxConcurrentConnections>
+    </server>
+  </servers>
+</settings>
+
+ +

Any additional elements are ignored.

+

Proxies

+

The purpose of the proxy definitions is to define a communication proxy. We support HTTP and SOCKS proxies. An additional built-in proxy is the DIRECT 'proxy'. Proxies can be authenticated with a username and password.

+

| Tag | Default | Values | Description | +|-----------------------------------------------------------------------------------------------| +| id | default | NAME | Identifies the proxy, must be unique in | +| | | | the list of proxies. | +| active | true | true | false | If this proxy is active | +| protocol | http | socks | http | direct | The proxy protocol to use. | +| host | | domain-name | The domain name or IP address of the proxy host | +| port | | INTEGER | Port number, maybe absent if default | +| | | | port for protocol | +| username | | | User name for authentication to the proxy | +| password | | | Password for authentication to the proxy | +| nonProxyHosts | none | GLOB ('|' GLOB)* | Filter on the destination hosts that should not be proxied |

+

Servers

+

In maven, the servers are identified by an id; when you define a repository you tell which id to use. In bnd this works +slightly different. Instead of using the id we use the id in the settings as a glob expression on the protocol, host name, +and port number. The glob expression must match the scheme, the host and the port if the port is not the default port. +To match the url https://maven2-repository.dev.java.net/, the server component could look like (pay attention to the missing trailing slash):

+
<server>
+    <id>https://*java.net</id>
+    ...
+</server>
+
+ +

The first server that matches the id will provide the parameters.

+

| Tag | Default | Values | Description | +|-----------------------------------------------------------------------------------------------| +| id | | GLOB | A glob expression on the scheme + host + port | +| username | | | User name for authentication to the server | +| password | | | Password for authentication to the server | +| verify | true | false | true | Enable/disable the verification of the host name against a certificate for HTTPS | +| trust | | | Provide paths to certificate that provide trust to the host certificate. The format most of a X.509 certificate file. Normally the extension is .cer | +| maxConcurrentConnections|0 (unlimited)|0.. | Limits the number of parallel connections to a host. Some hosts use the number of concurrent connections as a sign of a denial of service attack. |

+

oAuth2 authentication

+

It also supports Bearer (OAuth2) authentication. If the <server> configuration has only a password and no username, then Bearer authentication is in effect with the password used as the token.

+
-connection-settings: server;id="https://*.server.com";password="oauth2token"
+
+ +

will cause

+
Authorization: Bearer oauth2token
+
+ +

request header to be sent to servers matching the glob https://*.server.com.

+

See https://github.github.com/maven-plugins/site-plugin/authentication.html for an example of a <server> configuration for OAuth2.

+

Commands

+

The bnd command line provides a number of commands to display and verify the settings as well as getting the information from +getting a remote file.

+
$ bnd com
+Available sub-commands:
+
+clear                       -         Clear the cached file that is
+                                     associated with the givenURI 
+info                        -         Show the information used by the
+                                      Http Client to get aremote file 
+settings                    -         Show the bnd -connection-settings
+
+ +

Certificate Authentication

+

Certificate authentication is only suppprted using the Java settings through system properties. Either with -D on the command line +or in the eclipse.ini file or through some other means. In that case, make sure not specify the <trust/> nor <verify/> element +in a connection-settings.xml. The reason is that once you specify those element, the built-in Java mechanism is replaced with bnd code.

+



+ + diff --git a/org.bndtools.help/docs/instructions/consumer_policy.html b/org.bndtools.help/docs/instructions/consumer_policy.html new file mode 100644 index 0000000000..98c433ebfd --- /dev/null +++ b/org.bndtools.help/docs/instructions/consumer_policy.html @@ -0,0 +1,35 @@ + + + + +-consumer-policy VERSION-MASK + + + +

-consumer-policy VERSION-MASK

+ + +

The -consumer-policy instruction defines the semantic versioning policy to be used when a type is a consumer. A consumer is in general a type that is implemented by classes that are just users of the package. In contrast, a provider is the party that is basically responsible for the contract defined in the package. For example, when you implement Event Admin, the org.osgi.service.event package is your responsibility so the types you need to implement like EventAdmin are provider types. (These types are annotated with a @ProviderType annotation.) A casual user of the Event Admin service will be a consumer, the EventHandler type is therefore annotated with a@ConsumerType.

+

The purpose of this distinction is semantic versioning. It turns out that the relation between a consumer and a provider is not symmetric. A provider is tightly bound to a contract while a consumer is expected to have backward compatibility. Virtually any change to the contract requires the provider to adapt while a consumer is in almost all cases protect against changes.

+

This asymmetry has a consequence for the semantic versioning. In the OSGi, the semantics are defined that a micro change does not affect the provider nor the consumer. A minor change affects the provider, and a major change affects both. Therefore, a bundle that implements a provider type must import a range from major.minor.micro ... major.minor+1.0. A bundle that implements a consumer type must import major.minor.micro ... major+1.0.0.

+

In theory, bnd could have hard coded these policies but there are always cases where the policy is just not right. The -consumer-policy specifies the macro to use for calculating the version range. The default definition is:

+
-consumer-policy ${range;[==,+)} 
+-provider-policy ${range;[==,=+)}
+
+ +

The range macro works very much like the version macro. It uses a template to define a change the range/version.

+

The provider and consumer policy are global and this is not very convenient if you want to make an exception just for a specific bundle. For example, a bundle coming from Gavin King's Ceylon. For this reason, you can also specify a policy on an import:

+
Import-Package com.gavinking.*;version="${range;[--,++)}", *
+
+ +

The counterpart of the -consumer-policy is of course the -provider-policy.

+



+ + diff --git a/org.bndtools.help/docs/instructions/contract.html b/org.bndtools.help/docs/instructions/contract.html new file mode 100644 index 0000000000..aa51123d85 --- /dev/null +++ b/org.bndtools.help/docs/instructions/contract.html @@ -0,0 +1,77 @@ + + + + +-contract + + + +

-contract

+ + +

Though the OSGi has a very elegant package version model there are still many that think this is too much work. They do not want to be bothered by the niceties of semantic versions and just want to use, let's say, Servlet 3.0. For those people (seemingly not interested in minimizing dependencies) the OSGi Alliance came up with contracts in OSGi Core, Release 5.0.0. A contract allows you to:

+ +

This very common pattern is called the Capability/Requirement (C/R) model in OSGi, it underlies all of its dependency concepts like Import/Export package and others; it forms the foundation of the OSGi Bundle Repository. If you ever want to know what is happening deep down inside a framework than look at the Wiring API and you see the requirements and capabilities in their most fundamental form.

+

Capabilities declare a set of properties that describe something that a bundle can provide. A Requirement in a bundle has a filter that must match a capability before this bundle can be resolved. To prevent requirements matching completely unrelated capabilities they must both be defined in the same namespace, where the namespace then defines the semantics of the properties. Using the C/R model we were able to describe most of the OSGi dependencies with surprisingly few additional concepts. For a modern OSGi resolver there is very little difference between the Import-Package and Require-Bundle headers.

+

So how do those contracts work? Well, the bundle that provides the API for the contract has a contract capability. What this means is that it provides a Provide-Capability clause in the osgi.contract namespace, for example:

+
# Bundle P:
+Provide-Capability:\
+  osgi.contract;\
+    osgi.contract=Servlet;\
+    uses:="javax.servlet,javax.servlet.http";\
+    version:Version="3.0"
+Export-Package: javax.servlet, javax.servlet.http
+
+ +

This contract defines two properties, the contract name (by convention this is the namespace name as property key) and the version. A bundle that wants to rely on this API can add the following requirement to its manifest:

+
# Bundle R:
+Require-Capability:\
+  osgi.contract;\
+    filter:="(&(osgi.contract=Servlet)(version=3.0))"
+Import-Package: javax.servlet, javax.servlet.http
+
+ +

Experienced OSGi users should have cringed at these versionless packages, cringing becomes a gut-reaction at the sight of versionless packages. However, in this case it actually cannot harm. The previous example will ensure that Bundle P will be the class loader for the Bundle R for packages javax.servlet, javax.servlet.http. The magic is in the uses: directive, if the Require-Capability in bundle R is resolved to the Provide-Capability in bundle P then bundle R must import these packages from bundle P.

+

bnd has support for this. First bnd can make it easier to create the Provide-Capability header since the involved packages are in the Export-Package as well as in the Provide-Capability headers. The do-no-repeat-yourself mantra dictated am ${exports} macro. The ${exports} macro is replaced by the exported packages of the bundle, for example:

+
# Bundle P:
+Provide-Capability:\
+  osgi.contract;\
+    osgi.contract=Servlet;\
+    uses:="${exports}";\
+    version:Version="3.0"
+Export-Package: javax.servlet, javax.servlet.http
+
+ +

Furthermore there is the -define-contract instruction which can be applied in order to define a contract which is not available on the build path.

+

That said, the most extensive help you get from bnd is for requiring contracts. Providing a contract is not so cumbersome, after all you're the provider so you have all the knowledge and the interest in providing metadata. Consuming a contract is less interesting and it is much harder to get the metadata right. In a similar vein, bnd analyzes your classes to find out the dependencies to create the Import-Package statement, doing this by hand is really hard (as other OSGi developing environments can testify!)

+

So to activate the use of contracts, add the -contract instruction:

+
# bnd.bnd:
+-contract: *
+
+ +

This instruction will give bnd permission to scan the build path for contracts, i.e. Provide-Capability clauses in the osgi.contract namespace. These declared contracts cause a corresponding requirement in the bundle when the bundle imports packages listed in the uses clause. In the example with Bundle R, bnd will automatically insert the Require-Capability header and remove any versions on the imported packages.

+

Sometimes the wildcard for the -contract instruction can be used to limit the contracts that are considered. Sometimes you want a specific contract but not others. Other times you want to skip a specific contract. The following example skips the 'Servlet' contract:

+
bnd.bnd:\
+  -contract: !Servlet,*
+
+ +

Note: As of bnd 4.1.0 the default value for the -contract instruction will be * which result in the automatic application of any contracts found at build time.

+

The ContractTest.java provides some examples for people that want to have a deeper understanding.

+

Further Reading

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/define_contract.html b/org.bndtools.help/docs/instructions/define_contract.html new file mode 100644 index 0000000000..97a5e7aebb --- /dev/null +++ b/org.bndtools.help/docs/instructions/define_contract.html @@ -0,0 +1,41 @@ + + + + +-define-contract + + + +

-define-contract

+ + +

Used in conjunction with the -contract instruction,-define-contract can be applied in order to define a contract which is not available on the build path (i.e. compile class path).

+

The contract specification is exactly the same syntax used in the Provide-Capability header.

+
-define-contract:\
+  osgi.contract;\
+    osgi.contract=JavaServlet;\
+    uses:="javax.servlet,javax.servlet.annotation,javax.servlet.descriptor,javax.servlet.http";\
+    version:Version="3.0"
+
+ +

Now if the current bundle imports packages declared in the uses directive of the defined contract above, they will be imported without a package version, and a contract requirement will be added exactly as if there had been a contract on the build path.

+

Note the -contract instruction defaults to * (all contracts) and so it can be omitted when using the -define-contract instruction.

+

Further Reading

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/dependson.html b/org.bndtools.help/docs/instructions/dependson.html new file mode 100644 index 0000000000..8a7ed3f6b6 --- /dev/null +++ b/org.bndtools.help/docs/instructions/dependson.html @@ -0,0 +1,31 @@ + + + + +-dependson SELECTORS + + + +

-dependson SELECTORS

+ + +

Projects referenced by -buildpath are always built first but sometimes +you need to specify projects to be build first which are not referenced by -buildpath. +You can specify those additional projects using -dependson.

+

Example

+
-dependson: projA, projB
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/deploy.html b/org.bndtools.help/docs/instructions/deploy.html new file mode 100644 index 0000000000..1f0b39f038 --- /dev/null +++ b/org.bndtools.help/docs/instructions/deploy.html @@ -0,0 +1,28 @@ + + + + +-deploy + + + +

-deploy

+ + +

The -deploy instruction is used to deploy the current project to a repository using deploy plugins, such as the MavenDeploy plugin. When this instruction is set, bnd will attempt to deploy the project's build outputs to the specified repositories.

+

You must specify which repositories to deploy to using the appropriate configuration. If no repositories are set, deployment will not occur and a warning will be issued. This instruction is typically used in conjunction with plugins that handle the actual deployment process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/deployrepo.html b/org.bndtools.help/docs/instructions/deployrepo.html new file mode 100644 index 0000000000..9c37e9a2f6 --- /dev/null +++ b/org.bndtools.help/docs/instructions/deployrepo.html @@ -0,0 +1,29 @@ + + + + +-deployrepo + + + +

-deployrepo

+ + +

The -deployrepo instruction is used to deploy a bundle (JAR file) to a specific repository using deploy plugins, such as the MavenDeploy plugin. You can specify the repository by name, and the bundle will be uploaded to that repository if it supports write operations.

+

If no repository name is provided, the first writable repository found will be used. If no suitable repository is found, deployment will fail with an error. This instruction is typically used in conjunction with plugins that handle the actual deployment process.

+

Note: This feature may require additional configuration and plugin support to work as intended.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/diffignore.html b/org.bndtools.help/docs/instructions/diffignore.html new file mode 100644 index 0000000000..347d2ce677 --- /dev/null +++ b/org.bndtools.help/docs/instructions/diffignore.html @@ -0,0 +1,27 @@ + + + + +-diffignore SELECTORS + + + +

-diffignore SELECTORS

+ + +

You can use the -diffignore instruction to specify manifest header names +and resource paths to ignore during baseline comparison.

+

Example

+
-diffignore: com/foo/xyz.properties, Some-Manifest-Header
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/diffpackages.html b/org.bndtools.help/docs/instructions/diffpackages.html new file mode 100644 index 0000000000..d243efee6b --- /dev/null +++ b/org.bndtools.help/docs/instructions/diffpackages.html @@ -0,0 +1,41 @@ + + + + +-diffpackages SELECTORS + + + +

-diffpackages SELECTORS

+ + +

You can use the -diffpackages instruction to specify the names of exported packages +to be baseline compared. The default is all exported packages.

+

Attributes

+

The following attributes can be specified on each package selector:

+

threshold

+

Specifies the minimum change level that should be reported. Valid values are MICRO, MINOR, or MAJOR. Changes below this threshold will be ignored during baselining.

+

Example:

+
-diffpackages: *;threshold=MAJOR
+
+ +

This will only report MAJOR changes and ignore MINOR and MICRO changes.

+

Examples

+

Exclude internal packages from baselining:

+
-diffpackages: !*.internal.*, *
+
+ +

Set threshold for changes:

+
-diffpackages: *;threshold=MINOR
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/digests.html b/org.bndtools.help/docs/instructions/digests.html new file mode 100644 index 0000000000..d3a5d66e36 --- /dev/null +++ b/org.bndtools.help/docs/instructions/digests.html @@ -0,0 +1,25 @@ + + + + +-digests DIGEST ( ',' DIGEST ) * + + + +

-digests DIGEST ( ',' DIGEST ) *

+ + +

The -digests instruction allows you to specify which digest (checksum) algorithms should be used when generating JAR files. You can provide a comma-separated list of algorithms, such as SHA-1, MD-5, or others supported by your environment.

+

By default, if no value is specified, both SHA-1 and MD-5 are used. Setting this instruction ensures that the generated JAR includes the specified digests, which can be useful for verifying file integrity or meeting repository requirements.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/distro.html b/org.bndtools.help/docs/instructions/distro.html new file mode 100644 index 0000000000..11217f3790 --- /dev/null +++ b/org.bndtools.help/docs/instructions/distro.html @@ -0,0 +1,28 @@ + + + + +-distro REPO (',' REPO) + + + +

-distro REPO (',' REPO)

+ + +

The -distro instruction is used in the case that your application must run in a host environment, for example Karaf. In such cases it is not possible to calculate the system capabilities from the framework and the run path. Each of these host environments has a specific set of capabilities that should be used as input to the resolver.

+

The -distro capability has the same syntax as the -runpath, a list of bundle specifications. The resolver will parse these bundles and treat their capabilities specified with the Provide-Capability header in their Manifest as the system capabilities. These files can be generated manually. However, the bnd command line tool can create a distro bundle using the remote agent.

+

When the -distro is present in the bndrun file it overrides any other definition that are used to derive capabilities. If additional capabilities are needed the -runprovidedcapabilities should be used.

+

For example:

+
-distro: karaf-4.1.jar;version=file
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/donotcopy.html b/org.bndtools.help/docs/instructions/donotcopy.html new file mode 100644 index 0000000000..a411a5ac7d --- /dev/null +++ b/org.bndtools.help/docs/instructions/donotcopy.html @@ -0,0 +1,28 @@ + + + + +-donotcopy + + + +

-donotcopy

+ + +

When -includeresource copies files from another JAR or the file system it will look at the -donotcopy +instruction. This instruction is a single regular expression. Any resource that is copied is matched +against this list. If there is a match, then the file is ignored.

+

For example (and also the defaults)

+
-donotcopy: CVS|\\.svn|\\.git|\\.DS_Store|\\.gitignore
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/dsannotations.html b/org.bndtools.help/docs/instructions/dsannotations.html new file mode 100644 index 0000000000..6c10a3efae --- /dev/null +++ b/org.bndtools.help/docs/instructions/dsannotations.html @@ -0,0 +1,30 @@ + + + + +-dsannotations SELECTORS + + + +

-dsannotations SELECTORS

+ + +

The -dsannotations instruction tells bnd which classes in your bundle should be scanned for Declarative Services (DS) annotations. bnd will process these classes and generate the necessary DS XML descriptors automatically.

+

You provide a comma-separated list of fully qualified class names or use * to process all classes. This makes it easy to enable DS annotation processing for your entire bundle or for specific classes only.

+

You can further configure DS annotation processing using the -dsannotations-options instruction.

+

Component Class Requirements

+

When bnd processes DS annotations, it validates that component classes meet the DS specification requirements. Starting with bnd 7.3.0, component classes must have either a public no-argument constructor or a public @Activate-annotated constructor. Inner classes must be declared as static.

+

If validation fails, bnd will generate an error and stop the build. See Component Class Requirements for detailed requirements and examples.

+

source

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/dsannotations_options.html b/org.bndtools.help/docs/instructions/dsannotations_options.html new file mode 100644 index 0000000000..1d877d054c --- /dev/null +++ b/org.bndtools.help/docs/instructions/dsannotations_options.html @@ -0,0 +1,64 @@ + + + + +-dsannotations-options SELECTORS + + + +

-dsannotations-options SELECTORS

+ + +

The -dsannotations-options instruction configures how DS component annotations are processed and what metadata is generated.

+
-dsannotations-options: version;minimum=1.2.0;maximum=1.3.0
+
+ +

The example above, will restrict the use of OSGi DS annotations to minimum 1.2.0 and maximum 1.3.0 version. The version number denotes that the users are free to use any version equal to or higher than 1.2.0 but less than or equal to 1.3.0, provided that the users have the DS annotations included on the build path.

+

The following options are supported:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
option
inherituse DS annotations found in the class hierarchy of the component class. WARNING: Annotations are not inherited from the component's super classes by default. The problem is that super classes from imported packages may be different at runtime than they were at build time. So it is always best to declare your annotations on the actual component class.
felixExtensionsenable features proprietary to Apache Felix SCR
extenderadd the osgi.extender=osgi.component requirement to the manifest
nocapabilitiesdo not add osgi.service capabilities to the manifest
norequirementsdo not add osgi.service requirements to the manifest
versionset the minimum and/or maximum version of the osgi.extender=osgi.component requirement added to the manifest
+



+ + diff --git a/org.bndtools.help/docs/instructions/eeprofile.html b/org.bndtools.help/docs/instructions/eeprofile.html new file mode 100644 index 0000000000..6899b5dfe1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/eeprofile.html @@ -0,0 +1,29 @@ + + + + +-eeprofile 'auto' | PROFILE + + + + +

-eeprofile 'auto' | PROFILE +

+ + +

The -eeprofile instruction allows you to control which Java 8 (or later) profile is used for your project. A profile is a set of Java packages that enables the Java Virtual Machine to be delivered in smaller, more targeted versions.

+

You can set -eeprofile to auto to let bnd automatically determine the appropriate profile based on the packages your project uses. Alternatively, you can specify one or more profiles explicitly by name. If your project references packages outside the selected profiles, no profile will be set.

+

This instruction is useful for optimizing your bundle for specific Java environments and ensuring compatibility with the intended runtime profile.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/executable.html b/org.bndtools.help/docs/instructions/executable.html new file mode 100644 index 0000000000..95f52eb45e --- /dev/null +++ b/org.bndtools.help/docs/instructions/executable.html @@ -0,0 +1,134 @@ + + + + +-executable ( rejar= STORE | DEFLATE ) ( ',' strip= matcher ( ',' matcher )* ) ( ',' location= FORMAT ) + + + +

-executable ( rejar= STORE | DEFLATE ) ( ',' strip= matcher ( ',' matcher )* ) ( ',' location= FORMAT )

+ +

Directives

+ + +

Location

+

Bundles are stored in a jar directory in the executable JAR. The name in this directory is by default the file name in the repository. This filename is, however, also used by the launcher as the location. This implies that if the file name contains the version, a new location is created when the version changes. This ends up with too many duplicates quickly. This is only a problem when you keep the storage area.

+

The location option in the -executable instructions can provide a printf format to calculate a location based on the Bundle-SymbolicName and Bundle-Version.

+

For example:

+
-executable: location='${@bsn}-${version;=;${@version}}'
+
+ +

This format will create locations where a bundle will overwrite when the major part of the version is the same. I.e. com.example.foo-1. I.e., it will allow multiple bundles that are semantically incompatible but compatible bundles overwrite each other.

+

Compression

+

When an executable JAR is created by the Project Launcher the compression is controlled with the -compression +instruction. However, this über JAR contains bundles and JARs for the run path. Since executable JARs are sometimes used in +embedded environments it is important that they are small and the code can loaded quickly. It is difficult to +have defaults for this since there are many aspects:

+ +

In such a complex trade off there are no singular answers. This -executable instruction allows therefore to +set the different options and then benchmark the result.

+

Hints

+

Experience shows that the size can be minimized by rejarring the inner bundles and JARs with the STORE compression +but using DEFLATE for the outer/über JAR. This decreases the size because the compression algorithm then works on +all class files of all bundles. This is much more efficient for the DEFLATE algorithm then compressing each class file +on its own. Gains seen are 20%-30%.

+

rejar = (DEFLATE|STORE)

+

The rejar option in the -executable instruction can take the values STORE or DEFLATE. This will open +the embedded JARs and write them in the given compression in the über JAR.

+

For example:

+
-executable: rejar=STORE
+
+ +

The default is to not touch the bundle.

+

strip= matcher ( ',' matcher )*

+

The strip option can be used to strip resources from JARs embedded in the execetable. Its parameter can define +a list of two GLOBs. The first GLOB must match the file name of the resource and the second GLOB must match the +resource name in the bundle. GLOBs are separated with a colon (':'). If no colon is present then the first GLOB +is assumed to be the wildcard GLOB that matches anything.

+

Syntax:

+
strip   ::=  matcher ( ',' matcher )*
+matcher ::=  ( GLOB ':' ) GLOB
+
+ +

Some examples:

+ +

Note hat if you combine multiple GLOBs then you must separate them with a comma (',') and that implies the total must be +quoted with single or double quotes. If it is a single GLOB (pair) then quoting is optional. For example:

+
-executable: rejar=STORE, strip='OSGI-OPT,*.map'
+
+ +

The default is to not strip anything.

+

Signed Bundles

+

Rejarring and stripping should work for unsigned bundles since the signatures should not be affected by the +compression algorithms used.

+



+ + diff --git a/org.bndtools.help/docs/instructions/export.html b/org.bndtools.help/docs/instructions/export.html new file mode 100644 index 0000000000..68a114ca28 --- /dev/null +++ b/org.bndtools.help/docs/instructions/export.html @@ -0,0 +1,63 @@ + + + + +-export PATH ( ';' PARAMETER )* ( ',' PATH ( ';' PARAMETER )* )* + + + +

-export PATH ( ';' PARAMETER )* ( ',' PATH ( ';' PARAMETER )* )*

+ + +

The -export instruction can be used to export a bndrun or bnd file to an executable JAR during the build process. In contrast to the export functions, this -export instruction is supported in all drivers, including Eclipse. It can be used to continously build executable JARs or other supported exporters. It can only be used in the top level bnd.bnd file.

+

The format of the -export instruction is:

+
-export     ::= filespec ( ',' filespec )*
+filespec    ::= path (';' PARAMATER )*
+
+ +

The path is either a relative path in the project directory or it is a wildcard specification using globs. All files in the project directory are selected. In general, these should be bnd or bndrun files.

+

The following attributes are architected:

+ +

The -exporttype can be used to set some default attributes for a specific type.

+

Exporters

+

The Exporters use a plugin mechanism and therefore the list is not closed. The following exporters are supported by bnd out of the box:

+ +

Example

+

For example:

+
-export: \
+    foo.bndrun; \
+        -profile=debug; \
+        -runkeep=true; \
+        name = "foo.jar, \
+    bar.bndrun
+
+ +

Backward Compatibility

+

If the filespec clause does not set the type nor the name then it is assumed the backward compatible mode is required. This will set the output name to the file name with a .jar extension and it will set the bundle symbolic name.

+



+ + diff --git a/org.bndtools.help/docs/instructions/export_apiguardian.html b/org.bndtools.help/docs/instructions/export_apiguardian.html new file mode 100644 index 0000000000..8acd64c708 --- /dev/null +++ b/org.bndtools.help/docs/instructions/export_apiguardian.html @@ -0,0 +1,43 @@ + + + + +-export-apiguardian PACKAGE-SPEC, ( ',' PACKAGE-SPEC )* + + + +

-export-apiguardian PACKAGE-SPEC, ( ',' PACKAGE-SPEC )*

+ + +

API Guardian is a

+
+

Library that provides the @API annotation that is used to annotate public types, methods, constructors, and fields within a framework or application in order to publish their status and level of stability and to indicate how they are intended to be used by consumers of the API.

+
+

The heuristic used by bnd to determine which packages to export is as follows:

+ +

Examples

+

Export all packages annotated with @API using version 1.2.3:

+
-export-apiguardian: *;version="1.2.3"
+
+ +

Export only packages annotated with @API named com.acme.foo.* but not com.acme.foo.bar.*

+
-export-apiguardian:\
+    !com.acme.foo.bar.*,\
+    com.acme.foo.*
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/exportcontents.html b/org.bndtools.help/docs/instructions/exportcontents.html new file mode 100644 index 0000000000..ff60409ca7 --- /dev/null +++ b/org.bndtools.help/docs/instructions/exportcontents.html @@ -0,0 +1,37 @@ + + + + +-exportcontents PACKAGE-SPEC, ( ',' PACKAGE-SPEC )* + + + +

-exportcontents PACKAGE-SPEC, ( ',' PACKAGE-SPEC )*

+ + +

Exports the given packages but does not try to include them from the class path. The packages should be loaded with alternative means. The syntax is similar to the Export-Package header.

+

Export-Package = -includepackage + -exportcontents (source).

+

That is, Export-Package will add packages to the bundle, perhaps from (other) .jar files on the classpath, and also add those packages to the Export-Package manifest header.

+

-exportcontents will only add packages which are already part of the bundle to the Export-Package manifest header.

+
-exportcontents: com.example.api;
+
+ +

See the packages macro, which is useful in combination with -exportcontents.

+

Note: By default bnd automatically calculates Import-Package references for exported packages. This is called package substitution +You can use the -noimport:=true directive which instructs bnd to not calculate Import-Package references for exported packages.

+

Example:

+

` +-exportcontents: com.*;-noimport:=true

+

With the -nosubstitution: true instruction, this substitution behavior can be disabled globally.

+

Use Cases

+

So -exportcontent is appropriate for Maven and Gradle (non-Bnd workspace) builds where the content of the bundle is being managed by normal Maven or Gradle means.

+



+ + diff --git a/org.bndtools.help/docs/instructions/exportreport.html b/org.bndtools.help/docs/instructions/exportreport.html new file mode 100644 index 0000000000..d28e954c92 --- /dev/null +++ b/org.bndtools.help/docs/instructions/exportreport.html @@ -0,0 +1,112 @@ + + + + +-exportreport report-def ( ',' report-def )* + + + +

-exportreport report-def ( ',' report-def )*

+ + +

The purpose of the -exportreport instruction is to configure a list of reports of the current state of the workspace and/or its projects, which can then be exported by the build tool. The primary usage is to automate the documentation of projects. An introduction to this feature can be found here.

+

See -exportreport command documentation to export the reports.

+

Syntax

+
-exportreport    ::= report-def ( ',' report-def ) *
+report-def       ::= path ( ';' option ) *
+option           ::= scope | template | templateType | parameters | locale | configName
+scope            ::= 'scope' '=' ( 'workspace' | 'project' | EXTENSION )
+template         ::= 'template' '=' ( path | url )
+templateType     ::= 'templateType' '=' ( 'xslt' | 'twig' | EXTENSION )
+parameters       ::= 'parameters' '=' '"' parameter ( ',' parameter )* '"'
+locale           ::= 'locale' '=' <language> ( '-' <country> ( '-' <variant> )? )?
+configName       ::= 'configName' '=' extended
+
+ +

This is a merged instruction.

+

Example

+

The most simple configuration is to generate a file which will contain all the OSGI headers, metatypes declarations, declarative services, ... of a bundle built by a project:

+

bnb.bnd

+
-exportreport: metadata.json
+
+ +

an XML file can also be generated

+
-exportreport: metadata.xml
+
+ +

Advanced usage

+

Targeting the data source

+

The scope attribute allows to define all the reports in a common place and to target the source of the extracted data. In Bnd, the two possible values are workspace and project but other tools (such as Maven) could define their own scopes.

+

For example, the following configuration will generate a report at the workspace root, which will aggregate data of all the projects, and one report per project:

+

build.bnd

+
-exportreport: \
+   ${workspace}/jekyll_metadata.json;scope=workspace, \
+   metadata.json;scope=project
+
+ +

Transformation

+

The template attribute allows to specify a path or an URL to a template file. In Bnd, two template types are accepted: XSLT and TWIG.

+

For example, a template can be used to generate a markdown file:

+

bnd.bnd

+
-exportreport: readme.md;template=/home/me/templates/readme.twig
+
+ +

If the extension file is missing, the templateType attribute can be used to indicate the template type:

+

bnd.bnd

+
-exportreport: webpage.html;template=http:<...>/f57ge56a;templateType=xslt
+
+ +

If the template file needs to be parametrized, the parameters attribute can be used to provide a list of parameters and their values:

+

bnd.bnd

+
-exportreport: \
+   webpage.html; \
+     template=<...>/template.xslt; \
+     parameters="oneKey=<path to other template>,otherKey=api-bundle"
+
+ +
+

If a file with the same name as the exported report but with a template file extension is found in the same folder as the exported report, this file will be used to transform the report instead of the optionally defined template attribute. This allows to quickly customize a report without redefining an inherited instruction.

+
+

Internationalisation

+

The locale attribute can be used to extract the data for a specific locale. For example, if a bundle defines some metatype description in French:

+

bnd.bnd

+
-exportreport: report.json;locale=fr-FR
+
+ +

Customization of the Report Content

+

In some case, it may be necessary to control what data should be present in the report, for example if you use external plugins to contribute to the extraction and aggregation phase. For this you can use the -reportconfig instruction to create named configuration of reports.

+

With the configName attribute you can reference the configuration name that will be used to extract and aggregate the data of the report.

+

See the -reportconfig instruction documentation for more information.

+

Case of Sub-Projects

+

Reports are generated from workspaces and projects. However, in case of sub-projects, it may be necessary to generate a file for each built bundle and to know what bundle must be process by the template engine. For this, you can define a paramater in your template file and provide a different value for each bundle, for example:

+

build.bnd

+
-exportreport: \
+   readme.md;template=<...>/readme.twig;scope=project
+
+ +

bnd.bnd

+
-exportreport.sub: \
+   mybundle.api.md; \
+     template=<...>/readme.twig; \
+     parameters="currentBundle=mybundle.api", \
+   mybundle.provider.md; \
+     template=<...>/readme.twig; \
+     parameters="currentBundle=mybundle.provider"
+
+ +

For this specific multi-project, this will generate three files:

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/exporttype.html b/org.bndtools.help/docs/instructions/exporttype.html new file mode 100644 index 0000000000..c6796328a7 --- /dev/null +++ b/org.bndtools.help/docs/instructions/exporttype.html @@ -0,0 +1,19 @@ + + + + +-exporttype + + + +

-exporttype

+ + + diff --git a/org.bndtools.help/docs/instructions/extension.html b/org.bndtools.help/docs/instructions/extension.html new file mode 100644 index 0000000000..91407a0961 --- /dev/null +++ b/org.bndtools.help/docs/instructions/extension.html @@ -0,0 +1,25 @@ + + + + +-extension + + + +

-extension

+ + +

-extension

+

The -extension instruction allows you to specify a plugin that is loaded from a URL. The plugin provides a header used to instantiate the extension. This is useful for extending bnd's functionality with custom plugins or features that are not included by default.

+

Example:

+
-extension: com.example.MyExtension;version=1.0.0
+
+ +

The extension will be downloaded and loaded as part of the build process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/failok.html b/org.bndtools.help/docs/instructions/failok.html new file mode 100644 index 0000000000..de185de471 --- /dev/null +++ b/org.bndtools.help/docs/instructions/failok.html @@ -0,0 +1,33 @@ + + + + +-failok ('true' | 'false')? + + + +

-failok ('true' | 'false')?

+ + +

-failok

+

The -failok instruction allows the build to continue even if errors occur. When set to true, bnd will ignore any errors during the build process and assume everything went fine. This can be useful for experimental or non-critical builds, but should be used with caution as it may hide real problems.

+

Example:

+
-failok: true
+
+ +

By default, this option is not set and build errors will cause the process to fail.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/fixupmessages.html b/org.bndtools.help/docs/instructions/fixupmessages.html new file mode 100644 index 0000000000..b40a812fb9 --- /dev/null +++ b/org.bndtools.help/docs/instructions/fixupmessages.html @@ -0,0 +1,82 @@ + + + + +-fixupmessages SELECTOR ( ';' ( is | replace | restrict ) )* ... + + + +

-fixupmessages SELECTOR ( ';' ( is | replace | restrict ) )* ...

+ + +

The -fixupmessages instruction is intended to fixup the errors and warnings. It allows you to remove errors and/or warnings, turn errors into warnings, and turn warnings into errors. With this instruction you can fail a build based on a warning or succeed a build that runs into errors.

+

The default of this instruction is to list a number of patterns. Any error or warning that matches this pattern is then removed. The following example will remove any error/warning that matches 'some error', 'another error', or 'and yet another error'.

+
-fixupmessages:  \
+    some error, 
+    another error, 
+    and yet another error
+
+ +

The pattern is a SELECTOR, which makes it possible to do case insensitive matches, wildcards, literals, etc.

+

Syntax

+

The basic format of -fixupmessages is:

+
-fixupmessages ::= fixup ( ',' fixup ) *
+fixup          ::= SELECTOR directive *
+directive      ::= ';' ( restrict | is | replace )
+restrict       ::= 'restrict:=' ( 'error' | 'warning' )
+is             ::= 'is:=' ( 'ignore' | 'error' | 'warning' )
+replace        ::= 'replace:=' <<text>>
+
+ +

The value of a fixup clause is a globbing expression.

+

Directives

+

The following directives are supported:

+ +

The -fixupmessages instruction is a merged property. This means that you can define it in many different places like for example in a file in cnf/ext. Just put an extension on the instruction. For example:

+
-fixupmessages.one: 'Some error'
+-fixupmessages.two: 'Another error'
+
+ +

Examples

+
# Turn an error into a warning
+-fixupmessages:
+  'Invalid character'; \
+    restrict:=error;
+    is:=warning
+
+# Replace a message
+-fixupmessages: \
+  "split";replace:=broken
+
+# Ignore case by appending :i
+-fixupmessages: \
+  "case insensitive:i"
+
+# Wildcards
+-fixupmessages: \
+  "prefix*suffix"
+
+# Turn properties parser messages into warnings
+-fixupmessages.parser: \
+  "Invalid character in properties"; \
+  "No value specified for key"; \
+  "Invalid property key"; \
+  "Invalid unicode string"; \
+  "Found \\<whitespace>";
+    is:=warning
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/generate.html b/org.bndtools.help/docs/instructions/generate.html new file mode 100644 index 0000000000..c4725d2fd1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/generate.html @@ -0,0 +1,122 @@ + + + + +-generate srcs ';output=' DIR ( ';' ( system | generate | classpath))* ... + + + +

-generate srcs ';output=' DIR ( ';' ( system | generate | classpath))* ...

+ + +

Virtually all the work bnd is concerned about happens in generating the JAR file. The key idea is to pull resources in the JAR, instead of the more traditional push model of other builders. This works well, except for generating source code. This generating step must happen before the compiler is called, and the compiler is generally called before bnd becomes active.

+

This -generate instruction specifies the code generating steps that must be executed. Source code can be generated by system commands or the bnd external plugins.

+
-generate   ::=     clause ( ',' clause )*
+clause      ::=     FILESET ';' 'output=' DIR (';' option )*
+src     ::= FILESET
+option      ::=     'system=' STRING
+        |   'generate=' STRING
+        |   'classpath=' PATH
+        |   'workingdir=' FILE
+        |   'clear=' BOOLEAN
+        |   'version=' RANGE
+
+ +

For each clause, the key of the clause is used to establish an Ant File Set, e.g. foo/**.in. This a glob expression with the exception that the double wildcard ('**') indicates to any depth of directories. The output attribute must specify a directory. If the output must be compiled this directory must be on the bnd source path.

+

The output directory will created if it does not exist. It will be cleared of any previous generate results before a run, except if the option clear is set to false. In this case the used Generator needs to deal with the remnants in the directory itself.

+

If any file in the source is older than any file in the target (to any depth), or the target is empty, the clause is considered stale. If the clause is not stale, it is further ignored. If no further options are set on the clause, a warning is generated that some files are out of date.

+

If either a warning or error option is given, these will be executed on the project.

+

If a command STRING is given it is executed as in the ${system} macro. If the command STRING starts with a +minus sign (-) then a failure is not an error, it is reported as warning.

+

The generate option will execute an external plugin or plain JAR with a Main-Class manifest header. The choice is made by looking at the first word in the generate attribute.

+

If this name has a dot in it, like in a fully qualified class name, it is assume that species a class name. (If the name starts with a dot, it will be assume to be a name in the default package.) In this case, the classpath attribute of the instruction can be used to provide additional JARs on the command's classpath. The format of PATH is the standard format for instructions like -buildpath. In this case, you can also set the workingdir to a directory. This directory is specified relative to the project.

+

Without a dot in the name, the name is assumes to be an external plugin name, with the objectClass (service type) of Generator<? extends Options>. External , or Main-Class jars, can come from an external repository or a local workspace project.

+

The generate value is a command line. It can use the standard unix like way of specifying a command. It supports flags (boolean parameters) and parameter that take a value. When this external plugin is executed, it is expected to create files fall within the target, if not, an error is reported. These changed or created files are refreshed in Eclipse.

+

The command line can be broken in different commands with the semicolon (';'), like a unix shell. Redirection of stdin ('<'), stdout ('>', or '1>'), and stderr ('2>') are supported. The path for redirection is relative to the project directory, even if workingdir has been specified.

+

With the version version range attribute it is possible to restrict the candidates if there are multiple versions available. The code will select the highest version if only one is used.

+

Example with an External Plugin

+

Include in the bnd build is a javagen external plugin that is useful to generate Java code based on build information. It uses a template directory with Java files. When the external plugin runs, it will use all these files to write matching Java files in the output directory, in a matching package directory. The input Java files can be prefixed with a properties header:

+
---
+foo: 1
+---
+package foo.bar;
+class Foo {
+    int foo = ${foo};
+}
+
+ +

The optional header is removed and then the remainder of the file is ran through the bnd macro processor.

+

If this example is used, it is necessary to add a new source folder. In Eclipse, this requires adding an entry in the .classpath file, in bnd it requires the modification of the src property.

+
src=${^src},src-gen
+
+ +

Assuming that the input files are in the gen directory, the following can be used to automatically generate the output files based on the input files.

+
-generate:   \
+    gen/**.java; \ 
+        output='src-gen/' ; \ 
+        generate='javagen -o src-gen gen/'
+
+ +

Example with a Main Class JAR

+

JFlex and CUP are popular tools to create lexers and parsers. The JARs are on Maven Central with Main-Class manifest attribute. The JFlex JAR, however, requires the cup_runtime JAR on the classpath.

+

We can directly use these executable JARs with the -generate instruction.

+
-generate: \
+    lex/Foo.lex; \
+        output      = gen-src/ \
+        generate    = `jflex.Main -d lex-gen/ lex/Foo.lex'; \
+        classpath   = 'de.jflex:cup_runtime;version=11b-20160615'
+
+ +

Notice that we use the maven GAV format here to find the cup_runtime because these JARs are unfortunately not bundles.

+

Writing a Command

+

It is possible to create an External Plugin or a Main Class command your in the same workspace as where you apply the command. This makes it easy to develop commands interactively. The easiest way is to make an External Plugin. The support for Main-Class is mostly to support existing JAR.

+

The following is an Generate external plugin that outputs "hello":

+
@ExternalPlugin(name = "hello", objectClass = Generator.class)
+public class Hello implements Generator<HelloOptions> {
+
+    public interface HelloOptions extends Options {
+        boolean upper();
+        String name(String defaultName)
+    }
+
+    public Optional<String> generate(
+        BuildContext context, 
+        HelloOptions options) throws Exception {
+        String hello = "Hello " + options.name("World");
+        if ( options.upper() )
+            hello = hello.toUpperCase();
+
+        System.out.println( hello );
+        return Optional.empty();
+    }
+}
+
+ +

The @ExternalPlugin annotation creates an external plugin capability in the bundle's manifest. The name is the name we can use as the command name. Do not use a name that has dots in it, this will then be confused with a main class command.

+

The Hello class implements Generator<HelloOptions>. This is the type the generate code expects.

+

The type parameter specifies a specification interface. This interface is used to specify the command line. A boolean method is a flag, and any other type is an option. The first character of the method is the name of the flag or option. For example, boolean upper() is a flag and has the -u and --upper. Flags can be combined. For example, if you have a flag -a and -b then you can also use -ab.

+

Options take parameters. For example, a String name() option would be set as -n World. The method on the spec interface can optionally take an argument, this argument is used as default if the option is not used in the command line. The argument type and the return type can be different. For example, if the return type is File, then the parameter type can be String so that the returned File is resolved against the base directory of the build.

+

Options that return File will resolve the input against the project directory. A Set will accept an ant file set specification like gen/**.java.

+

The Options interface specifies a number of additional keys:

+ +

The actual code is in the generate(BuildContext,HelloOptions) method. the Build Context contains useful context information.

+

It is ok to write to the System.out and System.err. The output is captured and can be redirected in the command line in the standard Unix way.

+

The code is expected to return an Optional.empty() when everything is ok. If something is wrong, an actualString can be used to explain the error. Return a non-empty fails the call and the error will be reported.

+

If you the plugin source code is in the same workspace as the project using this plugin, you must make sure that the external plugin project is build before the project that uses it. You can achieve this with -dependson.

+

You can take a look at the JavaGen project in the bnd build to see how an actual external plugin is made.

+



+ + diff --git a/org.bndtools.help/docs/instructions/gestalt.html b/org.bndtools.help/docs/instructions/gestalt.html new file mode 100644 index 0000000000..9e9ed87de1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/gestalt.html @@ -0,0 +1,22 @@ + + + + +-gestalt + + + +

-gestalt

+ + + diff --git a/org.bndtools.help/docs/instructions/groupid.html b/org.bndtools.help/docs/instructions/groupid.html new file mode 100644 index 0000000000..0c36092d90 --- /dev/null +++ b/org.bndtools.help/docs/instructions/groupid.html @@ -0,0 +1,24 @@ + + + + +-groupid groupId + + + +

-groupid groupId

+ + +

The -groupid instruction defines the default Maven groupId to be used when generating POM resources and releasing to the Maven Bnd Repository Plugin.

+

If not specified, the value of -groupid defaults to the Bnd workspace folder name.

+

Also see the -pom and -maven-release instructions.

+



+ + diff --git a/org.bndtools.help/docs/instructions/include.html b/org.bndtools.help/docs/instructions/include.html new file mode 100644 index 0000000000..8a8f9999a9 --- /dev/null +++ b/org.bndtools.help/docs/instructions/include.html @@ -0,0 +1,68 @@ + + + + +-include PATH-SPEC ( ',' PATH-SPEC ) * + + + +

-include PATH-SPEC ( ',' PATH-SPEC ) *

+ + +

Explanation of -include Instruction

+

The -include instruction allows you to include the contents of other files (such as properties or manifest files) into your current configuration. You specify the path or URL of the file to include. The included file's properties will overwrite existing properties by default, unless you use the ~ prefix, which prevents overwriting. If the file or URL does not exist and you use the - prefix, no error will be reported.

+

The -include instruction is processed before any other properties, so it cannot use properties defined later in the same file. However, it can use properties defined by a parent configuration. This makes it possible to share common settings across multiple projects or workspaces.

+

You can use -include as follows:

+
-include: <path or url>
+
+ +

This will read the path or url as a properties or manifest file (if it ends in .MF).

+

It is important to realize that the include is not handled by the parser. +That is, it is not a normal text include. +The properties parser will read all properties in one go and then the Properties object is inspected for the -include instruction. +The paths or URLs in the -include instruction are processed one by one in order. +By default, the properties in the included file overwrite the properties that were set in the same file as the -include instruction. +If a property is already defined and not set to be overwritten (see below), the property will get a namespace assigned. +The namespace will be derived from the filename or the last segment of the URL.

+

The -include instruction is processed before anything else in the properties. +This means the -include instruction cannot use any properties defined in the same properties file to define the include paths. +It can use properties already defined by a parent. +So a Project's bnd.bnd file can have an -include instruction use properties defined in the Workspace (cnf/build.bnd and cnf/ext/*.bnd). +For the Workspace, cnf/build.bnd, -include instruction can only use the default properties of Bnd. +The Workspace cnf/ext/*.bnd files are processed after cnf/build.bnd. +So cnf/ext/*.bnd files can have -include instructions which use properties set in cnf/build.bnd.

+

There are two possible options. The path/URL starts with a:

+ +

Examples

+
# Read an optional file in the user's home directory
+-include -${user.home}/.xyz/base.bnd
+
+# Read a manifest
+-include META-INF/MANIFEST.MF
+
+# Use a URL
+-include https://example.com/foo/bar/setup.bnd
+
+# Read several
+-include first.bnd, second.properties
+
+# Don't overwrite any existing properties (my.prop, will not be overwritten by my.prop in no.overwrite)
+my.prop = don't overwrite
+-include ~no.overwrite
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/includepackage.html b/org.bndtools.help/docs/instructions/includepackage.html new file mode 100644 index 0000000000..34c1268eda --- /dev/null +++ b/org.bndtools.help/docs/instructions/includepackage.html @@ -0,0 +1,42 @@ + + + + +-includepackage PACKAGE-SPEC, ( ',' PACKAGE-SPEC )* + + + +

-includepackage PACKAGE-SPEC, ( ',' PACKAGE-SPEC )*

+ + +

The -includepackage instruction falls in the family of instructions to pull in packages from the current class path. The +instructions lists one of more package specifications that can contain wildcards. Any attributes or directives are +ignored. This instruction only operates during the expand phase of the JAR. It has not further semantics.

+

The primary motivation for this instruction is the use of the @Export annotation. Using that annoation puts +bnd in a bind. A Private-Package should be private and an Export-Package should be exported. Since a bnd file +should always have the final say, the @Export instruction needed an instruction that took in the packages but +that did not put export semantics on it.

+

This instruction is also taken into account when taken the decision to automatically fill up the JAR from the +current project. If this instruction is set (or any other construction instruction) it is assumed that the user +wants to be in control and the instructions are followed. If none of these instructions is set then the JAR is +constructed from the project's output folder.

+

When the packages selected by the -includepackage instructions overlap with either Private-Package or Export-Package +then the Export-Package has the highest priority and then Private-Package. That is, any @Export in a package that is selected +by Export-Package or Private-Package is ignored silently.

+

Notice that an annotation like @Version in a a package like selected can still provide the version if the Export-Package +header for that package provides no version.

+

Example

+

The following example includes all packages from com.example.* except com.example.bar.

+
-includepackage !com.example.bar, com.example.*
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/includeresource.html b/org.bndtools.help/docs/instructions/includeresource.html new file mode 100644 index 0000000000..8567cfb263 --- /dev/null +++ b/org.bndtools.help/docs/instructions/includeresource.html @@ -0,0 +1,256 @@ + + + + +-includeresource iclause + + + +

-includeresource iclause

+ + +

The purpose of -includeresource is to fill the JAR with non-class resources. In general these come from the file system. For example, today it is very common to have these type of resources in src/main/resources. This pattern can easily be simulated by bnd with the -includeresource instruction. However, since in OSGi the packaging is so important the -includeresource contains a number of options to minimize files on disk and speed up things.

+

The syntax of the -includeresource has become quite complex over time:

+
-includeresource ::= iclause ( ',' iclause ) *
+iclause          ::= (unroll | copy) parameter*
+copy             ::= '{' process '}' | process
+process          ::= assignment | source
+assignment       ::= PATH '=' source
+source           ::= ('-')? PATH parameter*
+unroll           ::= '@' (PATH | URL) ( '!/' SELECTOR )?
+parameters       ::= 'flatten:' | 'recursive:' | 'filter:' | `-preprocessmatchers`
+
+ +

In the case of assignment or source, the PATH parameter can point to a file or directory. It is also possible to use the name.ext path of a JAR file on the classpath, that is, ignoring the directory. The source form will place the resource in the target JAR with only the file name, therefore without any path components. That is, including src/a/b.c will result in a resource b.c in the root of the target JAR.

+

If the PATH points to a directory, the directory name itself is not used in the target JAR path. If the resource must be placed in a sub directory of the target jar, use the assignment form. If the file is not found, bnd will traverse the classpath to see of any entry on the classpath matches the given file name (without the directory) and use that when it matches. The inline requires a ZIP or JAR file, which will be completely expanded in the target JAR (except the manifest), unless followed with a file specification. The file specification can be a specific file in the jar or a directory followed by or *. The indicates recursively and the indicates one level. If just a directory name is given, it will mean *.

+

The filter: directive is an optional filter on the resources. This uses the same format as the instructions. Only the file name is verified against this instruction.

+
Include-Resource: @osgi.jar,[=\ =]
+    {LICENSE.txt},[=\ =]
+    acme/Merge.class=src/acme/Merge.class
+
+ +

The -includeresources instruction will be merged with all properties that starts with -includeresources*.

+

Preprocessing

+

A clause contained in curly braces ({ }) are preprocessed. While copying the files are run through the macro processor with the builder providing the properties. In the workspace model, all macros of the project are then available. Well known binary resources (as decided by their extension) are ignored. You can override the extension list with the -preprocessmatchers instruction. This must be a a selector that takes the source file name as the input. The clause can also specify a local -preprocessmatchers. This selector is prepended to the either the default pre process matchers or the set pre process matchers. This allows for the selection or rejection of specific files and/or extensions.

+
-includeresource: {src/main/resources}, {legal=contracts}
+
+ +

Ignoring Missing Sources

+

A source in the clause starting with a - sign will not generare an error when the source in the clause cannot be located. This is very convenient if you specify an global -includeresource instruction in build.bnd. For example, -includeresource.all = -src/main/resources will not complain when a project does not have a src/main/resources directory. Note that the minus sign must be on the source. E.g.

+
`-includeresource.all = {foo=-bar}`, -foo.txt
+
+ +

Rolling

+

There are two variants of the rolling operator @. It can be used to roll up a directory as a zip or jar file, or it can be used to unroll a jar file into its constituents.

+

If the destination is a path of a jar or zip file, like foo/bar/icons.zip and the source points to a directory in the file system, then the directory will be wrapped up in a Jar and stored as a single entry in the receiving jar file.

+
-includeresource    foo/bar/icons.zip=@icons/
+
+ +

Unrolling is getting the content from another JAR. It is activated by starting the source with an at sign (@). The at sign signals that it is not the actual file that should be copied, but the contents of that file should be placed in the destination.

+
-includeresource    tmp=@jar/foo.jar
+
+ +

The part that follows the at sign (@) is either a file path or a URL. Without any extra parameters it will copy all resources except the ones in the -donotcopy list and the META-INF/MANIFEST.

+
-includeresource    @jar/foo.jar
+
+ +

This is an ideal way to wrap a bundle since it is a full copy. After that one can add additional resources or use -exportcontents to export the contained packages in the normal way. In this way, bnd will calculate all imports.

+

The unrolling can also be restricted with a single selector. The syntax for the selector must start with a !/ marker, which is commonly used for this purpose. After the !/ the normal selector operators and patterns can be used. For example, if we want to get just the LICENSE from a bundle then we can do:

+
-includeresource    @jar/foo.jar!/LICENSE
+
+ +

However, since selectors can also negate, it is also possible to do the reverse:

+
-includeresource    "@jar/foo.jar!/!LICENSE"
+
+ +

This is a single selector, it is therefore not possible to specify a chain with rejections and selections. However, also a single selector can match multiple file paths:

+
-includeresource    @jar/osgi.jar!/!(LICENSE|about.html|org/*)
+
+ +

Wrapping often requires access to a JAR from the repository. It is therefore common to see the unrolling feature being combined with the ${repo} macro. The ${repo} macro is given the Bundle Symbolic Name and an optional version range returns the path to a file from the repository.

+
-includeresource    @${repo;biz.aQute.bndlib}!/about.html
+
+ +

Unrolling options

+

flatten:=BOOLEAN - puts all files in the file-tree into one folder

+
-includeresource new.package/=@jar/file.jar!/META-INF/services/*;flatten:=true
+
+ +

rename:=RENAME - maps the path using a given renaming instruction. Paths are filtered by the given instruction-SELECTOR. The instruction-Selector is compiled to a regex-pattern. This pattern is used to generate a matcher by using the filtered path and the matcher is used to replaceAll using the given extra value.

+
-includeresource new.package=@jar/cxf-rt-rs-sse-3.2.5.jar!/(META-INF)/(c*f)/(*);rename:=$2/$1/$3.copy
+
+ +

onduplicate - controls duplicate file handling for files with the same path and filename. See Handling duplicates below.

+

Handling duplicates

+

When unrolling multiple jar files into your target jar then duplicates can occur when multiple files share the same path and filename. By default duplicates overwrite existing files (last wins). +With the onduplicate directive you can control this behavior. For example there is the command onduplicate:=MERGE which by default is able to merge (append) services files in /META-INF/services/.

+

Examples:

+ +

WARN and ERROR can be combined with other commands, while OVERWRITE, MERGE, SKIP are mutually exclusive. +So combinations are possible, e.g.

+ +

Example - Handling duplicates

+

Let's take Apache FOP as an example. This library comes with 4 jars which are not OSGi bundles. +To use them in OSGi you could wrap them with bnd. Because of some classloading issues related to the ServiceLoader mechanism, one way to do it is to combine them into a single bundle. +One challenge is its extension mechanism which uses ServiceLoaders under /META-INF/services/.

+

For example the bundle fop-core contains a file META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader with the content:

+
org.apache.fop.image.loader.batik.PreloaderWMF
+org.apache.fop.image.loader.batik.PreloaderSVG
+
+ +

xmlgraphics-commons contains the same file META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader with content:

+
org.apache.xmlgraphics.image.loader.impl.PreloaderTIFF
+org.apache.xmlgraphics.image.loader.impl.PreloaderGIF
+org.apache.xmlgraphics.image.loader.impl.PreloaderJPEG
+org.apache.xmlgraphics.image.loader.impl.PreloaderBMP
+org.apache.xmlgraphics.image.loader.impl.PreloaderEMF
+org.apache.xmlgraphics.image.loader.impl.PreloaderEPS
+org.apache.xmlgraphics.image.loader.impl.imageio.PreloaderImageIO
+org.apache.xmlgraphics.image.loader.impl.PreloaderRawPNG
+
+ +

If you combine these two jars into a single target jar you want to ensure that both files do not overwrite each other but are merged / appended instead, in order to be a valid ServiceLoader file.

+

This can be achieved by the following instructions:

+
@${repo;org.apache.xmlgraphics:fop-core;latest}!/*,\
+@${repo;org.apache.xmlgraphics:xmlgraphics-commons;latest}!/*;onduplicate:=MERGE,\
+
+ +

The instructions above can be read like this:

+ +

Literals

+

For testing purposes it is often necessary to have tiny resources in the bundle. These could of course be placed on the file system but bnd can also generate these on the fly. Since these are defined in the bnd files, the content has full access to the macros. This is done by specifying a literal attribute on the clause.

+
-includeresource    foo.txt;literal='This is some content with a macro ${sum;1,2,3}'
+
+ +

The previous example will create a resource with the given content.

+

Flattening & Recurse

+

When a directory is specified bnd will by default recurse the source and create a similar hierarchy on the destination.

+

The recursion and the hierarchy can be controlled with directives.

+
-includeresource    target/=hierarchy/
+
+ +

The recursive: directive can be used to indicate that the source should not be recursively traversed by specifying false:

+
-includeresource    target/=hierarchy/;recursive:=false
+
+ +

In this case, only the hierarchy directory itself will be copied to the target directory. The flatten: directive indicates that if the directories are recursively searched, the output must not create any directories. That is all resources are flattened in the output directory.

+
-includeresource    target/=hierarchy/;flatten:=true
+
+ +

Sample usages

+

Simple form

+ + + + + + + + + + + + + + + + + + + + + + + + + +
InstructionExplanation
-includeresource: lib/fancylibrary-3.12.0.jarCopy lib/fancylibrary-3.12.0.jar file into the root of the target JAR
-includeresource.resources: -src/main/resourcesCopy folder src/main/resources contents (including subdfolders) into root of the target JAR
The arbitrarily named suffix .resources prevents this includeresource directive to be overwritten
The preceding minus sign instructs to supress an error for non-existing folder src/main/resources
-includeresource: ${workspace}/LICENSE, {readme.md}Copy the LICENSE file residing in the bnd workspace folder (above the project directory) as well as the pre-processed readme.md file (allowing for e.g. variable substitution) in the project folder into the target JAR
-includeresource: ${repo;com.acme:foo;latest}Copy the com.acme.foo bundle JAR in highest version number found in the bnd workspace repository into the root of the target JAR
+

Assignment form

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InstructionExplanation
-includeresource: images/=img/ or
-includeresource: images=img
Copy contents of img/ folder (including subdfolders) into an images folder of the target JAR
-includeresource: x=a/c/c.txtCopy a/c/c.txt into file x in the root folder of the target JAR
-includeresource: x/=a/c/c.txtCopy a/c/c.txt into file x/c.txt in the root folder of the target JAR
-includeresource: libraries/fancylibrary.jar=lib/fancylibrary-3.12.jar; lib:=trueCopy lib/fancylibrary-3.1.2.jar from project into libraries folder of the target JAR, and place it on the Bundle-Classpath (BCP). It will make sure the BCP starts with '.' and then each include resource that is included will be added to the BCP
-includeresource: lib/; lib:=trueCopy every JAR file underneath lib in a relative position under the root folder of the target JAR, and add each library to the bundle classpath
-includeresource: acme-foo-snap.jar=${repo;com.acme:foo;snapshot}Copy the highest snapshot version of com.acme.foo found in the bnd workspace repository as acme-foo-snap.jar into the root of the target JAR
-includeresource: foo.txt;literal='foo bar'Create a file named foo.txt containing the string literal "foo bar" in the root folder of the target JAR
-includeresource: bsn.txt;literal='${bsn}'Create a file named bsn.txt containing the bundle symbolic name (bsn) of this project in the root folder of the target JAR
-includeresource: libraries/=lib/;filter:=fancylibrary-*.jar;recursive:=false;lib:=true or
-includeresource: libraries/=lib/fancylibrary-*.jar;lib:=true (as of bndtools 4.2)
Copy a wildcarded library from lib/ into libraries and add it to the bundle classpath
+

Inline form

+ + + + + + + + + + + + + + + + + +
InstructionExplanation
-includeresource: @lib/fancylibrary-3.12.jar!/*Extract the contents of lib/fancylibrary-3.12.jar into the root folder of the target JAR, preserving relative paths
-includeresource: @${repo;com.acme.foo;latest}!/!META-INF/*Extract the contents of the highest found com.acme.foo version in the bnd workspace repository into the root folder of the target JAR, preserving relative paths, excluding the META-INF/ folder
+



+ + diff --git a/org.bndtools.help/docs/instructions/index.html b/org.bndtools.help/docs/instructions/index.html new file mode 100644 index 0000000000..b37e5750ed --- /dev/null +++ b/org.bndtools.help/docs/instructions/index.html @@ -0,0 +1,166 @@ + + + + +Instructions Reference + + + +

Instructions Reference

+ + + diff --git a/org.bndtools.help/docs/instructions/init.html b/org.bndtools.help/docs/instructions/init.html new file mode 100644 index 0000000000..008c4680d1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/init.html @@ -0,0 +1,30 @@ + + + + +-init ${MACRO} ( ',' ${MACRO}) * + + + +

-init ${MACRO} ( ',' ${MACRO}) *

+ + +

-init

+

The -init instruction specifies one or more macros to execute when initializing the project for building. This ensures that certain setup steps are always performed before the build starts.

+

Example:

+
-init: ${my_macro}, ${my_macro2}
+
+ +

Macros are usually resolved and executed on demand, but those listed in -init are always executed during project initialization.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/invalidfilenames.html b/org.bndtools.help/docs/instructions/invalidfilenames.html new file mode 100644 index 0000000000..6345e345c7 --- /dev/null +++ b/org.bndtools.help/docs/instructions/invalidfilenames.html @@ -0,0 +1,25 @@ + + + + +-invalidfilenames + + + +

-invalidfilenames

+ + +

The -invalidfilenames instruction allows you to specify file or directory names that should not be used in your project because they are not portable across all operating systems (especially Windows). By default, bnd checks for reserved names that are problematic on Windows, such as CON, PRN, AUX, NUL, COM1, LPT1, and others.

+

You can customize the regular expression used to detect invalid names by setting this instruction. If any files or directories in your JAR match the specified pattern, bnd will report an error, helping you avoid portability issues when distributing your bundles.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/javaagent.html b/org.bndtools.help/docs/instructions/javaagent.html new file mode 100644 index 0000000000..e4cc3641f5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/javaagent.html @@ -0,0 +1,36 @@ + + + + +-javaagent BOOLEAN + + + +

-javaagent BOOLEAN

+ + +

If the value is true, then each classpath elements that +has a Premain-Class manifest header is used as a java agent +when launching by adding a -javaagent: argument to the java invocation.

+
-javaagent:jarpath
+
+ +

If the classpath element was specified with an agent attribute, the +value of the agent attribute will be used as the options for the +-jaragent: argument to the java invocation.

+
-javaagent:jarpath=options
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/jpms_module_info.html b/org.bndtools.help/docs/instructions/jpms_module_info.html new file mode 100644 index 0000000000..374b2e24ae --- /dev/null +++ b/org.bndtools.help/docs/instructions/jpms_module_info.html @@ -0,0 +1,38 @@ + + + + +-jpms-module-info modulename [; version=<version>] [; access=OPEN|SYNTHETIC|MANDATED] + + + +

-jpms-module-info modulename [; version=] [; access=OPEN|SYNTHETIC|MANDATED]

+ + +

See jpms for an overview and the detailed rules how the module-info.class file is +calculated.

+

The -jpms-module-info instruction is a single parameter

+
-jpms-module-info   ::= module-name [ ';version=' VERSION ] access
+access              ::= `;access=' '"' item ( ',' item ) * '"'
+item                ::= 'OPEN' | 'SYNTHETIC' | 'MANDATED'
+
+ + +

For example:

+
-jpms-module-info: foo.module;version=5.4.1; access="OPEN,SYNTHETIC"
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/jpms_module_info_options.html b/org.bndtools.help/docs/instructions/jpms_module_info_options.html new file mode 100644 index 0000000000..8b213e2586 --- /dev/null +++ b/org.bndtools.help/docs/instructions/jpms_module_info_options.html @@ -0,0 +1,66 @@ + + + + +-jpms-module-info-options module-infos+ + + + +

-jpms-module-info-options module-infos+

+ + +

See jpms for an overview and the detailed rules how the module-info.class file is +calculated.

+

The -jpms-module-info-options instruction provides some capabilities to help the developer handle these scenarios. The keys of these instructions are module names and there are 4 available attributes.

+
-jpms-module-info-options       ::= moduleinfo
+moduleinfo                      ::= NAME 
+                                    [ ';substitute=' substitute ] 
+                                    [ ';ignore=' ignore ] 
+                                    [ ';static=' static ] 
+                                    [ ';transitive=' transitive ]
+
+ +

They attributes are:

+ +

means that if bnd calculates the module name to be geronimo-jcdi_2.0_spec it should replace it with java.enterprise

+

ignore - If the attribute ignore="true" is found the require matching the key of the instruction will not be added. + e.g.

+

properties + -jpms-module-info-options: java.enterprise;ignore="true"

+

means ignore the module java.enterprise

+ +

properties + -jpms-module-info-options: java.enterprise;static="true"

+

means make the require for module java.enterprise static

+ +

properties + -jpms-module-info-options: java.enterprise;transitive="true"

+

means make the require for module java.enterprise transitive

+

The following is an example with multiple attributes and instructions:

+
-jpms-module-info-options: \
+    java.enterprise;substitute="geronimo-jcdi_2.0_spec";static=true;transitive=true,\
+    java.management;ignore=true;
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/jpms_multi_release.html b/org.bndtools.help/docs/instructions/jpms_multi_release.html new file mode 100644 index 0000000000..44c85e4c14 --- /dev/null +++ b/org.bndtools.help/docs/instructions/jpms_multi_release.html @@ -0,0 +1,30 @@ + + + + +-jpms-multi-release BOOLEAN + + + +

-jpms-multi-release BOOLEAN

+ + +

This instruction controls that if a JAR setup to be a multi-release jar the manifests & module-infos +for each supported versions should be added. If this instruction is true, it will generate this metadata, +if the instruction is absent or the value is not true, then it will ignore the versions.

+

A multi release Jar (MRJ) will contain directories in META-INF/versions/, where the directory name is a release +number. If this instruction is enabled, then during manifest generation, bnd will also calculate a manifest and +module-info in each versioned directory.

+



+ + diff --git a/org.bndtools.help/docs/instructions/launcher.html b/org.bndtools.help/docs/instructions/launcher.html new file mode 100644 index 0000000000..5568588114 --- /dev/null +++ b/org.bndtools.help/docs/instructions/launcher.html @@ -0,0 +1,42 @@ + + + + +-launcher + + + +

-launcher

+ + +

This instruction has as purpose to collect options and special settings for the launcher. The +following options are architected:

+ +

Example

+
-launcher manage = all
+
+ +

Background

+

This instruction was primarily designed to handle start levels. Originally the launcher was +narrowly managing only the bundles that were in its scope. However, this was inadvertently +changed and not discovered for several reasons. The option to narrowly manage was therefore +introduced with the default being the latest behavior.

+



+ + diff --git a/org.bndtools.help/docs/instructions/library.html b/org.bndtools.help/docs/instructions/library.html new file mode 100644 index 0000000000..5145fb3afa --- /dev/null +++ b/org.bndtools.help/docs/instructions/library.html @@ -0,0 +1,107 @@ + + + + +-library library ( ',' library )* + + + +

-library library ( ',' library )*

+ + +

The main reason for the -library instruction is to let you package and share bnd-related configuration in a self-contained way so it can be reused across workspaces, projects, or run descriptions.

+

Let's use some examples for explanation.

+

Example 1) Common bnd Configuration Across Multiple Projects

+

Scenario

+

You have many projects that all need the same baseline OSGi or bnd settings—like default macros, a specific build plugin, or a certain analyzer configuration (e.g., “treat warnings as errors,” “export packages in a particular way,” etc.).

+

How a Library Helps

+
    +
  1. Put these shared bnd instructions (i.e., the macros and plugin setups) in project.bnd (or workspace.bnd/bndrun.bnd) inside a “library bundle” in your repo.
  2. +
  3. In each project that wants these settings, just add: + -library myconfig
  4. +
  5. All the macros and plugin instructions from that library will be included.
  6. +
+

This avoids copying the same lines into each bnd.bnd. Instead, every project references the same library, ensuring consistency.

+

Example 2) Including Pre-Configured Tooling/Plugins

+

Scenario

+

You have a plugin (e.g., for code generation) that always needs a certain set of properties to work properly—maybe a specific source folder or some environment variables.

+

How a Library Helps

+
    +
  1. Provide a bundle that contains the plugin (or references it) plus a bnd file with the plugin’s configuration.
  2. +
  3. Other projects include that library: + -library codegen
  4. +
  5. Now each project automatically has the plugin in its build plus the right plugin settings (class paths, macros, etc.).
  6. +
+

This is particularly nice if you have multiple plugins or complex plugin settings that you do not want to replicate.

+

Creating a library

+

A library is stored in a bundle. A bundle can contain multiple libraries that are each described by a +capability in the bnd.library name space. This capability looks like:

+
Provide-Capability: \
+    bnd.library; \
+        bnd.library     = foo; \
+        version         = 1.2.3; \
+        path           = lib/foo
+
+ +

The following attributes are defined for the bnd.library capabilities:

+ +

The root of the library should contain the bnd files to be included. The defaults (workspace.bnd, project.bnd, and +bndrun.bnd) should only be there if it makes sense to include the library in that type.

+

Using a library

+

A library can provide additional named functionality to a workspace, a project, or a bndrun file. It does this by +including a bnd file in the setup that originates from a bundle in the repositories. This included bnd file +can refer and use any binary resources in this bundle. Bundles can contain multiple libraries.

+

The -library instruction can apply a library extension from the repositories to a workspace or project. A library +extension is a resource that is stored in one of the repositories. When the -library instruction is used, the corresponding resource +will be expanded in the workspace's cache and one or more files from this area are read as include files containing +bnd properties.

+
-library    ::=  library ( ',' library )*
+library     ::=  '-'? NAME ( ';' parameter ) *
+
+ +

For example, the library foo is included in a resource in the repository. We can apply this library in the +build.bnd, bnd.bnd, or *.bndrun file.

+
-library  foo
+
+ +

The following parameter attributes are architected:

+

version – The version range of the capability. If no version is specified, 0 is used. If a version is specified, then + this is the lowest acceptable version. The runtime will select the highest matching version. The version can also be: + * file – the library name is a path to a directory or JAR file. Since this lacks the 'where' of the library in the + directory or JAR, this can be set with the where attribute in the same clause. +* include – The name of the include file or directory, relative to the root directory of the library. If a directory + is targeted, all *.bnd files will be read. The default include depends on where the library is included. In: + * The workspace (build.bnd) – workspace.bnd + * A project (bnd.bnd) – project.bnd + * A bndrun spec (*.bndrun) – bndrun.bnd

+

Some remarks:

+ +

Repositories & Ordering

+

Since libraries are stored in repositories but can also provide new repositories it is important to +understand the ordering.

+

Only libraries included in the workspace can contribute repositories. The workspace will first read the cnf/ext +directory bnd files and then build.bnd. Any repositories defined in these bnd files can be used for libraries. +The workspace will include the libraries based on these repositories. However, after all libraries have +been included, all plugins are reset and this will reset the repositories. Any repository plugins defined +in a library will then become available.

+

Projects and bndrun files can include libraries but they cannot define any new repositories.

+

NOTE: what about standalone bndruns?

+



+ + diff --git a/org.bndtools.help/docs/instructions/make.html b/org.bndtools.help/docs/instructions/make.html new file mode 100644 index 0000000000..8e9f8f3a6a --- /dev/null +++ b/org.bndtools.help/docs/instructions/make.html @@ -0,0 +1,145 @@ + + + + +-make + + + +

-make

+ +

Directives

+ + +
    package aQute.bnd.make;
+
+    import java.util.*;
+    import java.util.Map.Entry;
+    import java.util.regex.*;
+
+    import aQute.bnd.header.*;
+    import aQute.bnd.osgi.*;
+    import aQute.bnd.service.*;
+
+    public class Make {
+        Builder                             builder;
+        Map<Instruction,Map<String,String>> make;
+
+        public Make(Builder builder) {
+            this.builder = builder;
+        }
+
+        public Resource process(String source) {
+            Map<Instruction,Map<String,String>> make = getMakeHeader();
+            builder.trace("make " + source);
+
+            for (Map.Entry<Instruction,Map<String,String>> entry : make.entrySet()) {
+                Instruction instr = entry.getKey();
+                Matcher m = instr.getMatcher(source);
+                if (m.matches() || instr.isNegated()) {
+                    Map<String,String> arguments = replace(m, entry.getValue());
+                    List<MakePlugin> plugins = builder.getPlugins(MakePlugin.class);
+                    for (MakePlugin plugin : plugins) {
+                        try {
+                            Resource resource = plugin.make(builder, source, arguments);
+                            if (resource != null) {
+                                builder.trace("Made " + source + " from args " + arguments + " with " + plugin);
+                                return resource;
+                            }
+                        }
+                        catch (Exception e) {
+                            builder.error("Plugin " + plugin + " generates error when use in making " + source
+                                    + " with args " + arguments, e);
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        private Map<String,String> replace(Matcher m, Map<String,String> value) {
+            Map<String,String> newArgs = Processor.newMap();
+            for (Map.Entry<String,String> entry : value.entrySet()) {
+                String s = entry.getValue();
+                s = replace(m, s);
+                newArgs.put(entry.getKey(), s);
+            }
+            return newArgs;
+        }
+
+        String replace(Matcher m, CharSequence s) {
+            StringBuilder sb = new StringBuilder();
+            int max = '0' + m.groupCount() + 1;
+            for (int i = 0; i < s.length(); i++) {
+                char c = s.charAt(i);
+                if (c == '$' && i < s.length() - 1) {
+                    c = s.charAt(++i);
+                    if (c >= '0' && c <= max) {
+                        int index = c - '0';
+                        String replacement = m.group(index);
+                        if (replacement != null)
+                            sb.append(replacement);
+                    } else {
+                        if (c == '$')
+                            i++;
+                        sb.append(c);
+                    }
+                } else
+                    sb.append(c);
+            }
+            return sb.toString();
+        }
+
+        Map<Instruction,Map<String,String>> getMakeHeader() {
+            if (make != null)
+                return make;
+            make = Processor.newMap();
+
+            String s = builder.getProperty(Builder.MAKE);
+            Parameters make = builder.parseHeader(s);
+
+            for (Entry<String,Attrs> entry : make.entrySet()) {
+                String pattern = Processor.removeDuplicateMarker(entry.getKey());
+
+                Instruction instr = new Instruction(pattern);
+                this.make.put(instr, entry.getValue());
+            }
+
+            return this.make;
+        }
+    }
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/manifest.html b/org.bndtools.help/docs/instructions/manifest.html new file mode 100644 index 0000000000..f24d4fe7aa --- /dev/null +++ b/org.bndtools.help/docs/instructions/manifest.html @@ -0,0 +1,25 @@ + + + + +-manifest FILE + + + +

-manifest FILE

+ + +

The -manifest instruction allows you to override the default manifest calculation and specify a fixed manifest file to use in your JAR. When this instruction is set, bnd will use the provided manifest file instead of generating one automatically, although it will still analyze the classpath as part of the build process.

+

This is useful when you need to comply with specific manifest requirements or reuse an existing manifest file for your bundle.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/manifest_name.html b/org.bndtools.help/docs/instructions/manifest_name.html new file mode 100644 index 0000000000..f2b875dc51 --- /dev/null +++ b/org.bndtools.help/docs/instructions/manifest_name.html @@ -0,0 +1,20 @@ + + + + +-manifest-name RESOURCE + + + +

-manifest-name RESOURCE

+ + +

The -manifest-name instruction allows you to set a custom resource path for the manifest file in your JAR. By default, the manifest is stored as META-INF/MANIFEST.MF, but some standards or environments may require a different name or location.

+

Use this instruction to override the default manifest path when needed. For example, you might set it to a different file name or directory to comply with a specific packaging requirement.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/maven_dependencies.html b/org.bndtools.help/docs/instructions/maven_dependencies.html new file mode 100644 index 0000000000..3cf4141d86 --- /dev/null +++ b/org.bndtools.help/docs/instructions/maven_dependencies.html @@ -0,0 +1,68 @@ + + + + +-maven-dependencies* entry ( ',' entry )* + + + +

-maven-dependencies* entry ( ',' entry )*

+ + +

The -pom instruction can be used to generate a pom in the bundle. The value of the -maven-dependencies instruction is used to generate the <dependencies> section in the generated pom.

+

Syntax

+
-maven-dependencies ::= entry ( ',' entry ) *
+ entry     ::= key ( ';' attribute ) *
+ attribute ::= groupId-attr | artifactId-attr | version-attr
+               | classifier-attr
+ groupId-attr    ::= 'groupId' '=' groupId
+ artifactId-attr ::= 'artifactId' '=' artifactId
+ version-attr    ::= 'version' '=' version
+ classifier-attr ::= 'classifier' '=' classifier
+ gavkey    ::= groupId ':' artifactId ':' version ( ':jar:' classifier)?
+
+ +

Description

+

For Bnd Workspace builds, the -maven-dependencies instruction is automatically set, if not already set, by Bnd from the -buildpath entries of the project. Normally, you can allow Bnd to automatically set the -maven-dependencies instruction. But you can override the maven dependency information by explicitly setting the -maven-dependencies instruction. If set to the empty string, then no <dependencies> section will be added in the generated pom. Since the -maven-dependencies instruction is a merged instruction, you can use suffixes to override the generated information for a dependency and to add additional dependencies to the maven dependency information.

+

When Bnd automatically sets the -maven-dependencies instruction, it will generate the key value using the gavkey production with the groupId, artifactId, version, and classifier (if set) values of the artifact. Using a well defined gavkey value, allows the attributes of a specific artifact to be overriden by merged property value while allowing the other automatically set values to still be used. However any unique key value can be used if you don't care to override the automatically set value for a specific dependency.

+

When an artifact come from a maven repository, such as MavenBndRepository or BndPomRepository, the maven repository will supply the groupId, artifactId, version, and classifier (if the artifact has a non-empty classifier) attributes of the artifact. If the artifact does not come from a maven repository but does contain a pom.properties resource, then the groupId, artifactId, and version attributes are supplied by that resource.

+

Buildpath Entries

+

An attribute value can also be specified on a -buildpath entry, by prefixing the attribute name with maven-, which can then replace any such attribute value coming from the maven repository or a pom.properties resource.

+

You can set the maven-scope attribute on a -buildpath entry to specify a different dependency scope than the default dependency scope specified by the -maven-scope instruction. The value of the maven-scope attribute must be a valid dependency scope.

+

You can also set the maven-optional attribute on a -buildpath entry to true which will exclude the artifact from the generated dependencies information. The default value for maven-optional is false.

+

Examples

+

Disable generating the <dependencies> section in the generated pom.

+
-maven-dependencies:
+
+ +

Override the automatically set dependency information for a specific artifact. You must use the matching gavkey of the actual artifact and then specify the groupId, artifactId, and version attributes to use for the artitact. This example replaces the version of the artifact to remove -SNAPSHOT.

+
-maven-dependencies.fix: org.osgi:osgi.annotation:8.0.0-SNAPSHOT;\
+ groupId=org.osgi;artifactId=osgi.annotation;version=8.0.0
+
+ +

This could also be done on the -buildpath entry for the artifact by specifying the maven-version attribute to override the maven version of the artifact.

+
-buildpath: osgi.annotation;version=8.0.0.SNAPSHOT;maven-version=8.0.0
+
+ +

Add an additional dependency. You must specify the groupId, artifactId, and version attributes to use for the artitact.

+
-maven-dependencies.log: log;groupId=org.osgi;\
+ artifactId=org.osgi.service.log;version=1.5.0
+
+ +

Don't generate a <dependency> element for a specific artifact. This is done by specifying the proper gavkey value and not specifying any attributes.

+
-maven-dependencies.nodependency: org.osgi:osgi.annotation:8.0.0
+
+ +

This could also be done on the -buildpath entry for the artifact by specifying the maven-optional attribute with the value true.

+
-buildpath: osgi.annotation;version=8.0.0;maven-optional=true
+
+ +

Change the dependency scope for the artifact. The default dependency scope is specified by the -maven-scope instruction.

+
-buildpath: osgi.annotation;version=8.0.0;maven-scope=provided
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/maven_release.html b/org.bndtools.help/docs/instructions/maven_release.html new file mode 100644 index 0000000000..9d0d56c0b4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/maven_release.html @@ -0,0 +1,76 @@ + + + + +-maven-release ('local'|'remote') ( ',' option )* + + + +

-maven-release ('local'|'remote') ( ',' option )*

+ + +

The -maven-release instruction provides the context for a release to Maven repository. In the Maven world it is customary that a release has a JAR with sources and a JAR with Javadoc. In the OSGi world this is unnecessary because the sources can be packaged inside the bundle. (Since the source is placed at a standard location, the IDEs can take advantage of this.) However, putting an artifact on Maven Central requires that these extra JARs are included. This instruction allows you to specify additional parameters for this release process.

+

Though this instruction is not specific for a plugin, it was developed in conjunction with the Maven Bnd Repository Plugin.

+
-maven-release ::= ( 'local'|'remote' ( ';' snapshot )? ) ( ',' option )*
+snapshot       ::= <value to be used for timestamp>
+option         ::= sources | javadoc | pom | sign | archive*
+archive          ::= 'archive' 
+                   ( ';path=' ( PATH | '{' PATH '}' )?
+                   ( ';classifier=' maven-classifier )?
+sources        ::= 'sources' 
+                   ( ';path=' ( 'NONE' | PATH ) )?
+                   ( ';force=' ( 'true' | 'false' ) )?
+                   ( ';-sourcepath=' PATH ( ',' PATH )* )?
+javadoc        ::= 'javadoc'
+                   ( ';path=' ( 'NONE' | PATH ) )?
+                   ( ';packages=' ( 'EXPORTS' | 'ALL' ) )?
+                   ( ';force=' ( 'true' | 'false' ) )?
+                   ( ';' javadoc-option )*
+javadoc-option ::= '-' NAME '=' VALUE
+pom            ::= 'pom'
+                   ( ';path=' ( 'JAR' | PATH ) )?
+sign            ::= 'sign'
+                   ( ';passphrase=' VALUE )?
+                   ( ';keyname=' VALUE )?
+
+ +

If sources or javadoc has the attribute force=true, either one will be release to the maven repository even if no releaseUrl or snapshotUrl is set or maven-release=local.

+

The aQute.maven.bnd.MavenBndRepository is a bnd plugin that represent the local and a remote Maven repository. The locations of both repositories can be configured. The local repository is always used as a cache for the remote repository.

+

For a detailed configuration of the Maven Bnd Repository Plugin, please look at the documentation page.

+

If the Maven Bnd Repository is asked to put a file, it will look up the -maven-release instruction using merged properties. The property is looked up from the bnd file that built the artifact. However, it should in general be possible to define this header in the workspace using macros like ${project} to specify relative paths.

+

The archive option provides a way to add additional files/archives to release. A Maven release always has a pom and then a number of files/archives that are separated by a classifier. The default classifier is generally the jar file. Special classifiers are reserved for the sources and the javadoc.

+

The archive option takes the following parameters:

+ +

For example:

+
 -maven-release \
+       archive;\
+        path=files/feature.json;
+        classifier=feature
+
+ +

Signing

+

If the instruction contains the sign attribute and release build is detected the repository tries to apply gnupg via a command process to create .asc files for all deployed artifacts. This requires a Version of gnupg installed on your build system. By default it uses the gpg command. If the passphrase is configured, it will hand it over to the command as standard input, same for the keyname.

+

The command will be constructed as follows:

+

gpg --batch --local-user <keyname> --passphrase-fd 0 --output <filetosign>.asc --detach-sign --armor <filetosign>. Some newer gnupg versions will ignore the passphrase via standard input for the first try and ask again with password screen. This will crash the process. Have a look here to teach gnupg otherwise. The command can be exchanged or amended with additional options by defining a property named gpg in your workspace (e.g. build.bnd or somewhere in the ext directory).

+

Example config could look like:

+
# use the env macro to avoid to set the passphrase somehwere in your project
+-maven-release: pom,sign;keyname=${env;GNUPG_KEYNAME}, passphrase=${env;GNUPG_PASSPHRASE}
+gpg: gpg --homedir /mnt/n/tmp/gpg/.gnupg --pinentry-mode loopback
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/maven_scope.html b/org.bndtools.help/docs/instructions/maven_scope.html new file mode 100644 index 0000000000..935484eb6d --- /dev/null +++ b/org.bndtools.help/docs/instructions/maven_scope.html @@ -0,0 +1,33 @@ + + + + +-maven-scope dependency-scope + + + +

-maven-scope dependency-scope

+ + +

The -pom instruction can be used to generate a pom in the bundle. The -maven-scope instruction can be used to specify the default dependency scope to use when Bnd generates maven dependency information for a -buildpath entry that will be used to create a <dependency> in the generated pom.

+

Also see the -maven_dependencies instruction for information on how to manualy configure the maven dependency information in a generated pom.

+

Default behavior

+

-maven-scope defaults to the value compile which is the default dependency scope for Maven.

+

Examples

+

Change the default dependency scope to provided.

+
-maven-scope: provided
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/metainf_services.html b/org.bndtools.help/docs/instructions/metainf_services.html new file mode 100644 index 0000000000..55c97d35d5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/metainf_services.html @@ -0,0 +1,52 @@ + + + + +-metainf-services + + + +

-metainf-services

+ + +

The -metainf-services instruction tells bnd how files in the META-INF/services should be processed. +See the chapter about META-INF/services Annotations how to apply Bundle annotations to the files in the META-INF/services.

+

This instruction can have the following values:

+ +

Example of auto-registration

+

Assume we want to wrap a non-OSGi library containing META-INF/services. +Create bnd.bnd file and put a library having a META-INF/services folder e.g. groovy-3.0.22.jar in a local lib folder. +We will use -includeresource: @lib/groovy-3.0.22.jar to unroll the jar.

+
# bnd.bnd
+-includeresource: @lib/groovy-3.0.22.jar
+-metainf-services: auto
+
+ +

This creates a new jar with the following MANIFEST.MF headers from the META-INF/services folder:

+
# MANIFEST.MF
+Provide-Capability                      osgi.service;objectClass:List<String>="org.codehaus.groovy.transform.ASTTransformation";effective:=active
+                                        osgi.serviceloader;osgi.serviceloader="org.codehaus.groovy.transform.ASTTransformation";register:="groovy.grape.GrabAnnotationTransformation"
+Require-Capability                      osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
+                                        osgi.extender;filter:="(&(osgi.extender=osgi.serviceloader.registrar)(version>=1.0.0)(!(version>=2.0.0)))";resolution:=optional
+
+ +

Because -metainf-services: auto is used, it instructs bnd to auto-generate a @ServiceProvider annotation under the hood for services without annotations. +To prevent the latter (auto-generation) use the default -metainf-services: annotation (to process only textual annotations) or use -metainf-services: none to skip processing of META-INF/services files completely.

+

source

+



+ + diff --git a/org.bndtools.help/docs/instructions/metatypeannotations.html b/org.bndtools.help/docs/instructions/metatypeannotations.html new file mode 100644 index 0000000000..04ae0fccca --- /dev/null +++ b/org.bndtools.help/docs/instructions/metatypeannotations.html @@ -0,0 +1,26 @@ + + + + +-metatypeannotations SELECTORS + + + +

-metatypeannotations SELECTORS

+ + +

The -metatypeannotations instruction tells bnd which bundle classes, if any, to search for Metatype Service annotations. bnd will then process those classes into Metatype XML resources.

+

The value of this instruction is a comma delimited list of fully qualified class names.

+

The default value of this instruction is *, which means that by default bnd will process all bundle classes looking for Metatype annotations.

+

The behavior of Metatype annotation processing can be further configured using the -metatypeannotations-options instruction.

+

source

+



+ + diff --git a/org.bndtools.help/docs/instructions/metatypeannotations_options.html b/org.bndtools.help/docs/instructions/metatypeannotations_options.html new file mode 100644 index 0000000000..9296663e8a --- /dev/null +++ b/org.bndtools.help/docs/instructions/metatypeannotations_options.html @@ -0,0 +1,28 @@ + + + + +-metatypeannotations-options SELECTORS + + + +

-metatypeannotations-options SELECTORS

+ + +
-metatypeannotations-options: version;minimum=1.2.0
+
+ +

Analogous to -dsannotations-options, this will also restrict the use of OSGi Metatype annotations to minimum 1.2.0 version. The version number denotes that the users can use any version equal to or higher than 1.2.0, provided that the users have the Metatype annotations included on the build path.

+



+ + diff --git a/org.bndtools.help/docs/instructions/namesection.html b/org.bndtools.help/docs/instructions/namesection.html new file mode 100644 index 0000000000..52e07ae8fc --- /dev/null +++ b/org.bndtools.help/docs/instructions/namesection.html @@ -0,0 +1,67 @@ + + + + +-namesection RESOURCE-SPEC ( ',' RESOURCE-SPEC ) * + + + +

-namesection RESOURCE-SPEC ( ',' RESOURCE-SPEC ) *

+ + +

Create a name section (second part of manifest) with optional property expansion and addition of custom attributes.

+

Matching

+

The key of the -namesection instruction is an ant style glob. And there are two target groups for matching:

+ +

Custom attributes

+

The goal of named sections is to provide attributes over a specific subset of resources and paths in the jar file. Attributes are specified using the same syntax used elsewhere (such as package attributes). Attributes can contain properties and macros for expansion and replacement.

+

Each attribute is processed by bnd and the matching value is passed using the @ property.

+

Resources

+

Resources are targeted by using a glob pattern not ending with /.

+

For example, the following instruction sets the content type attribute for png files:

+
-namesection: com/foo/*.png; Content-Type=image/png
+
+ +

This produces a result like the following:

+
Name: org/foo/icon_12x12.png
+Content-Type: image/png
+
+Name: org/foo/icon_48x48.png
+Content-Type: image/png
+
+ +

Packages

+

Packages are targeted by using a glob pattern that ends with /.

+

For example, to produce a Java Package Version Information section use an instruction like this one:

+
-namesection: jakarta/annotation/*/;\
+    Specification-Title=Jakarta Annotations;\
+    Specification-Version=${annotation.spec.version};\
+    Specification-Vendor=Eclipse Foundation;\
+    Implementation-Title=jakarta.annotation;\
+    Implementation-Version=${annotation.spec.version}.${annotation.revision};\
+    Implementation-Vendor=Apache Software Foundation
+
+ +

This produces a result like the following:

+
Name: jakarta/annotation/
+Implementation-Title: jakarta.annotation
+Implementation-Vendor: Apache Software Foundation
+Implementation-Version: 2.0.0-M1
+Specification-Title: Jakarta Annotations
+Specification-Vendor: Eclipse Foundation
+Specification-Version: 2.0
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/nobuildincache.html b/org.bndtools.help/docs/instructions/nobuildincache.html new file mode 100644 index 0000000000..2effac56ff --- /dev/null +++ b/org.bndtools.help/docs/instructions/nobuildincache.html @@ -0,0 +1,28 @@ + + + + +-nobuildincache BOOLEAN + + + +

-nobuildincache BOOLEAN

+ + +

The -nobuildincache instruction controls whether a build cache is used for the launcher and JUnit. When set to true, bnd will not use a build cache, which can be useful for troubleshooting or when you want to ensure that all builds are performed from scratch without relying on cached files.

+

By default, the build cache is enabled to improve performance by reusing previously built artifacts. Disabling the cache may slow down builds but can help avoid issues related to stale or corrupted cache data.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/nobundles.html b/org.bndtools.help/docs/instructions/nobundles.html new file mode 100644 index 0000000000..6a68d5c7ab --- /dev/null +++ b/org.bndtools.help/docs/instructions/nobundles.html @@ -0,0 +1,33 @@ + + + + +-nobundles BOOLEAN + + + +

-nobundles BOOLEAN

+ + +

-nobundles

+

The -nobundles instruction tells bnd to skip building the project. This can be useful for projects that only provide resources or configuration, or for disabling builds in certain environments.

+

Example:

+
-nobundles: true
+
+ +

When this instruction is set to true, bnd will not produce any output JARs for the project.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/noclassforname.html b/org.bndtools.help/docs/instructions/noclassforname.html new file mode 100644 index 0000000000..1669daa6f9 --- /dev/null +++ b/org.bndtools.help/docs/instructions/noclassforname.html @@ -0,0 +1,35 @@ + + + + +-noclassforname BOOLEAN + + + +

-noclassforname BOOLEAN

+ + +

Normally Bnd will examine the method bodies of classes looking for the instruction sequence:

+
ldc(_w) "some.Class"
+invokestatic "java/lang/Class" "forName(Ljava/lang/String;)Ljava/lang/Class;"
+
+ +

which results from calls to Class.forName(String) passing a String constant for the class name. Bnd will use the String constant as a class reference for the purposes of calculating package references for generating the Import-Package manifest header.

+

The -noclassforname instruction can be used to tell Bnd to not search the method bodies for this instruction sequence.

+

For example:

+
-noclassforname: true
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/nodefaultversion.html b/org.bndtools.help/docs/instructions/nodefaultversion.html new file mode 100644 index 0000000000..db24822af0 --- /dev/null +++ b/org.bndtools.help/docs/instructions/nodefaultversion.html @@ -0,0 +1,28 @@ + + + + +-nodefaultversion BOOLEAN + + + +

-nodefaultversion BOOLEAN

+ + +

The -nodefaultversion instruction controls whether a default version is added to exported packages when no version is specified. By default, bnd will add the bundle version as the version for any exported package that does not have an explicit version. When this instruction is set to true, no default version will be added, and exported packages without a version will remain unversioned.

+

This can be useful if you want to avoid implicit versioning and ensure that only explicitly specified versions are used in your exported packages.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/noee.html b/org.bndtools.help/docs/instructions/noee.html new file mode 100644 index 0000000000..f7dcf7b0d4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/noee.html @@ -0,0 +1,28 @@ + + + + +-noee BOOLEAN + + + +

-noee BOOLEAN

+ + +

The -noee instruction controls whether bnd automatically adds a requirement for an Execution Environment (EE) capability based on the class file format. By default, bnd will analyze the class version and add the minimum required EE as a requirement. When this instruction is set to true, bnd will not add this automatic requirement, giving you full control over EE requirements in your bundle.

+

This is useful if you want to manage EE requirements manually or if your project has special compatibility needs.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/noextraheaders.html b/org.bndtools.help/docs/instructions/noextraheaders.html new file mode 100644 index 0000000000..0272ec3b3c --- /dev/null +++ b/org.bndtools.help/docs/instructions/noextraheaders.html @@ -0,0 +1,28 @@ + + + + +-noextraheaders BOOLEAN + + + +

-noextraheaders BOOLEAN

+ + +

The -noextraheaders instruction controls whether bnd adds extra headers to the manifest that are specific to bnd, such as Created-By, Tool, and Bnd-LastModified. By default, these headers are included to provide information about the build environment and tool versions. When this instruction is set to true, bnd will not add these extra headers, resulting in a cleaner manifest with only the standard OSGi headers.

+

This can be useful if you want to minimize metadata or ensure that your manifest contains only the required information.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/noimportjava.html b/org.bndtools.help/docs/instructions/noimportjava.html new file mode 100644 index 0000000000..0b427bfa65 --- /dev/null +++ b/org.bndtools.help/docs/instructions/noimportjava.html @@ -0,0 +1,37 @@ + + + + +-noimportjava BOOLEAN + + + +

-noimportjava BOOLEAN

+ + +

Prior to OSGi Core R7, it was invalid for the Import-Package header to include java.* packages. So Bnd would never include them in the generated Import-Package header. In OSGi Core R7, or later (e.g. OSGi Core R8), it is now permitted to include java.* packages in the Import-Package header. This allows the OSGi framework validate the execution environment can supply all the java packages required by a bundle. This can avoid a NoClassDefFoundError during execution of the bundle due to a missing java.* package required by the bundle.

+

Bnd will now generate the Import-Package header including referenced java.* packages when either the bundle imports the org.osgi.framework package from OSGi Core R7, or later, or when the bundle includes class files targeting Java 11, or later.

+

The -noimportjava instruction can be used to tell Bnd not to include referenced java.* packages in the generated Import-Package header.

+

For example:

+
-noimportjava: true
+
+ +

You can use the Import-Package instruction to control which referenced java.* packages should be imported.

+

For example:

+
Import-Package: java.util.*, !java.*, *
+
+ +

will only import java.util.* packages and no other java.* packages.

+



+ + diff --git a/org.bndtools.help/docs/instructions/nojunit.html b/org.bndtools.help/docs/instructions/nojunit.html new file mode 100644 index 0000000000..38d088cb8b --- /dev/null +++ b/org.bndtools.help/docs/instructions/nojunit.html @@ -0,0 +1,28 @@ + + + + +-nojunit BOOLEAN + + + +

-nojunit BOOLEAN

+ + +

The -nojunit instruction indicates that the project does not contain JUnit tests. When this instruction is set to true, bnd will not attempt to run JUnit tests for the project, even if test sources are present.

+

This is useful for projects that do not require unit testing or do not have any test cases that need to be executed as part of the build process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/nojunitosgi.html b/org.bndtools.help/docs/instructions/nojunitosgi.html new file mode 100644 index 0000000000..68a9faae6b --- /dev/null +++ b/org.bndtools.help/docs/instructions/nojunitosgi.html @@ -0,0 +1,28 @@ + + + + +-nojunitosgi BOOLEAN + + + +

-nojunitosgi BOOLEAN

+ + +

The -nojunitosgi instruction indicates that the project does not contain JUnit OSGi tests. When this instruction is set to true, bnd will not attempt to run OSGi-based JUnit tests for the project. This is useful for projects that do not require OSGi test execution or do not have any test cases that need to be run in an OSGi environment.

+

By default, if test sources and test cases are present, bnd will attempt to run both standard and OSGi-based JUnit tests unless this instruction is specified.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/nomanifest.html b/org.bndtools.help/docs/instructions/nomanifest.html new file mode 100644 index 0000000000..1941d9b97f --- /dev/null +++ b/org.bndtools.help/docs/instructions/nomanifest.html @@ -0,0 +1,30 @@ + + + + +-nomanifest BOOLEAN + + + +

-nomanifest BOOLEAN

+ + +

-nomanifest

+

The -nomanifest instruction controls whether the manifest file is included in the generated JAR. When set to true, the manifest will not be saved in the JAR file. This can be useful in scenarios where a manifest is not required or when you want to minimize the contents of the JAR for specific use cases.

+

Typically, most OSGi bundles require a manifest, but in some advanced or custom build scenarios, you may wish to omit it. Use this option with caution, as omitting the manifest may cause the resulting JAR to be unusable in standard OSGi environments.

+

By default, the manifest is included in the JAR unless -nomanifest: true is specified.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/noparallel.html b/org.bndtools.help/docs/instructions/noparallel.html new file mode 100644 index 0000000000..db10ddd3bc --- /dev/null +++ b/org.bndtools.help/docs/instructions/noparallel.html @@ -0,0 +1,30 @@ + + + + +-noparallel CATEGORY;task=TASKS + + + +

-noparallel CATEGORY;task=TASKS

+ + +

Gradle supports --parallel to run build tasks in parallel when possible. This can be a great speed improvement for a build. But sometimes, certain tasks cannot be run in parallel due to certain resource contention.

+

The -noparallel Bnd instruction can be used to state that any tasks assigned to a category must not be run in parallel with any other task assigned to the same category. The category names are open ended. Any task names specified must be the names of actual Gradle tasks in the project. Multiple categories and multiple task names per category can be specified.

+

For example:

+
-noparallel: launchpad;task="test", port80;task="testOSGi"
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/noproxyinterfaces.html b/org.bndtools.help/docs/instructions/noproxyinterfaces.html new file mode 100644 index 0000000000..fea0eb0fda --- /dev/null +++ b/org.bndtools.help/docs/instructions/noproxyinterfaces.html @@ -0,0 +1,48 @@ + + + + +-noproxyinterfaces BOOLEAN + + + +

-noproxyinterfaces BOOLEAN

+ + +

Normally, Bnd examines the method bodies of classes looking for the instruction sequence:

+
Proxy.newProxyInstance(ClassLoader, Class[], InvocationHandler)
+
+ +

When Bnd detects a call to Proxy.newProxyInstance, it inspects the Class[] argument — for example, new Class[] { SomeInterface.class, ... } — and treats all listed interfaces as if they were implemented by the class. This means that any types referenced in the parameters or return types of those interfaces must also be imported.

+

Example

+

Consider the following code:

+
return (ServletContext) Proxy.newProxyInstance(
+    curClassLoader, 
+    new Class[] { ServletContext.class }, 
+    new AdaptorInvocationHandler()
+);
+
+ +

Bnd will automatically add the package javax.servlet.descriptor to the Import-Package header, because the detected ServletContext interface declares the method JspConfigDescriptor getJspConfigDescriptor().

+

Limitations

+

Interface detection only occurs when the Class[] array is created inline (that is, using the anewarray bytecode pattern shown above). +If the array is obtained from a field, local variable, or method parameter, Bnd cannot reliably determine its contents from the bytecode, and therefore no interfaces will be detected in those cases.

+

Disabling Proxy Interface Detection

+

The -noproxyinterfaces instruction can be used to tell Bnd not to search method bodies for calls to Proxy.newProxyInstance.

+

For example:

+
-noproxyinterfaces: true
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/nosubstitution.html b/org.bndtools.help/docs/instructions/nosubstitution.html new file mode 100644 index 0000000000..99e1125621 --- /dev/null +++ b/org.bndtools.help/docs/instructions/nosubstitution.html @@ -0,0 +1,38 @@ + + + + +-nosubstitution + + + +

-nosubstitution

+ + +

See Subsitution to learn more about package Substition (a key aspect of OSGi allowing that a package can be both exported and imported).

+

Note, that package substitution behaviour is enabled by default in bnd for backward-compatibilty. But recommended to disable for most cases these days via -nosubstitution:true.

+

Example

+
-nosubstitution:true
+-exportcontents: *
+Import-Package: *
+
+ +

This ensures that no Import-Package is calculated for any package in Export-Package. This is equivalent to Export-Package: *;-noimport:=true or -exportcontents: *;-noimport:=true.

+

The advantage is that -nosubstitution:true is a global switch, thus a developer cannot forget to add -noimport:=true in case of a more fine-grained Export-Package declaration with multiple packages.

+

Why is it useful?

+

It is useful for library authors who never want to have any exported packages in Import-Package. +Often, library authors who are just using bnd to generate OSGi metadata in their build scripts (e.g. via maven or gradle plugins) but are otherwise unfamiliar with bnd and OSGi, need a simple way to disable this substitution behavior, because it can lead to surprising resolution results (or failures) after deployment (because other bundles providing the same package are pulled in). This is often undesirable in a pure "library" use-case.

+

This instruction helps making bnd / OSGi adoption easier for library projects just wanting to provide OSGi metadata.

+



+ + diff --git a/org.bndtools.help/docs/instructions/nouses.html b/org.bndtools.help/docs/instructions/nouses.html new file mode 100644 index 0000000000..aca440ce61 --- /dev/null +++ b/org.bndtools.help/docs/instructions/nouses.html @@ -0,0 +1,32 @@ + + + + +-nouses BOOLEAN + + + +

-nouses BOOLEAN

+ + +

Do not calculate the uses directive on package exports or on capabilities, if set to true. +Default: false

+

For example:

+
-nouses: true
+
+ +

Warning: +Setting this flag to true is rarely needed and can be dangerous. Without any uses clause, all packages are treated as independent from each other. That means the OSGi resolver is free to wire these packages to different classloaders if used by a consumer (or its dependencies).

+



+ + diff --git a/org.bndtools.help/docs/instructions/output.html b/org.bndtools.help/docs/instructions/output.html new file mode 100644 index 0000000000..fd0c972c7b --- /dev/null +++ b/org.bndtools.help/docs/instructions/output.html @@ -0,0 +1,26 @@ + + + + +-output FILE + + + +

-output FILE

+ + +

The -output instruction allows you to specify the output directory or file for the generated JAR or bundle. You can provide a file path or directory; if a directory is specified, the output file will be named based on the bundle symbolic name and version (e.g., bsn-version.jar).

+

If no output is specified, bnd will use default naming strategies, such as the name of the source file or a generic name like Untitled. This instruction is useful for controlling where and how your build artifacts are saved.

+

Note: See also the -outputmask instruction for more advanced output naming options.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/outputmask.html b/org.bndtools.help/docs/instructions/outputmask.html new file mode 100644 index 0000000000..dde5cf080c --- /dev/null +++ b/org.bndtools.help/docs/instructions/outputmask.html @@ -0,0 +1,25 @@ + + + + +-outputmask TEMPLATE ? + + + +

-outputmask TEMPLATE ?

+ + +

The -outputmask instruction allows you to define a template for naming the output file when building a JAR. You can use any macro in the template, but ${@bsn} and ${@version} are especially useful as they refer to the current bundle symbolic name and version, respectively. The default template is ${@bsn}.jar.

+

This instruction is helpful for customizing the naming convention of your build artifacts, making it easier to organize and identify them according to your project's needs.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/packageinfotype.html b/org.bndtools.help/docs/instructions/packageinfotype.html new file mode 100644 index 0000000000..8d2899ea98 --- /dev/null +++ b/org.bndtools.help/docs/instructions/packageinfotype.html @@ -0,0 +1,19 @@ + + + + +-packageinfotype + + + +

-packageinfotype

+ + + diff --git a/org.bndtools.help/docs/instructions/pedantic.html b/org.bndtools.help/docs/instructions/pedantic.html new file mode 100644 index 0000000000..f2592dfc94 --- /dev/null +++ b/org.bndtools.help/docs/instructions/pedantic.html @@ -0,0 +1,27 @@ + + + + +-pedantic BOOLEAN + + + +

-pedantic BOOLEAN

+ + +

When setting this instruction to true there will be more warnings about things that are not really wrong but still not right. +It can be helpful to fix problems in your workspace.

+

Note for Eclipse users: Currently a change to this instruction requires a restart of Eclipse. The Refresh-Workspace button is not enough.

+



+ + diff --git a/org.bndtools.help/docs/instructions/plugin.html b/org.bndtools.help/docs/instructions/plugin.html new file mode 100644 index 0000000000..7b385a641d --- /dev/null +++ b/org.bndtools.help/docs/instructions/plugin.html @@ -0,0 +1,72 @@ + + + + +-plugin.* plugin-def ( ',' plugin-def )* + + + +

-plugin.* plugin-def ( ',' plugin-def )*

+ + +

A plugin is a parameterized piece of code that runs inside bndlib. The -plugin instruction defines a plugin by specifying its class name and a given set of parameters; a specific class can be instantiated multiple times.

+

The -plugin instruction actually aggregates all properties that start with -plugin*. This makes it possible to set plugins in different places, for example include files or with the bndlib workspace extensions. The following sets the Git plugin:

+
-plugin.git = aQute.bnd.plugin.git.GitPlugin
+
+ +

Plugins are created at startup using a special plugin class loader. This class loader is pre-loaded with any URLs set in the -pluginpath instructions. The plugin definition can, however, also add additional URLs to this classloader with the 'path:' directive.

+

If the plugin implements the Plugin interface, it is given the parameters specified in the -plugin instruction. It is then registered in the plugin registry and made available to the rest of the system.

+

All plugins are (unfortunately) loaded in a single class loader.

+

Syntax

+
-plugin*       ::= plugin-def ( ',' plugin-def )*
+plugin-def     ::= qname ( ';' ( attribute | directive ) )*
+
+ +

The qname must identify a class, if it is an interface then this will load proxies to any external plugins. This class will be loaded with the -pluginpath and/or the path: directive.

+

Any attributes are passed to the plugin if it implements the aQute.bnd.servce.Plugin interface. Consult the actual plugin for the possible attributes.

+

The following directives are architected.

+ +

External Plugins

+

If the specified qname identifies an interface then the current repositories are searched for external plugins that implement this interface. Any found implementations are turned into a proxy that will lazily load the implementation class. The attributes in the clause will be given as properties when the plugin implements Closeable. External plugins that implement Closeable will be closed as normal plugins.

+

Typical Example

+

The following example installs an embedded FileRepo and will load all exporters from this repository.

+
-plugin.repo.main:\
+  aQute.lib.deployer.FileRepo; \
+    name='Main'; \
+    location=${build}/repo/main, \
+  aQute.bnd.service.export.Exporter;name=*
+
+ +

Errors & Warnings

+ + + +

Caveats

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/pluginpath.html b/org.bndtools.help/docs/instructions/pluginpath.html new file mode 100644 index 0000000000..78855c8f3a --- /dev/null +++ b/org.bndtools.help/docs/instructions/pluginpath.html @@ -0,0 +1,35 @@ + + + + +-pluginpath* PARAMETERS + + + +

-pluginpath* PARAMETERS

+ +

Directives

+ + +

The -pluginpath instruction allows you to define JAR files or directories that should be loaded into the local classloader for plugins. This is useful for plugins that are not embedded in bndlib and need to load their classes from external locations.

+

You can specify multiple -pluginpath clauses in different places, and they will be merged together. If a specified file does not exist, you can provide a URL to download it, and optionally a SHA-1 digest to verify the download. This ensures that all required plugin dependencies are available and loaded correctly at build time.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/pom.html b/org.bndtools.help/docs/instructions/pom.html new file mode 100644 index 0000000000..12684a6894 --- /dev/null +++ b/org.bndtools.help/docs/instructions/pom.html @@ -0,0 +1,138 @@ + + + + +-pom BOOLEAN | PROPERTIES + + + +

-pom BOOLEAN | PROPERTIES

+ + +

The -pom instruction can generate a pom derived from the manifest and store it in the +bundle. The groupId can be specified by the groupid key which defaults to the value of +the -groupid instruction. If neither the groupid key or the -groupid instruction +are specified, the groupId will be derived from the Bundle Symbolic Name by using +everything until the last '.' (bsn prefix) and the artifactId will be everything from the +last '.' to the end (bsn suffix).

+

The following properties are supported:

+

|Key |Default |Description | +|groupid |-groupid |The groupId to use. Will default to bsn prefix if no groupid is set.| +|artifactid |bundle symbolic name|The artifactId to use. Will default to bsn suffix if no groupid is set.| +|version |bundle version |The version to use. | +|where |META-INF/maven/<groupid>/<artifactid>/pom.xml|The location of the pom.xml file. Will default to pom.xml if no groupid is set.|

+

Note: When -pom is defined, then existing META-INF/maven/ subfolders will be removed, before the pom.xml is generated. This might remove folders which existed previously e.g. by unrolling jar files.

+

The -pom instruction can use any macro but the ${@bsn} and ${@version} macros +refer to the current JAR being built.

+

The -pom instruction will also attempt to convert the following headers to their POM counterpart:

+ +

|Parameters |Default |Description| +|email | |Email address (mandatory)| +|id |email |A developer id (defaults to email)| +|name | |Name of the developer| +|organization | |Name of the organization| +|organizationUrl | |URL of the organization| +|roles | |Roles of the developer (comma separated)| +|timezone | |Three letter time zone|

+
Bundle-Developers: \
+  Peter.Kriens@aQute.biz; \
+    name="Peter Kriens"; \
+    organization=aQute; \
+    roles="programmer,gopher"
+
+ + +

|Parameters |Default |Description| +|connection | |Read only connection| +|developerConnection | |Developer connection| +|url | |The URL for a web front end to your SCM system.|

+
Bundle-SCM: \
+    url=https://github.com/bndtools, \
+    connection=scm:git:https://github.com/bndtools/bnd, \
+    developerConnection=scm:git:git@github.com/bndtools/bnd
+
+ +

Example

+

The following example bnd file:

+
Bundle-SymbolicName: com.example.foo
+Bundle-Version: 1.2.3.qualifier
+-pom: true
+
+ +

Generates the following pom in pom.xml:

+
<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="" 
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+            <modelVersion>4.0.0</modelVersion>
+            <groupId>com.example</groupId>
+            <artifactId>foo</artifactId>
+            <version>1.2.3.qualifier</version>
+            <name>com.example.foo</name>
+</project>
+
+ +

You can override the different parts of the Maven coordinates:

+
Bundle-SymbolicName:          com.example.foo
+Bundle-Version:               1.2.3.qualifier
+Bundle-Developers:            Peter.Kriens@aQute.biz; \
+  name="Peter Kriens"; \
+  organization=aQute; \
+  roles="programmer,gopher"
+Bundle-SCM: url=https://github.com/bndtools, \
+  connection=scm:git:https://github.com/bndtools/bnd, \
+  developerConnection=scm:git:git@github.com/bndtools/bnd
+-pom: groupid=com.example, \
+  where=META-INF/maven/pom.xml, \
+  version=${versionmask;==;${Bundle-Version}}
+
+ +

Generates the following pom in META-INF/maven/pom.xml:

+
<project xmlns="http://maven.apache.org/POM/4.0.0" 
+    xmlns:xsi=""
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+            <modelVersion>4.0.0</modelVersion>
+            <groupId>com.example</groupId>
+            <artifactId>com.example.foo</artifactId>
+            <version>1.2</version>
+            <name>com.example.foo</name>
+            <scm>
+                <url>https://github.com/bndtools</url>
+                <connection>scm:git:https://github.com/bndtools/bnd</connection>
+                <developerConnection>scm:git:git@github.com/bndtools/bnd</developerConnection>
+            </scm>
+            <developers>
+                <developer>
+                    <id>Peter.Kriens@aQute.biz</id>
+                    <name>Peter Kriens</name>
+                    <organization>aQute</organization>
+                    <roles>
+                        <role>programmer</role>
+                        <role>gopher</role>
+                    </roles>
+                    <email>Peter.Kriens@aQute.biz</email>
+                </developer>
+            </developers>
+</project>
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/prepare.html b/org.bndtools.help/docs/instructions/prepare.html new file mode 100644 index 0000000000..c556832c29 --- /dev/null +++ b/org.bndtools.help/docs/instructions/prepare.html @@ -0,0 +1,56 @@ + + + + +-prepare makespec ( ',' makespec )* + + + +

-prepare makespec ( ',' makespec )*

+ + +

An typical use case for the -prepare instruction is the generation of CSS files from a less or sccs specification. The prepare instruction will execute a number of commands in the shell before it starts the build process.

+

The commands used in the shell must work on the platform. Since the shell is so different in a Windows environment this function is not guaranteed to work.

+

Example

+

The following example compiles typescript code in the typescript directory. The output goes to web/repository.js. To install the tsc command, see npm.

+
-prepare: \
+    web/foo.js <= typescript/*.ts ; \
+        command:=tsc -p typescript --out $@
+
+ +

Syntax

+
-prepare     ::= makespec ( ',' makespec )
+makespec     ::= dependency ( ';' parameter )+
+dependency   ::= PATH ( '<=' FILESPEC )?
+parameter    ::= command | report | name | env
+command      ::= 'command:=' <shell> # mandatory
+report       ::= 'report:=' PATTERN
+name         ::= 'name:=' STRING
+env          ::= key '=' value
+
+ +

A makespec defines a dependency in the file system. It must start with a file path, this is the output file of the command. It can be followed with a dependency. A dependency is a FILESPEC. The FILESPEC defines the set of input files to the command. If specified, then the command is only executed when the target file is older than any of the dependencies and the project bnd files.

+

It is possible to specify a name for the command, this name is then used for any error reporting.

+

The command parameter specifies the shell command. It must be a valid shell command. Any $@ and $< macros are replaced by the target file path and the set of files in the dependency.

+

The shell is supposed to support multiple commands (separate with ';') and pipes ('|'). The working directory the command will run in is the project directory.

+

Any attributes (i.e. not directives) are added as an environment variable for the command.

+

If the executed command provides diagnostic output with file names, line numbers, etc. then it is possible in some cases to report these to the IDE so the error/warning appears on the right place. This requires the specification of a regular expression. This regular expression must specify named groups. A named group is like (?<name>.*). The expression must find error messages from the console output or the error output.

+

The following names can be used in the regular expression:

+
file           relative file name
+line           zero based line number
+line-1         one based line number
+type           `error` | `warning`
+message        the message
+
+ +

For example, the report pattern for the Microsoft TypeScript compiler tsc:

+
"(^|\n)(?<file>[^(]+)\\((?<line>[0-9]+),(?<column>[0-9]+)\\):(?<message>[^\n]*)"
+
+ +

Path

+

It is possible to set the platforms command search path with the -PATH macro. This macro must contain a comma separated list of PATH, specifying places where to look. If this -PATH macro contains ${@} then this will be replaced with the platforms current PATH. By not specifying the ${@} it is possible to limit the available commands.

+



+ + diff --git a/org.bndtools.help/docs/instructions/preprocessmatchers.html b/org.bndtools.help/docs/instructions/preprocessmatchers.html new file mode 100644 index 0000000000..e31fed1839 --- /dev/null +++ b/org.bndtools.help/docs/instructions/preprocessmatchers.html @@ -0,0 +1,30 @@ + + + + +-preprocessmatchers SELECTOR + + + +

-preprocessmatchers SELECTOR

+ + +

During the -includeresource processing it is possible to pre-process the files that are copied into the JAR by enclosing the clause in curly braces ({}). Since this can create havoc when applied to text files bnd will attempt to skip binary files. To skip binary files, bnd uses a pre-process matchers list. This list is a standard selector. The default is:

+
!*.(jpg|jpeg|jif|jfif|jp2|jpx|j2k|j2c|fpx|png|gif|swf|doc|pdf|tiff|tif|raw|bmp|ppm|pgm|pbm|pnm|pfm|webp|zip|jar|gz|tar|tgz|exe|com|bin|mp[0-9]|mpeg|mov|):i, *
+
+ +

When bnd copies a file from a source to a directory it will match that name against this list. If it is one of the extensions listed, then it will not preprocess that file.

+

The default can be overridden with the -preprocessmatchers instruction.

+
-preprocessmatchers:    !OSGI-INF/*,*
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/privatepackage.html b/org.bndtools.help/docs/instructions/privatepackage.html new file mode 100644 index 0000000000..0020fac7b5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/privatepackage.html @@ -0,0 +1,33 @@ + + + + +-privatepackage PACKAGE-SPEC + + + +

-privatepackage PACKAGE-SPEC

+ + +

-privatepackage

+

The -privatepackage instruction specifies packages to include from the class path as private packages. Unlike the Private-Package header, this instruction is not included in the manifest. It is used to control which packages are bundled privately in the output JAR.

+

Example:

+
-privatepackage: com.example.internal.*
+
+ +

This instruction is useful for fine-grained control over bundle contents during the build process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/profile.html b/org.bndtools.help/docs/instructions/profile.html new file mode 100644 index 0000000000..54db34d3a0 --- /dev/null +++ b/org.bndtools.help/docs/instructions/profile.html @@ -0,0 +1,25 @@ + + + + +-profile KEY + + + +

-profile KEY

+ + +

The -profile instruction sets a prefix (profile key) that is used when a variable is not found in the current context. If a variable is missing, bnd will re-search for it using the pattern [<profile>]<key>, where <profile> is the value of the -profile instruction and <key> is the variable name.

+

This allows you to define profile-specific values for variables, making it easier to manage different build or runtime configurations within the same project. If no profile is set or the variable is not found under the profile, bnd will fall back to the default value.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/provider_policy.html b/org.bndtools.help/docs/instructions/provider_policy.html new file mode 100644 index 0000000000..0ab678c761 --- /dev/null +++ b/org.bndtools.help/docs/instructions/provider_policy.html @@ -0,0 +1,35 @@ + + + + +-provider-policy VERSION-MASK + + + +

-provider-policy VERSION-MASK

+ + +

The -provider-policy instruction defines the semantic versioning policy to be used when a type is a provider. A provider is in general a type that is implemented by classes that are responsible for the contract implied by the package. In contrast, a consumer is the party that just uses the contract defined in the package. For example, when you implement Event Admin, the org.osgi.service.event package is your responsibility so the types you need to implement like EventAdmin are provider types. (These types are annotated with a @ProviderType annotation.) A casual user of the Event Admin service will be a consumer, the EventHandler type is therefore annotated with a@ConsumerType.

+

The purpose of this distinction is semantic versioning. It turns out that the relation between a consumer and a provider is not symmetric. A provider is tightly bound to a contract while a consumer is expected to have backward compatibility. Virtually any change to the contract requires the provider to adapt while a consumer is in almost all cases protect against changes.

+

This asymmetry has a consequence for the semantic versioning. In the OSGi, the semantics are defined that a micro change does not affect the provider nor the consumer. A minor change affects the provider, and a major change affects both. Therefore, a bundle that implements a provider type must import a range from major.minor.micro ... major.minor+1.0. A bundle that implements a consumer type must import major.minor.micro ... major+1.0.0.

+

In theory, bnd could have hard coded these policies but there are always cases where the policy is just not right. The -provider-policy specifies the macro to use for calculating the version range. The default definition is:

+
-consumer-policy ${range;[==,+)} 
+-provider-policy ${range;[==,=+)}
+
+ +

The range macro works very much like the version macro. It uses a template to define a change the range/version.

+

The provider and consumer policy are global and this is not very convenient if you want to make an exception just for a specific bundle. For example, a bundle coming from Gavin King's Ceylon. For this reason, you can also specify a policy on an import:

+
Import-Package com.gavinking.*;version="${range;[--,++)}", *
+
+ +

The counterpart of the -provider-policy is of course the -consumer-policy.

+



+ + diff --git a/org.bndtools.help/docs/instructions/releaserepo.html b/org.bndtools.help/docs/instructions/releaserepo.html new file mode 100644 index 0000000000..de0a54b7b4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/releaserepo.html @@ -0,0 +1,34 @@ + + + + +-releaserepo* NAME ( ',' NAME ) * + + + +

-releaserepo* NAME ( ',' NAME ) *

+ + +

You can specify zero or more repository names to use when releasing a project.

+

The -releaserepo instruction aggregates the -releaserepo property and all properties that start with -releaserepo.. This makes it possible to set release repository names in different places.

+

If the -releaserepo instruction is set to the empty value, then releasing a project does nothing. If the -releaserepo instruction is unset, then releasing a project will release it to the first writable repository.

+

Example:

+
-releaserepo: releases, snapshots
+
+ +

This instruction is useful for managing release targets in multi-repository environments.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/remoteworkspace.html b/org.bndtools.help/docs/instructions/remoteworkspace.html new file mode 100644 index 0000000000..8255e7db2c --- /dev/null +++ b/org.bndtools.help/docs/instructions/remoteworkspace.html @@ -0,0 +1,37 @@ + + + + +-remoteworkspace (true|false) + + + +

-remoteworkspace (true|false)

+ + +

Launchpad is a library that enables testing in local JUnit settings. Launchpad needs access to the enclosing +bnd workspace. However, this workspace runs in another process then the test code. Launchpad will therefore +attempt to a workspace remote server.

+

For security reasons, this remote workspace server is not enabled by default. It requires:

+
-remoteworkspace        true
+
+ +

Remote Workspace servers can be nested. That is, you can run Eclipse and then Gradle on the same workspace. +Launchpad will use the latest initialized remote workspace.

+

Details

+

If you enable the remote workspace, its socket's port will be registered in the /cnf/cache/remotews directory.

+

The remote workspace server can only be accessed from the local machine on 127.0.0.1 to prevent outside +attacks.

+



+ + diff --git a/org.bndtools.help/docs/instructions/removeheaders.html b/org.bndtools.help/docs/instructions/removeheaders.html new file mode 100644 index 0000000000..b3a16fe131 --- /dev/null +++ b/org.bndtools.help/docs/instructions/removeheaders.html @@ -0,0 +1,24 @@ + + + + +-removeheaders KEY-SELECTOR ( '.' KEY-SELECTOR ) * + + + +

-removeheaders KEY-SELECTOR ( '.' KEY-SELECTOR ) *

+ + +

The -removeheaders instruction allows you to remove specific headers from the manifest of your bundle. You provide a list of header names or patterns, and any matching headers will be excluded from the final manifest. This is useful for cleaning up or customizing the manifest to meet specific requirements.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/reportconfig.html b/org.bndtools.help/docs/instructions/reportconfig.html new file mode 100644 index 0000000000..56deefc395 --- /dev/null +++ b/org.bndtools.help/docs/instructions/reportconfig.html @@ -0,0 +1,228 @@ + + + + +-reportconfig plugin-def ( ',' plugin-def )* + + + +

-reportconfig plugin-def ( ',' plugin-def )*

+ + +

The purpose of the -reportconfig instruction is to configure the content of the reports exported with the -exportreport instruction.

+

When a report is generated, a set of plugins is used to extract a specific piece of data from the source (for example, the information contain in metatypes from a bundle source). Those plugins are generally designed to not require a configuration and are silently ignored if they do not find any data, thus, this instruction should rarely be used.

+

Additional plugins can be declared and configured with the -plugin.* instruction and will be available for all your reports, however the -reportconfig instruction gives more control on the plugins that should be used when generating a specific report. This instruction diverges from the -plugins.* instruction as you can declare named configuration, for example -reportconfig.api-bundle:... will have the name api-bundle that you can then use for a specific report -exportreport:file.json;configName=api-bundle. In addition, this instruction allows to declare plugins with a short name instead of the canonical name of the plugin class (importFile instead of biz.aQute.bnd.reporter.plugins.entries.any.ImportResourcePlugin).

+

See -exportreport instruction documentation.

+

Syntax

+
-reportconfig.xxx  ::= plugin-def ( ',' plugin-def ) *
+plugin-def         ::= plugin | 'clearDefaults'
+plugin             ::= ( qname | plugin-name ) ( ';' parameters ) *
+plugin-name        ::= extended
+
+ +

where xxx is the name of the configuration.

+

Example

+

One use case is when you want a specific resource from a bundle in the report but where there is no plugins to extract it. For this you can use the importJarFile plugin which need the path to the resource inside the bundle and will import it into the report.

+

For example, if you need blueprint data:

+

bnb.bnd

+
-reportconfig.blueprint: importJarFile;path=OSGI-INF/blueprint/component.xml
+-exportreport: metadata.json;configName=blueprint
+
+ +

Clean configuration

+

When you set a -reportconfig.xxx instruction, a list of default plugins will be added to the specified list. If you do not want the default plugins you can use the special property clearDefaults:

+

bnb.bnd

+
-reportconfig.blueprint: \
+   importJarFile;path=OSGI-INF/blueprint/component.xml, \
+   clearDefaults
+
+ +

Plugins

+

This section describes the available plugins in Bnd, additional plugins may be provided by a specific build tool.

+

All plugins have the entryName property which can be set to override the name under which data will be aggregated into the reports (this corresponds to a tag name when serialised in XML):

+
 -reportconfig.bundle: metatypes;entryName=serviceConfigs
+
+ +

Any Entry

+

This plugin allows the user to define an arbitrary entry.

+ +
-reportconfig.api-bundle:anyEntry;key=bundleType;value=api
+
+ +

Import File

+

This plugin allows to add a local or remote file to the report. The type of the file can be: properties, manifest, XML and JSON.

+ +
-reportconfig.bundle:importFile;url=http://<...>/myFile.json
+
+ +

Import Jar File

+

This plugin allows to add a file contains in a bundle to the report. The type of the file can be: properties, manifest, XML and JSON.

+ +
-reportconfig.bundle:
+
+ +

CommonInfo

+

Add some common data to the report. If data are extracted from the workspace, the following properties will be read in the build.bnd file: ws-name, ws-description, ws-version, ws-icons, ws-docURL, ws-updateLocation, ws-licenses, ws-developers, ws-scm, ws-copyright, ws-vendor, ws-contactAddress; otherwise, the corresponding headers will be read. If data are extracted from a project, the above properties will be read in the bnd.bnd file but with a p- prefix, such as p-contactAddress.

+ +

Manifest

+

Add the OSGI headers to the report.

+ +

Components

+

Add a list of the declarative services.

+ +

Metatypes

+

Add a list of the metatypes.

+ +

File Name

+

Add the file name or the folder name in which the source is backed up.

+ +

Bundles

+

Add a list of bundle data (for example, the bundles built by a project).

+ +
-reportconfig.project:bundles;useConfig=api-bundle;excludes="com.domain.product.provider"
+
+ +

Code Snippets

+

Add a list of code snippet extracted from source files in a project. By default, source files containing code snippets must be located in a <root test source dir>/examples folder and its sub directories (eg; src/test/java/examples/**). The actual supported file types are: java.

+

Code snippets can either be a single sample code with a title and a description or have multiple steps.

+ +

Java Code Snippets

+

You can either export a full type or a method. For the snippet to be extracted you must add a comment block to the type or the method. The comment must contain the ${snippet } tag with the following optional properties:

+ +

Here is an example illustrating a code snippet with steps:

+
/**
+ * ${snippet title=How to Print Something in Java, description="In this example we will show how to
+ * print a string to the console.", groupName=print} 
+ */
+public class PrintExample {
+
+  /**
+   * ${snippet title=Print No New Line, description="Here, we print without a new line at the end.",
+   * parentGroup=print, includeDeclaration=false} 
+   */
+  public void printNoNewLine() {
+    System.out.print("Hello");
+  }
+
+  /**
+   * ${snippet title=Print With New Line, description="Here, we print with a new line at the end.",
+   * parentGroup=print, includeDeclaration=false} 
+   */
+  public void printWithNewLine() {
+    System.out.println("Hello");
+  }
+}
+
+ +

Which will result in the following json object:

+
{ 
+   "id": "PrintExample",
+   "title":"How to Print Something in Java",
+   "description":"In this example we will show how to print a string to the console.",
+   "steps":[
+      {
+         "id": "printNoNewLine",
+         "title":"Print No New Line",
+         "description":"Here, we print without a new line at the end.",
+         "programmingLangague":"java",
+         "codeSnippet":"System.out.print(\"Hello\");"
+      },
+      {
+         "id": "printWithNewLine",
+         "title":"Print With New Line",
+         "description":"Here, we print with a new line at the end.",
+         "programmingLangague":"java",
+         "codeSnippet":"System.out.println(\"Hello\");"
+      }
+   ]
+}
+
+ +

Projects

+

Add a list of project data (for example, the projects built by the workspace).

+ +
-reportconfig.ws:projects;useConfig=bnd-proj;excludes="maven-index"
+
+ +

Maven Coordinate

+

Add the maven coordinate of the bundle (extracted from the pom.properties file).

+ +

Gogo Commands

+

Add a list of Gogo commands.

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/reportnewer.html b/org.bndtools.help/docs/instructions/reportnewer.html new file mode 100644 index 0000000000..7457c274e5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/reportnewer.html @@ -0,0 +1,33 @@ + + + + +-reportnewer BOOLEAN + + + +

-reportnewer BOOLEAN

+ + +

-reportnewer

+

The -reportnewer instruction reports any entries that were added to the build since the last JAR was made. This is useful for tracking changes and ensuring that only new or updated files are included in the build output.

+

Example:

+
-reportnewer: true
+
+ +

When enabled, bnd will output a list of files that are newer than the previous build.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/reproducible.html b/org.bndtools.help/docs/instructions/reproducible.html new file mode 100644 index 0000000000..c8a362ddb8 --- /dev/null +++ b/org.bndtools.help/docs/instructions/reproducible.html @@ -0,0 +1,34 @@ + + + + +-reproducible BOOLEAN | TIMESTAMP + + + +

-reproducible BOOLEAN | TIMESTAMP

+ + +

To ensure the bundle can be built in a reproducible manner, the timestamp of the zip entries is set to the fixed time 1980-02-01T00:00:00Z when the value of this instruction is true. +The value can also be set to either an ISO-8601 formatted time or the number of seconds since the epoch which is used as the timestamp for the zip entries. +The Bnd-LastModified header is also omitted from the manifest. +The default value is false.

+

For example:

+
-reproducible: true
+-reproducible: 1641127394
+-reproducible: 2022-01-02T12:43:14Z
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/require_bnd.html b/org.bndtools.help/docs/instructions/require_bnd.html new file mode 100644 index 0000000000..d7e9d0c629 --- /dev/null +++ b/org.bndtools.help/docs/instructions/require_bnd.html @@ -0,0 +1,38 @@ + + + + +-require-bnd (FILTER ( ',' FILTER )* )? + + + +

-require-bnd (FILTER ( ',' FILTER )* )?

+ + +

-require-bnd

+

The -require-bnd instruction allows you to specify a filter that must match the Bnd version for the build to proceed. If the filter does not match, bnd will generate an error and stop the build. This is useful for enforcing minimum or specific Bnd versions in your build environment.

+

Example:

+
-require-bnd: version>=7.0.0
+
+ +

If not set, any Bnd version will be accepted.

+

Each specified filter must evaluate to true for the running version of Bnd in the version attribute. Since the values of the instruction are filter expressions, they need to quoted so the filter operators are not processed by Bnd.

+

This instruction can be useful when the workspace requires a feature of Bnd introduced in some version of Bnd. For example:

+
-require-bnd: "(version>=4.3.0)"
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/resolve.effective.html b/org.bndtools.help/docs/instructions/resolve.effective.html new file mode 100644 index 0000000000..5ac5498bb3 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolve.effective.html @@ -0,0 +1,44 @@ + + + + +-resolve.effective qname (',' qname ) + + + +

-resolve.effective qname (',' qname )

+ + +

Each requirement and capability has an effective or is effective=resolve. An effective of resolve is always processed by the resolver.However, in (very) special cases it is necessary to provide more rules.

+

The -resolve.effective syntax is as follows:

+
-resolve.effective  ::= effective ( ',' effective )*
+effective       ::= NAME (';skip:=' skip )
+skip            ::= skip = '"' namespace ( ',' namespace ) * '"'
+
+ +

The simplest model is to just list the names, for example:

+
-resolve.effective: resolve,active
+
+ +

In this case, the resolver will only look at requirements that are either resolve or active.

+

Adding a meta effective could then be:

+
-resolve.effective: resolve,active, meta
+
+ +

However, in very, very rare (usually error) cases it is necessary to exclude certain namespaces. This can be done by using the skip: directive.

+
-resolve.effective: resolve,active, meta;skip:='osgi.extender,osgi.wiring.package'
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/resolve.excludesystem.html b/org.bndtools.help/docs/instructions/resolve.excludesystem.html new file mode 100644 index 0000000000..a8380ec9a2 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolve.excludesystem.html @@ -0,0 +1,24 @@ + + + + +-resolve.excludesystem true|false + + + +

-resolve.excludesystem true|false

+ + +

This property has no meaning in the normal configuration. It is used by code that needs to +have the system resource in the wiring. Normally the wiring excludes the system resource. +However, sometimes it is necessary to see the full solution.

+



+ + diff --git a/org.bndtools.help/docs/instructions/resolve.html b/org.bndtools.help/docs/instructions/resolve.html new file mode 100644 index 0000000000..e5f7deb0b5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolve.html @@ -0,0 +1,93 @@ + + + + +-resolve (manual|auto|beforelaunch|batch|cache) + + + +

-resolve (manual|auto|beforelaunch|batch|cache)

+ +

Directives

+ + +

The bnd workspace can use a resolver to calculate the content of the -runbundles instruction based on a set of initial requirements. The bndtools GUI can manually resolve the initial requirements but through the -resolve instruction it is possible to calculate the -runbundles when the file is saved or just before the -runbundles are used in the launch.

+

The values are:

+ +

Example

+
-resolve beforelaunch
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/resolve.preferences.html b/org.bndtools.help/docs/instructions/resolve.preferences.html new file mode 100644 index 0000000000..9662cfb613 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolve.preferences.html @@ -0,0 +1,47 @@ + + + + +-resolve.preferences qname ( ',' qname ) + + + +

-resolve.preferences qname ( ',' qname )

+ + +

The resolver normally finds a lost of capabilities that match a given requirement. This list has an order defined by the context. However, in certain occasions this order is not the desired order. The -resolve.preferences allows you to override this context order. It is an ordered list of Bundle Symbolic Names. The list of capabilities will always be adjusted to have the bundles in the -resolver.preferences always first when they are present.

+

For example:

+
`-resolve.preferences` : \
+    com.example.bundle.most.priority, \
+    com.example.bundle.less.priority, \
+    com.example.whatever
+
+ +

Given that for a requirement the capabilties come from:

+
com.example.some.bundle, 
+om.example.bundle.less.priority, 
+com.example.another.bundle, 
+com.example.most.priority
+
+ +

Then the resulting order will be:

+
com.example.most.priority
+om.example.bundle.less.priority, 
+com.example.some.bundle, 
+com.example.another.bundle,
+
+ +

Preferences should only be used when blacklisting is not a better solution.

+



+ + diff --git a/org.bndtools.help/docs/instructions/resolve.reject.html b/org.bndtools.help/docs/instructions/resolve.reject.html new file mode 100644 index 0000000000..5e3eeda470 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolve.reject.html @@ -0,0 +1,63 @@ + + + + +-resolve.reject ( '@'? namespace ( ';filter:=' FILTER )? ), + + + +

-resolve.reject ( '@'? namespace ( ';filter:=' FILTER )? ),

+ + +

The resolver will request capabilities from the resolve context. In bnd, the resolve hook can be +used to reject some of these capabilities. The -resolve.reject instruction can control the default +hook. Without this instruction, nothing is rejected and the resolver sees all capabilities. With this +hook it is possible to reject

+ +

To directly reject a namespace foo, the instruction is simply:

+
-resolve.reject foo
+
+ +

This will reject any capability in the namespace foo. To reject a namespace foo where a filter matches, the instruction is:

+
-resolve.reject foo;filter:='(foo=3)`
+
+ +

This will reject any capability in the namespace foo that has an attribute foo that has the value 3.

+

Sometimes it is necessary to reject a capability depending on its resource. For example, you want to reject +capabilities that come from fragments. You can achieve this by prefixing the requirement with +a @ (commercial at sign). For example, if you want to reject any capabilities that come from a resource that has identity type osgi.fragment.

+
-resolve.reject @osgi.identity;filter:='(type=osgi.fragment)'
+
+ +

You can add multiple requirements in the specification. These requirements will be or'ed together. The following + specification:

+
-resolve.reject @foo, baz
+
+ +

Will reject any capabiliy from a resource that has a foo capability and it will remove all baz capabilities.

+

Example

+

Before bnd release 7, the resolver always rejected resources that were neither a bundle nor a fragment. This was +changed to allow more scenarios. The filtering was moved to the list of bundles where it is necessary that the resources +are all bundles.

+

This should normally not make a difference during resolving. However, in some cases you want to have the old +situation. The following example restores the pre release 7 situation.

+
-resolve.reject     @osgi.identity;filter:='(!(|(type=osgi.bundle)(type=osgi.fragment)))'
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/resolvedebug.html b/org.bndtools.help/docs/instructions/resolvedebug.html new file mode 100644 index 0000000000..ed8c67eec1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/resolvedebug.html @@ -0,0 +1,28 @@ + + + + +-resolvedebug INTEGER + + + +

-resolvedebug INTEGER

+ + +

When resolving, the -resolvedebug instruction can be used to request debug information about the resolve is displayed to System.out. The value 0 turns off displaying debug information. The values 1, 2, and 3 display progressively more debug information.

+
-resolvedebug: 1
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/resourceonly.html b/org.bndtools.help/docs/instructions/resourceonly.html new file mode 100644 index 0000000000..9e5df68fab --- /dev/null +++ b/org.bndtools.help/docs/instructions/resourceonly.html @@ -0,0 +1,33 @@ + + + + +-resourceonly BOOLEAN + + + +

-resourceonly BOOLEAN

+ + +

-resourceonly

+

The -resourceonly instruction tells bnd to ignore warnings if the bundle contains only resources and no classes. This is useful for bundles that are intended to provide configuration files, images, or other non-code assets.

+

Example:

+
-resourceonly: true
+
+ +

When set, bnd will not warn about the absence of classes in the bundle.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runblacklist.html b/org.bndtools.help/docs/instructions/runblacklist.html new file mode 100644 index 0000000000..3b9b1195c1 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runblacklist.html @@ -0,0 +1,27 @@ + + + + +-runblacklist requirement (',' requirement) + + + +

-runblacklist requirement (',' requirement)

+ + +

The blacklist is a set of requirements. These requirements are used to get a set of resources from the repositories that match any of these requirements. This set is then removed from any result from the repositories, effectively making it impossible to use.

+

For example:

+
-runblacklist: \
+    osgi.identity;filter:='(osgi.identity=com.foo.bad.bundle)'
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runbuilds.html b/org.bndtools.help/docs/instructions/runbuilds.html new file mode 100644 index 0000000000..c0e362da77 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runbuilds.html @@ -0,0 +1,32 @@ + + + + +-runbuilds BOOLEAN + + + +

-runbuilds BOOLEAN

+ + +

The -runbuilds instruction controls whether the bundles built by the current project should be automatically added to the -runbundles list when running or testing the project.

+ +

This instruction is useful for controlling which bundles are available at runtime, especially when you want to test or launch only a subset of the bundles produced by your project.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runbundles.html b/org.bndtools.help/docs/instructions/runbundles.html new file mode 100644 index 0000000000..3d0578e520 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runbundles.html @@ -0,0 +1,72 @@ + + + + +-runbundles* REPO-ENTRY ( ',' REPO-ENTRY )* + + + +

-runbundles* REPO-ENTRY ( ',' REPO-ENTRY )*

+ +

Directives

+ + +

The runbundles instruction is used to specify which bundles should be installed when a framework is started. This is the primary mechanism to run applications directly from bnd/bndtools. A bundle listed in -runbundles can be either a workspace bundle (a bundle created by one of the workspace's projects) or a bundle from one of the configured repositories. Note that all required bundles to run the application should be listed, transitive dependencies are not handles automatically so that there is full control over the runtime.

+

This list can be maintained manually it is normally calculated by the resolver. That is, when a resolve is run then it will, without warning, override this list.

+

For example:

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)',\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1)',\
+    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
+    ...
+    osgi.enroute.twitter.bootstrap.webresource;version='[3.3.5,3.3.6)',\
+    osgi.enroute.web.simple.provider;version='[2.1.0,2.1.1)'
+
+ +

Start Levels

+

Some launchers support startlevels and the -runbundles instruction therefore has a startlevel attribute. This attribute +must be a positive integer larger than 0.

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)'; startlevel=100,\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1)'; startlevel=110,\
+    ...
+
+ +

Since the common workflow is to use the resolver to calculate the set of run bundles, any start level settings +would be overridden after the next resolve. There are the following solutions.

+

Use the -runstartlevel instruction to let the resolver calculate the start level ordering. In that case the +resolver will add the startlevel attribute.

+

Use the decoration facility. With the decoration facility you can augment the -runbundles instruction by +specifying the -runbundles+ property (or the -runbundles++ if you want to add literals). The keys are glob expressions +and any attributes or directives will be set (or overridden) on the merged -runbundles instruction.

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)',\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1)',\
+    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
+
+-runbundles+: \
+    org.apache.felix.servlet-api;startlevel=100, \
+    *;startlevel=110
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runee.html b/org.bndtools.help/docs/instructions/runee.html new file mode 100644 index 0000000000..0e8174437d --- /dev/null +++ b/org.bndtools.help/docs/instructions/runee.html @@ -0,0 +1,43 @@ + + + + +-runee EE + + + +

-runee EE

+ + +

The -runee instruction adds the capabilities of an execution environment to the system capabilities. Every Java edition has a set of standard packages and OSGi has also defined a number of execution environments that define which packages can be found. The -runee allows these capabilities to be defined by using the name of the execution environment. Additionally, this instruction also adds an osgi.ee requirement with the given name and version. You can use the following execution environment names:

+
OSGi/Minimum-1.0
+OSGi/Minimum-1.1 
+OSGi/Minimum-1.2
+JRE-1.1
+J2SE-1.2
+J2SE-1.3
+J2SE-1.4
+J2SE-1.5
+JavaSE-1.6
+JavaSE-1.7
+JavaSE/compact1-1.8
+JavaSE/compact2-1.8
+JavaSE/compact3-1.8
+JavaSE-1.8
+JavaSE-9
+
+ +

An example:

+
-runee: JavaSE-1.8
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runenv.html b/org.bndtools.help/docs/instructions/runenv.html new file mode 100644 index 0000000000..56653fc82a --- /dev/null +++ b/org.bndtools.help/docs/instructions/runenv.html @@ -0,0 +1,30 @@ + + + + +-runenv PROPERTIES + + + +

-runenv PROPERTIES

+ + +

-runenv

+

The -runenv instruction specifies system properties to set when launching the application. This is useful for configuring the runtime environment, such as setting ports, feature flags, or other JVM properties.

+

Example:

+
-runenv: my.property=value, another.property=1234
+
+ +

These properties will be set in the local JVM when the workspace is started.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runframework.html b/org.bndtools.help/docs/instructions/runframework.html new file mode 100644 index 0000000000..929de36d4d --- /dev/null +++ b/org.bndtools.help/docs/instructions/runframework.html @@ -0,0 +1,28 @@ + + + + +-runframework ( 'none' | 'services' | ANY )? + + + +

-runframework ( 'none' | 'services' | ANY )?

+ + +

The -runframework instruction sets the type of framework to run when launching an OSGi application. If set to none, an internal dummy framework is used. If set to services or any other value, the Java META-INF/services mechanism is used to locate the FrameworkFactory implementation.

+

Note: The name of this instruction is somewhat confusing due to historical reasons. In most cases, you should use the -runfw instruction to specify the actual framework JAR. The -runframework instruction is only needed if you want to control the framework discovery mechanism or use a dummy framework for testing purposes.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runframeworkrestart.html b/org.bndtools.help/docs/instructions/runframeworkrestart.html new file mode 100644 index 0000000000..770c6703f5 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runframeworkrestart.html @@ -0,0 +1,27 @@ + + + + +-runframeworkrestart BOOLEAN + + + +

-runframeworkrestart BOOLEAN

+ + +

Any bundle can stop the framework. After stopping, the launcher receives a notification and normally +exit the process with System.exit. In some cases, usually testing, it is necessary to do a restart +in the local VM.

+

If -runframeworkrestart is set to true, the launcher will not do a hard exit after the framework is stopped, +but will restart the framework after doing the normal clean up.

+

The launcher keeps a system property launcher.framework.restart.count that is set to the iteration, it is initially zero.

+



+ + diff --git a/org.bndtools.help/docs/instructions/runfw.html b/org.bndtools.help/docs/instructions/runfw.html new file mode 100644 index 0000000000..815ded3a3c --- /dev/null +++ b/org.bndtools.help/docs/instructions/runfw.html @@ -0,0 +1,27 @@ + + + + +-runfw REPO-ENTRY + + + +

-runfw REPO-ENTRY

+ + +

The -runfw instruction sets the framework to use. This framework will be added to the -runpath. Any exported packages or capabilities listed in the manifest of the framework are automatically added to the system capabilities.

+

For example:

+
-runfw: org.eclipse.osgi; version=3.10
+
+ +

Note – Do not use runframework, this instruction is deprecated and had very different intent and syntax.

+



+ + diff --git a/org.bndtools.help/docs/instructions/runjdb.html b/org.bndtools.help/docs/instructions/runjdb.html new file mode 100644 index 0000000000..1413e6fa7a --- /dev/null +++ b/org.bndtools.help/docs/instructions/runjdb.html @@ -0,0 +1,49 @@ + + + + +-runjdb ADDRESS + + + +

-runjdb ADDRESS

+ + +

-runjdb

+

The -runjdb instruction specifies a JDB (Java Debugger) socket transport address to use when launching the application outside a debugger. This allows the debugger to attach to the running process for debugging purposes.

+

Example:

+
-runjdb: localhost:10001
+
+ +

The address can include a host name or IP address and a port. This is useful for remote debugging scenarios.

+

This instruction launches the VM with the

+
-agentlib:jdwp=transport=dt_socket,server=y,address=<address>,suspend=y
+
+ +

command line argument.

+

The socket transport address can include a host name (or IP address) and a port. For example:

+
-runjdb: localhost:10001
+
+ +

The socket transport address can be just a port number. For example:

+
-runjdb: 10001
+
+ +

Note: Starting with Java 9, using just a port number means that the launched VM will only listen on localhost for the connection. If you want to remote debug, you will need to specify a host name (or IP address), or an asterisk (*) to accept from any host. For example:

+
-runjdb: *:10001
+
+ +

If the socket transport address starts with a minus sign (-), then the launched VM is not suspended: suspend=n. The minus sign is removed from the socket transport address before it is used for the address option.

+

If the specified socket transport address is not a port number or a host:port value, then the address 1044 is used.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runkeep.html b/org.bndtools.help/docs/instructions/runkeep.html new file mode 100644 index 0000000000..4c03bf5b6f --- /dev/null +++ b/org.bndtools.help/docs/instructions/runkeep.html @@ -0,0 +1,35 @@ + + + + +-runkeep true | false + + + +

-runkeep true | false

+ + +

-runkeep

+

The -runkeep instruction decides whether to keep the framework storage directory between launches. When set to true, the storage directory is preserved, which can be useful for debugging or maintaining state between runs.

+

The -runkeep instruction is particularly useful in scenarios where you need to persist data across different runs of the framework. For instance, if your application generates logs, caches data, or requires a specific directory structure to function correctly, setting -runkeep to true will ensure that these elements are not removed between launches.

+

However, one should be cautious while using this option, as preserving the storage directory might lead to outdated or corrupted data being used in subsequent runs. It is generally recommended to use the default setting (i.e., -runkeep: false) unless there is a specific need to retain the storage directory.

+

Example:

+
-runkeep: true
+
+ +

By default, the storage directory is deleted between launches.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runnoreferences.html b/org.bndtools.help/docs/instructions/runnoreferences.html new file mode 100644 index 0000000000..f9c9d45519 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runnoreferences.html @@ -0,0 +1,33 @@ + + + + +-runnoreferences BOOLEAN + + + +

-runnoreferences BOOLEAN

+ + +

-runnoreferences

+

The -runnoreferences instruction controls whether the reference: URL scheme is used for installing bundles in the OSGi installer. On non-Windows systems, reference: URLs are used by default for efficiency. Setting -runnoreferences: true disables this behavior and uses regular file URLs instead. On Windows, this instruction is ignored because reference: URLs are never used due to file locking issues.

+

Example:

+
-runnoreferences: true
+
+ +

Use this instruction if you need to avoid reference: URLs for compatibility or deployment reasons.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runoptions.html b/org.bndtools.help/docs/instructions/runoptions.html new file mode 100644 index 0000000000..b44873ba19 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runoptions.html @@ -0,0 +1,19 @@ + + + + +-runoptions + + + +

-runoptions

+ + + diff --git a/org.bndtools.help/docs/instructions/runpath.html b/org.bndtools.help/docs/instructions/runpath.html new file mode 100644 index 0000000000..0ebd9469ef --- /dev/null +++ b/org.bndtools.help/docs/instructions/runpath.html @@ -0,0 +1,45 @@ + + + + +-runpath REPO-ENTRY ( ',' REPO-ENTRY ) + + + +

-runpath REPO-ENTRY ( ',' REPO-ENTRY )

+ +

Directives

+ + +

An OSGi application will have a set of bundles and an environment created by the framework and any additional JARs on the class path. The -runpath instruction sets these additional bundles. These JARs can actually export packages and provide capabilities that the launcher will automatically add to the system capabilities. The resolver will do the same. Any packages exported by bundles or provided capabilities on the -runpath are automatically added to the system capabilities.

+

The -runpath instruction allows you to specify additional JARs that should be included on the class path of the remote VM when running an OSGi application. These JARs can export packages and provide capabilities that are automatically added to the system capabilities, making them available to the resolver and the launcher.

+

This is particularly useful for including frameworks or other dependencies that are not part of the main set of bundles but are required for the application to function correctly.

+

For example:

+
-runpath: \
+    com.foo.bar;version=1, \
+    file.jar; version=file
+
+ +
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runprogramargs.html b/org.bndtools.help/docs/instructions/runprogramargs.html new file mode 100644 index 0000000000..ce3ae67579 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runprogramargs.html @@ -0,0 +1,25 @@ + + + + +-runprogramargs + + + +

-runprogramargs

+ + +

The -runprogramargs instruction allows you to specify additional arguments that will be passed to the main program when it is launched. These arguments are appended to the command line after all other options and can be used to control the behavior of your application at runtime.

+

This is useful for providing custom parameters, flags, or configuration values to your application without modifying the code or build process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runproperties.html b/org.bndtools.help/docs/instructions/runproperties.html new file mode 100644 index 0000000000..64fd865e8a --- /dev/null +++ b/org.bndtools.help/docs/instructions/runproperties.html @@ -0,0 +1,25 @@ + + + + +-runproperties PROPERTIES + + + +

-runproperties PROPERTIES

+ + +

The -runproperties instruction allows you to define system properties that will be set for the remote Java Virtual Machine (JVM) when your application is launched. These properties are passed as -Dkey=value arguments and can be used to configure the runtime environment, control application behavior, or provide configuration values.

+

This is useful for setting environment-specific options or overriding default values without modifying your application's code.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runprovidedcapabilities.html b/org.bndtools.help/docs/instructions/runprovidedcapabilities.html new file mode 100644 index 0000000000..dd9ddb4b87 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runprovidedcapabilities.html @@ -0,0 +1,31 @@ + + + + +-runprovidedcapabilities + + + +

-runprovidedcapabilities

+ + +

-runprovidedcapabilities

+

The -runprovidedcapabilities instruction is used with the -distro instruction to specify extra capabilities that are provided by the target system but not listed in the distro file. This helps the resolver understand what is available at runtime.

+

The -runprovidedcapabilities instruction allows you to declare additional capabilities for a distribution that are not explicitly mentioned in the distribution file. By using this instruction, you enable the resolver to take into account these extra capabilities when determining the set of available features and functionalities in the target environment. This can be particularly useful in scenarios where certain capabilities are provided by the system but are not included in the default distribution configuration.

+

Example:

+
-runprovidedcapabilities: some.namespace;some.namespace=foo
+
+ +

This instruction is only relevant when working with distribution-based resolves.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runremote.html b/org.bndtools.help/docs/instructions/runremote.html new file mode 100644 index 0000000000..fb0473cc66 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runremote.html @@ -0,0 +1,19 @@ + + + + +-runremote + + + +

-runremote

+ + + diff --git a/org.bndtools.help/docs/instructions/runrepos.html b/org.bndtools.help/docs/instructions/runrepos.html new file mode 100644 index 0000000000..68fbd365ee --- /dev/null +++ b/org.bndtools.help/docs/instructions/runrepos.html @@ -0,0 +1,75 @@ + + + + +-runrepos REPO-NAME ( ',' REPO-NAME )* + + + +

-runrepos REPO-NAME ( ',' REPO-NAME )*

+ + +

The -runrepos instruction is used to restrict or order the available repositories. A bndrun file (see Resolving) can be based on a workspace or can be standalone. In the workspace case the, the repositories are defined in build.bnd or in a *.bnd file in the cnf/ext directory as bnd plugins. In the standalone case the repositories are either OSGi XML repositories listed in the -standalone instruction or they are also defined as plugins but now in the bndrun file.

+

In both cases there is an ordered list of repositories. In the -standalone it is easy to change this order or exclude repositories. However, in the workspace case this is harder because the set of repositories is shared with many other projects. The -runrepos can then be used to exclude and reorder the list repositories. It simply lists the names of the repositories in the desired order. Each repository has its own name.

+

If -runrepos is ommited then all repositories having either no tags or the tag resolve will be included for resolution. +You can exclude certain repositories by assigning it a tag different than resolve (e.g. <<EMTPY>> or foobar). See Tagging of repository plugins for more details.

+

Note The name of a repository is not well defined. It is either the name of the repository or the toString() result. In the later case the name is sometimes a bit messy.

+

Example 1: include specific repos

+
-runrepos: Maven Central, Main, Distro
+
+ +

This includes exactly the three repositories.

+

Example 2: include all repos

+ +

e.g. a .bndrun file without -runrepos would include the following repos in the resolution:

+
aQute.bnd.repository.maven.provider.MavenBndRepository;\
+        tags = "resolve"; \
+        name="Maven Central A";\
+        releaseUrl="${mavencentral}";\
+        snapshotUrl="${ossrh}";\
+        index="${.}/central.mvn";\
+        readOnly=true,\
+
+ +

because it has the resolve tag

+

and also

+
aQute.bnd.repository.maven.provider.MavenBndRepository;\
+        name="Maven Central B";\
+        releaseUrl="${mavencentral}";\
+        snapshotUrl="${ossrh}";\
+        index="${.}/central.mvn";\
+        readOnly=true,\
+
+ +

because there is no tags at all.

+

Example 3: include all repos, except some

+ +

For example the following repository definition in /cnf/build.bnd would be excluded:

+
aQute.bnd.repository.maven.provider.MavenBndRepository;\
+        tags = "<<EMPTY>>"; \
+        name="Maven Central";\
+        releaseUrl="${mavencentral}";\
+        snapshotUrl="${ossrh}";\
+        index="${.}/central.mvn";\
+        readOnly=true,\
+
+ +

because it has a <<EMPTY>> tag (and thus no resolve tag).

+

An example use case is exclude the baseline-repository from resolution. In the case, you would not add the resolve tag to the baseline-repo, and then it won't be considered for resolution in a .bndrun.

+



+ + diff --git a/org.bndtools.help/docs/instructions/runrequires.html b/org.bndtools.help/docs/instructions/runrequires.html new file mode 100644 index 0000000000..648057960e --- /dev/null +++ b/org.bndtools.help/docs/instructions/runrequires.html @@ -0,0 +1,79 @@ + + + + +-runrequires REQUIREMENT ( ',' REQUIREMENT )* + + + +

-runrequires REQUIREMENT ( ',' REQUIREMENT )*

+ + +

The -runrequires instruction specifies root requirements for a resolve operation. These requirements are input into the resolver +which generates a list of bundles (the -runbundles list) that can satisfy the requirements.

+

Each requirement must be in the format of an entry in the OSGi standard Require-Capability header. See Section 3.3.6 ("Bundle Requirements") of OSGi Core Release 6 specification.

+

A requirement can specify any arbitrary namespace, including but not limited to those listed in Chapter 8 ("Framework Namespaces Specification") of OSGi Core Release 6 specification and Chapter 135 ("Common Namespaces Specification") of OSGi Compendium Release 6.

+

Bnd also supports alias namespaces -- see below.

+

Example

+
-runrequires: \
+    osgi.identity; filter:='(osgi.identity=org.example.foo)',\
+    osgi.identity; filter:='(&(osgi.identity=org.example.bar)(version>=1.0)(!(version>=2.0)))'
+
+ +

This specifies a requirement for the resource identified as "org.example.foo" (with any version) AND the resource identified as "org.example.bar" with version in the range 1.0 inclusive to 2.0 exclusive.

+

Requirement Aliases

+

To ease manual entry of requirements bnd supports alias namespaces which translate to standard namespaces and filters.

+

In all cases, attributes and directives that are not consumed by the alias are passed through to the generated requirement. For example if the bnd.identity alias is used with a directive of resolution:=optional then the generated osgi.identity requirement shall also have the directive resolution:=optional.

+

The following aliases are supported:

+

bnd.identity

+

The bnd.identity namepace alias takes the following attributes:

+ +

Example:

+
-runrequires:\
+    bnd.identity; id=org.example.foo,\
+    bnd.identity; id=org.example.bar; version=1.0,\
+    bnd.identity; id=org.example.baz; version='[1.0,2.0)'
+
+ +

is translated to:

+
-runrequires:\
+    osgi.identity; filter:='(osgi.identity=org.example.foo)',\
+    osgi.identity; filter:='(&(osgi.identity=org.example.bar)(version>=1.0))',\
+    osgi.identity; filter:='(&(osgi.identity=org.example.baz)(version>=1.0)(!(version>=2.0)))'
+
+ +

bnd.literal

+

The bnd.literal alias can be used if you need to create a literal requirement that has a namespace clashing with one of the aliases. For example if you want to have a requirement with the literal namespace bnd.identity, i.e. not processed as an alias.

+

Only one attribute is used:

+ +

Example:

+
-runrequires:\
+    bnd.literal; bnd.literal=bnd.identity; filter:='(bnd.identity=foo)',\
+    bnd.literal; bnd.literal=bnd.literal; filter:='(bnd.literal=bar)'
+
+ +

is translated to:

+
-runrequires:\
+    bnd.identity; filter:='(bnd.identity=foo)',\
+    bnd.literal; filter:='(bnd.literal=bar)'
+
+ +

See Also

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runstartlevel.html b/org.bndtools.help/docs/instructions/runstartlevel.html new file mode 100644 index 0000000000..47ddacd5a2 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runstartlevel.html @@ -0,0 +1,160 @@ + + + + +-runstartlevel ( order | begin | step )* + + + +

-runstartlevel ( order | begin | step )*

+ +

Directives

+ + +

After a resolve the resolver calculates a number of resources that are mapped to bundles. This mapping can +include ordering and assigned startlevels. The basic instruction that parameterizes this is -runstartlevel.

+

Default behavior when not set

+

If -runstartlevel is not set the set of -runbundles will be sorted by name and version after which it is merged with the existing +-runbundles. Setting the -runstartlevel makes it possible to let bnd assign startlevels based on different +ordering strategies.

+

Syntax

+

This instruction has the following syntax:

+
-runstartlevel      ::= runstartlevel ( ',' runstartlevel )
+runstartlevel       ::  order | begin | step
+order               ::= 'order=' ORDER
+ORDER               ::= 
+        'leastdependenciesfirst' 
+    |   'leastdependencieslast'
+    |   'random'
+    |   'sortbynameversion'
+    |   'mergesortbynameversion'
+begin               ::= 'begin=' NUMBER
+step                ::= 'step=' NUMBER
+
+ +

The final -runstartlevel flattens the properties so that the last of each of order, begin, or step will be used.

+

Order Types

+

The value of order can take on the following values:

+ +

The topological sorting algorithm is based on Tarjan. It can handle cyclic dependencies well. However, cyclic dependencies +make the ordering not perfect.

+

Startlevels

+

After the resources have been resolved they are sorted according to the order. If the begin attribute is set and +higher than 0, the resources will be assigned a startlevel that starts at the given value. By default, the step for each +bundle is 10. (A lesson taught to us by BASIC) The step can be overridden by setting the step value.

+

If the begin value is not set, or it is set to a value < 1, then no startlevel attribute is added. However, the +order of the -runbundles will be in the specified order. In most cases, this is then some kind of natural ordering +since launchers start these

+

If you set the step to 0 then all bundles will be assigned the same startlevel. However, the -runbundles has the proper +order.

+

Example

+
-runstartlevel: \
+    order = leastdependenciesfirst, \
+    begin = 1000, \
+    step  =    1
+
+ +

After resolving, this can generate:

+
-runbundles: \
+    org.apache.felix.configadmin;version='[1.8.8,1.8.9)';startlevel=1000,\
+    org.apache.felix.http.jetty;version='[3.2.0,3.2.1);startlevel=1001',\
+    org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3);startlevel=1002',\
+    ...
+    osgi.enroute.twitter.bootstrap.webresource;version='[3.3.5,3.3.6);startlevel=1019',\
+    osgi.enroute.web.simple.provider;version='[2.1.0,2.1.1);startlevel=1020'
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runstorage.html b/org.bndtools.help/docs/instructions/runstorage.html new file mode 100644 index 0000000000..6892d77084 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runstorage.html @@ -0,0 +1,30 @@ + + + + +-runstorage FILE + + + +

-runstorage FILE

+ + +

-runstorage

+

The -runstorage instruction defines the directory to use for the framework's work area. This is where the OSGi framework stores its runtime data, such as bundle caches and configuration.

+

Example:

+
-runstorage: fwstorage
+
+ +

By default, this directory is set to fw under the project's target directory, but you can override it with this instruction.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runsystemcapabilities.html b/org.bndtools.help/docs/instructions/runsystemcapabilities.html new file mode 100644 index 0000000000..f320a104ed --- /dev/null +++ b/org.bndtools.help/docs/instructions/runsystemcapabilities.html @@ -0,0 +1,41 @@ + + + + +-runsystemcapabilities* CAPABILITY (',' CAPABILITY ) + + + +

-runsystemcapabilities* CAPABILITY (',' CAPABILITY )

+ + +

Although resolver analyses the -runpath (and thus -runfw) for system capabilities, this is not always sufficient. For example, if the target system has special hardware then this might be described with a capability. Such an external capability must be explicitly given to the resolver. These extra capabilities maybe given with the -runsystemcapabilities instruction.

+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runsystempackages.html b/org.bndtools.help/docs/instructions/runsystempackages.html new file mode 100644 index 0000000000..5d9620c874 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runsystempackages.html @@ -0,0 +1,27 @@ + + + + +-runsystempackages* PARAMETERS + + + +

-runsystempackages* PARAMETERS

+ + +

The resolver will analyse the -runpath and -runfw JARs for any exported packages and make these available as system packages to the bundles. However, in certain cases this automatic analysis does not suffice. In that case extra packages can be added. These packages must, of course, be available on the class path.

+

For example:

+
-runsystempackages: \
+    com.sun.misc
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/runtimeout.html b/org.bndtools.help/docs/instructions/runtimeout.html new file mode 100644 index 0000000000..d0c04b9ba0 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runtimeout.html @@ -0,0 +1,25 @@ + + + + +-runtimeout DURATION + + + +

-runtimeout DURATION

+ + +

The -runtimeout instruction allows you to specify a timeout duration for running or testing your project. The value should be a duration (such as 30 SECONDS, 5 MINUTES, etc.), and it controls how long bnd will wait for the process to complete before terminating it.

+

This is useful for preventing tests or application runs from hanging indefinitely, ensuring that your build or test process completes in a reasonable amount of time.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runtrace.html b/org.bndtools.help/docs/instructions/runtrace.html new file mode 100644 index 0000000000..ca76b12156 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runtrace.html @@ -0,0 +1,28 @@ + + + + +-runtrace BOOLEAN + + + +

-runtrace BOOLEAN

+ + +

The -runtrace instruction enables detailed tracing of the launched process. When set to true, bnd will output additional information about the launch sequence, configuration, and runtime events. This can be helpful for debugging, troubleshooting, or understanding the behavior of your application during launch.

+

Use this instruction if you need more insight into the launch process or want to diagnose issues with your runtime environment.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/runvm.html b/org.bndtools.help/docs/instructions/runvm.html new file mode 100644 index 0000000000..a654a1a9c4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/runvm.html @@ -0,0 +1,25 @@ + + + + +-runvm KEYS + + + +

-runvm KEYS

+ + +

The -runvm instruction allows you to specify additional arguments that will be passed directly to the Java Virtual Machine (JVM) when launching your application. These arguments are added as-is to the command line and can be used to set system properties, enable debugging, adjust memory settings, or configure other JVM options.

+

This is useful for customizing the runtime environment of your application without modifying the code or build process.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/savemanifest.html b/org.bndtools.help/docs/instructions/savemanifest.html new file mode 100644 index 0000000000..75e0094f09 --- /dev/null +++ b/org.bndtools.help/docs/instructions/savemanifest.html @@ -0,0 +1,30 @@ + + + + +-savemanifest FILE + + + +

-savemanifest FILE

+ + +

-savemanifest

+

The -savemanifest instruction allows you to write out the calculated manifest to a separate file after it has been generated. This is useful for debugging, auditing, or sharing the manifest independently of the JAR.

+

Example:

+
-savemanifest: my-manifest.mf
+
+ +

The specified file will contain the manifest as it would appear in the final bundle.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/sign.html b/org.bndtools.help/docs/instructions/sign.html new file mode 100644 index 0000000000..75946ac864 --- /dev/null +++ b/org.bndtools.help/docs/instructions/sign.html @@ -0,0 +1,44 @@ + + + + +-sign PARAMETERS + + + +

-sign PARAMETERS

+ + +

-sign

+

The -sign instruction is used to sign the generated JAR file with a specified certificate or keystore. This is important for distributing secure and trusted bundles, especially in environments that require signed artifacts.

+

Example:

+
-sign: mykeystore;alias=myalias
+
+ +

This instruction ensures that the output JAR is cryptographically signed as part of the build process.

+

A more detailed example using additional properties:

+
-sign: mykeystore;alias=myalias;storepass=secret;keypass=secret;keystore=path/to/keystore.jks;digestalg=SHA-256
+
+ +

In this example: +- mykeystore is the name of the keystore. +- alias specifies the certificate alias to use for signing. +- storepass and keypass provide the passwords for the keystore and key. +- keystore gives the path to the keystore file. +- digestalg sets the digest algorithm (e.g., SHA-256) for the signature.

+

These options allow you to fully control the signing process and meet the requirements of your deployment environment.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/snapshot.html b/org.bndtools.help/docs/instructions/snapshot.html new file mode 100644 index 0000000000..fff185253c --- /dev/null +++ b/org.bndtools.help/docs/instructions/snapshot.html @@ -0,0 +1,52 @@ + + + + +-snapshot STRING + + + +

-snapshot STRING

+ + +

-snapshot

+

The -snapshot instruction specifies a string to substitute for "SNAPSHOT" in the bundle version's qualifier. This is useful for customizing versioning schemes during the build process.

+

Example:

+
-snapshot: 20250708
+
+ +

If the bundle version's qualifier is "SNAPSHOT" or ends with "-SNAPSHOT", the specified string will be used instead.

+

When the bundle version's qualifier equals "SNAPSHOT" or ends with "-SNAPSHOT", the STRING +value of the -snapshot instruction is substituted for "SNAPSHOT". The STRING value of +the empty string will remove the qualifier if it equals "SNAPSHOT" or +will remove "-SNAPSHOT" from the end of the qualifier.

+

The default is no substitution.

+

For example, the bundle's version can be set with a "SNAPSHOT" qualifier indicating it is +a maven snapshot version.

+
Bundle-Version: 3.2.0.SNAPSHOT
+
+ +

When time to release, the -snapshot instruction can be used, in a central location such +as cnf/build.bnd, to substitute "SNAPSHOT" for another value such as the timestamp of +the build:

+
-snapshot: ${tstamp}
+
+ +

or some other meaningful value:

+
-snapshot: REL
+
+ +

Using "SNAPSHOT" in the bundle version's qualifier and the -snapshot instruction +are generally for bundles intended for maven builds.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/sourcepath.html b/org.bndtools.help/docs/instructions/sourcepath.html new file mode 100644 index 0000000000..99a8bc98f4 --- /dev/null +++ b/org.bndtools.help/docs/instructions/sourcepath.html @@ -0,0 +1,25 @@ + + + + +-sourcepath + + + +

-sourcepath

+ + +

The -sourcepath instruction specifies a list of directory names that bnd should use to find source files. These directories are searched for Java source files and related resources when building your project or including sources in the bundle.

+

This is useful for ensuring that all relevant source files are available for compilation, packaging, or source inclusion in the generated JAR.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/sources.html b/org.bndtools.help/docs/instructions/sources.html new file mode 100644 index 0000000000..faa3bbda18 --- /dev/null +++ b/org.bndtools.help/docs/instructions/sources.html @@ -0,0 +1,28 @@ + + + + +-sources BOOLEAN + + + +

-sources BOOLEAN

+ + +

The -sources instruction tells bnd to include the source code (if available on the -sourcepath) in the bundle under the OSGI-OPT/src directory. This is useful for distributing source code along with your binary bundle, making it easier for others to debug or understand your code.

+

When enabled, bnd will collect the relevant source files and package them in the appropriate location within the bundle.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/stalecheck.html b/org.bndtools.help/docs/instructions/stalecheck.html new file mode 100644 index 0000000000..3c09f9ce4f --- /dev/null +++ b/org.bndtools.help/docs/instructions/stalecheck.html @@ -0,0 +1,63 @@ + + + + +-stalecheck srcs ';newer=' depends ( ';' ( warning | error | command ))* ... + + + +

-stalecheck srcs ';newer=' depends ( ';' ( warning | error | command ))* ...

+ + +

If you work in Bndtools then there is normally little to worry about, bndtools keeps everything up to dated all the time. +Any file you save, and guaranteed in s short time all dependent bundles are updated. This comes with a crucial guarantee +that anything you do in Bndtools is faithfully reproduced on the build server using Gradle. For a default workspace there +is no need for any gradle specific files. All the workspace's settings are defined in the bnd files.

+

However, sometimes it is necessary to generate sources that need to be compiled. There are then two choices when you +checkout a workspace. Always use the command line let the build do its magic or checkin the generated sources. +Although generally frowned upon, it has the advantage that you do not need to store the tool itself under version control. +Any revision can always compile regardless of what happened to the tool. It is also nice to see it on Github, it actually +makes the experience of the majority of people that use the workspace and usually not touch the swagger file blithely +unaware of the underlying complexities.

+

However, this has a very serious problem. Sometimes you touch the swagger file and forget to run the gradle to generate +new sources. It would be very convenient if bnd could generate an error if certain files were out of date respective +to a set of other files. Thhe -stalecheck instruction has this purpose.

+
-stalecheck ::=     clause ( ',' clause )*
+clause      ::=     src ';' 'newer=' depends (';' option )*
+src     ::= Ant Glob spec
+depends     ::=     Ant Glob spec
+option      ::=     'error=' STRING 
+        |   'warning=' STRING 
+        |   'command=' STRING
+
+ +

Just before bnd will start making the JAR(s) for a project it will check if any of the files in the src specification +is newer than the files in the depends set. If so, it will provide warning or error. If either a specific error or +warning STRING is given then this is reported accordingly.

+

If a command STRING is given it is executed as in the ${system} macro. If the command STRING starts with a +minus sign (-) then a failure is not an error, it is reported as warning.

+

If no command is given, nor an error or warning then a default error is reported.

+

Examples

+
-stalecheck:  \   
+    openapi.json; \ 
+        newer='gen-src/, checksum.md5'
+
+-stalecheck:   \
+    specs/**.md; \ 
+        newer='doc/**.doc' ; \ 
+        error='Markdown needs to be generated'
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/standalone.html b/org.bndtools.help/docs/instructions/standalone.html new file mode 100644 index 0000000000..642ceb2438 --- /dev/null +++ b/org.bndtools.help/docs/instructions/standalone.html @@ -0,0 +1,41 @@ + + + + +-standalone repo-spec (, repo-spec ) + + + +

-standalone repo-spec (, repo-spec )

+ + +

The -standalone instruction in bnd allows you to transform a bndrun file into a standalone file that doesn't require a workspace. It is a merged property, meaning you can specify additional repo-specs using -standalone.extra. However, the presence of the exact -standalone flag is what determines if the bndrun file is standalone. Without the -standalone flag, even if -standalone.extra is specified, a workspace will still be required.

+

A bndrun file is by default connected to its workspace, where the workspace defines the context and most important: the repositories. The workspace is by default defined in the workspace's cnf directory.

+

The -standalone instruction tells bnd that this connection should be severed and that all information is contained in the bndrun file. The value of the -standalone instruction is used to define the repositories. Each repo-spec clause defines a repository.

+
-standalone     ::= repo-spec ( ',' repo-spec )*
+repo-spec       ::= <relative url> ( '; <fixed index repo attrs> )*
+
+ +

The repositories that are created from the -standalone instruction are the OSGi Capabilities repositories as implemented by the Fixed Index Repository. For this repository you can add the following attributes:

+ +

Example

+
-standalone:    index.html; name=local
+-runfw:         org.apache.felix.framework;version=5
+-runee:         JavaSE-1.8
+-runrequires:   osgi.identity;filter:='(osgi.identity=com.springsource.org.apache.tools.ant)'
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/strict.html b/org.bndtools.help/docs/instructions/strict.html new file mode 100644 index 0000000000..1f68034f5d --- /dev/null +++ b/org.bndtools.help/docs/instructions/strict.html @@ -0,0 +1,33 @@ + + + + +-strict BOOLEAN + + + +

-strict BOOLEAN

+ + +

-strict

+

The -strict instruction enables extra verification during the build process. When set to true, bnd performs additional checks and validation to ensure the highest quality and correctness of the bundle.

+

Example:

+
-strict: true
+
+ +

This is useful for enforcing stricter build requirements and catching potential issues early.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/sub.html b/org.bndtools.help/docs/instructions/sub.html new file mode 100644 index 0000000000..c2385179d9 --- /dev/null +++ b/org.bndtools.help/docs/instructions/sub.html @@ -0,0 +1,53 @@ + + + + +-sub FILE-SPEC ( ',' FILE-SPEC )* + + + +

-sub FILE-SPEC ( ',' FILE-SPEC )*

+ + +

You can enable sub-bundles with the -sub instruction, to build a set of .bnd files that use the bnd.bnd file as a basis. The list of sub-.bnd files can be specified with wildcards.

+

Example

+

Assume a bundle com.example with a main bnd.bnd file:

+

-sub *.bnd

+

And besides the following files:

+ +

This will process every other .bnd file as a sub-bundle and will create a .jar file for it:

+ +

The Bundle Symbolic Name for each sub bundle will be the name of the project + . + file name prefix of the sub bundle.

+

Sub bundles are mostly treated as independent projects. They are part of the repositories and release process.

+

The content of the sub .bnd files is as usual (see also Generating JARs).

+

-buildpath and -classpath with sub-bundles

+

The -buildpath is a project instruction. This means that it must be placed in the main bnd.bnd file, not in the sub-.bnd file. A project can only have a single -buildpath.

+

Thus, in the sub bundle .bnd-files you have to use -classpath instead.

+

Example:

+
-classpath: \
+    ${repo;org.apache.poi:poi;latest},\
+
+ +

Use cases

+

Gogo Commands

+

A case where this approach is useful is, when you provide an implementation and want to separate the Gogo commands from the main code. In that case you create a main provider bundle and a Gogo bundle.

+

In most cases it is best to have one project generate one bundle. However, sometimes it creates a lot of overhead and you’d like to be able to provide multiple bundles in a project since they share so much information.

+

Wrapping JAR files

+

Another use case is when you need to wrap .jar files, e.g. to convert non-OSGi bundles into OSGi-Bundles by adding meta-data to the Manifest. +A practise to do so could be to have a single Wrapper-bundle where you do all your wrapping of external dependencies. The advantage is, that you don't clutter up your workspace with lots of tiny Bundle-wrapping projects. With sub-bundles you can keep all your wrapped jars in one single project.

+



+ + diff --git a/org.bndtools.help/docs/instructions/systemproperties.html b/org.bndtools.help/docs/instructions/systemproperties.html new file mode 100644 index 0000000000..522f6d2c52 --- /dev/null +++ b/org.bndtools.help/docs/instructions/systemproperties.html @@ -0,0 +1,25 @@ + + + + +-systemproperties PROPERTIES + + + +

-systemproperties PROPERTIES

+ + +

The -systemproperties instruction allows you to set system properties in the local JVM when a workspace is started. These properties are applied as early as possible, making it possible to configure JVM options or work around specific Java issues (such as SSL settings) before any other code runs.

+

This is especially useful for setting environment-specific options or JVM flags that must be in place for your workspace or build to function correctly.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/testcontinuous.html b/org.bndtools.help/docs/instructions/testcontinuous.html new file mode 100644 index 0000000000..8877a6d525 --- /dev/null +++ b/org.bndtools.help/docs/instructions/testcontinuous.html @@ -0,0 +1,28 @@ + + + + +-testcontinuous BOOLEAN + + + +

-testcontinuous BOOLEAN

+ + +

The -testcontinuous instruction enables continuous testing for your project. When set to true, bnd will not exit after running the test suites. Instead, it will keep watching the bundles and automatically rerun the test cases if any bundle is updated.

+

This is useful for development workflows where you want immediate feedback on changes, as tests will be re-executed whenever relevant code is modified.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/tester.html b/org.bndtools.help/docs/instructions/tester.html new file mode 100644 index 0000000000..ef538aeca2 --- /dev/null +++ b/org.bndtools.help/docs/instructions/tester.html @@ -0,0 +1,29 @@ + + + + +-tester REPO-SPEC + + + +

-tester REPO-SPEC

+ + +

The -tester instruction defines what bundle is used to setup testing. This bundle must have a Tester-Plugin that will setup the test environment.

+

By default the, -tester is the bundle biz.aQute.tester. This bundle will instruct bnd to add this bundle to the -runbundles, sets the appropriate properties, and then launches. It will then run whatever tests are configured.

+

Older Versions

+

For a long time bnd had biz.aQute.junit as the tester. This launcher added itself to the -runpath and then executed the tests from there. Unfortunately this required that the tester actually exported the JUnit packages. This caused constraints between JUnit and bnd that was not good because JUnit itself is not directly a shining example of software engineering :-(

+

If you want to be backward compatible with the older model, set:

+
-tester: biz.aQute.junit
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/testpackages.html b/org.bndtools.help/docs/instructions/testpackages.html new file mode 100644 index 0000000000..af9b446765 --- /dev/null +++ b/org.bndtools.help/docs/instructions/testpackages.html @@ -0,0 +1,25 @@ + + + + +-testpackages PACKAGE-SPEC ( ',' PACKAGE-SPEC ) + + + +

-testpackages PACKAGE-SPEC ( ',' PACKAGE-SPEC )

+ + +

The -testpackages instruction allows you to specify which packages should be included as test packages in your project. You provide a comma-separated list of package specifications, and bnd will treat these packages as containing test code.

+

This is useful for projects that separate test code into specific packages or want to control which packages are considered for testing, especially when running or packaging tests.

+
+

TODO Needs review - AI Generated content

+



+ + diff --git a/org.bndtools.help/docs/instructions/testpath.html b/org.bndtools.help/docs/instructions/testpath.html new file mode 100644 index 0000000000..a417e0e1e3 --- /dev/null +++ b/org.bndtools.help/docs/instructions/testpath.html @@ -0,0 +1,23 @@ + + + + +-testpath REPO-SPEC ( ',' REPO-SPEC ) + + + +

-testpath REPO-SPEC ( ',' REPO-SPEC )

+ + +

The -testpath instruction specifies JARs from a repository that should be added to the remote JVM's classpath when the JVM is started in test mode. These JARs are included in addition to those specified by -runpath and are typically used to provide test dependencies, such as JUnit or other testing libraries.

+

This is useful for ensuring that all necessary test dependencies are available during test execution without including them in the main runtime classpath.

+



+ + diff --git a/org.bndtools.help/docs/instructions/testsources.html b/org.bndtools.help/docs/instructions/testsources.html new file mode 100644 index 0000000000..2c5feffac8 --- /dev/null +++ b/org.bndtools.help/docs/instructions/testsources.html @@ -0,0 +1,26 @@ + + + + +-testsources REGEX ( ',' REGEX )* + + + +

-testsources REGEX ( ',' REGEX )*

+ + +

The -testsources instruction specifies how bnd should find JUnit test cases by searching the test source directory for Java classes. By default, it looks for all .java files, but you can provide a regular expression to customize which files are considered test sources.

+

This instruction is useful for projects with non-standard test file naming or organization, allowing you to control which files are included as test cases during the build process.

+



+ + diff --git a/org.bndtools.help/docs/instructions/testunresolved.html b/org.bndtools.help/docs/instructions/testunresolved.html new file mode 100644 index 0000000000..4954f85d68 --- /dev/null +++ b/org.bndtools.help/docs/instructions/testunresolved.html @@ -0,0 +1,26 @@ + + + + +-testunresolved BOOLEAN + + + +

-testunresolved BOOLEAN

+ + +

The -testunresolved instruction controls whether a special JUnit test case is executed before any other test cases to check for unresolved bundles. If any bundles are unresolved, this test will abort the test run and report the issue as a failure.

+

This is useful for ensuring that your test environment is fully resolved before running tests, helping to catch dependency or configuration problems early in the process.

+



+ + diff --git a/org.bndtools.help/docs/instructions/undertest.html b/org.bndtools.help/docs/instructions/undertest.html new file mode 100644 index 0000000000..cf491814fb --- /dev/null +++ b/org.bndtools.help/docs/instructions/undertest.html @@ -0,0 +1,19 @@ + + + + +-undertest true + + + +

-undertest true

+ + +

The -undertest instruction is set by the project when it builds a JAR in test mode. It is intended to be used by plugins or build logic to indicate that the current build is for testing purposes. When this instruction is present, certain behaviors or configurations (such as including test packages) may be enabled automatically.

+

When building with -undertest, the build process skips dependency checking, so it is important to ensure that any dependent projects are built first. The instruction also causes the project to include test-specific packages (such as those specified by -testpackages) in the build, making them available for testing. This helps automate and streamline the test build process, ensuring that test-specific settings are applied only when needed and that the resulting JAR is suitable for test execution.

+

In summary, -undertest signals that the current build is for testing, enables test package inclusion, and skips dependency checks to speed up the test build workflow.

+



+ + diff --git a/org.bndtools.help/docs/instructions/upto.html b/org.bndtools.help/docs/instructions/upto.html new file mode 100644 index 0000000000..4aa52f5c4c --- /dev/null +++ b/org.bndtools.help/docs/instructions/upto.html @@ -0,0 +1,24 @@ + + + + +-upto VERSION + + + +

-upto VERSION

+ + +

The -upto instruction specifies the highest version of bnd features that your project should be compatible with. When you set this instruction, any features or behaviors introduced after the specified version will be disabled, ensuring compatibility with earlier versions of bnd.

+

This is useful for maintaining backward compatibility or for projects that need to avoid adopting new behaviors automatically. If -upto is not set, bnd assumes the latest version and enables all features by default.

+

In summary, use -upto to control the introduction of new features and maintain a stable build environment as bnd evolves.

+



+ + diff --git a/org.bndtools.help/docs/instructions/wab.html b/org.bndtools.help/docs/instructions/wab.html new file mode 100644 index 0000000000..03095b09bf --- /dev/null +++ b/org.bndtools.help/docs/instructions/wab.html @@ -0,0 +1,92 @@ + + + + +-wab FILE ( ',' FILE )* + + + +

-wab FILE ( ',' FILE )*

+ + +

In OSGi Enterprise 4.2 the concept of Web Archive Bundles were introduced. Web Archive Bundles are 100% normal bundles following all the rules of OSGi. Their speciality is that they can be mapped to a web server following several of the rules of Java Enterprise Edition's Servlet model. The big difference is that the WARs of the servlet model have a rather strict layout of their archive because the servlet container also handles class loading. In OSGi, the class loading is very well specified and it would therefore be wrong to create special rules.

+

However, the OSGi supports the Bundle-Classpath header. This header allows the organization of the internal layout. It turns out that it is possible to create a valid Web Application Bundle (WAB) that is also a valid Web ARchive (WAR). Being deploy an archive both to OSGi and an application server obviously has advantages. bnd therefore supports a number of instructions that make it easy to create these dual mode archives.

+

The -wab instruction instructs bnd to move the root of the created archive to WEB-INF/classes. That is, you build your bundle in the normal way,not using the Bundle-ClassPath. The -wab command then moves the root of the archive so the complete class path for the bundle is no inside the WEB-INF/classes directory. It then adjusts the Bundle-ClassPath header to reflect this new location of the classes and resources.

+

The new root now only contains WEB-INF. In the Servlet specification, the root of the archive is mapped to the server's context URL. It is therefore often necessary to place static files in the root. For this reason, the -wab instruction has the same form as Include-Resource header, and performs the same function. However, it performs this function of copying resources from the file system after the classes and resources of the original bundle have been moved to WEB-INF.

+

For example, the following code creates a simple WAB/WAR:

+
  Private-Package:   com.example.impl.*
+  Export-Package:    com.example.service.myapi
+  Include-Resource:  resources/
+  -wab:              static-pages/
+
+ +

The layout of the resulting archive is:

+
  WEB-INF/classes/com/example/impl/
+  WEB-INF/classes/com/example/service/myapi/
+  WEB-INF/classes/resources/
+  index.html // from static-pages
+
+ +

The Bundle-ClassPath is WEB-INF/classes.

+

WARs can carry a WEB-INF/lib directory. Any archive in this directory is mapped to the class path of the WAR. The OSGi specifications do not recognize directories with archives it is therefore necessary to list these archives also on the Bundle-ClassPath header. This is cumbersome to do by hand so the -wablib command will take a list of paths.

+
  Private-Package:   com.example.impl.*
+  Export-Package:    com.example.service.myapi
+  Include-Resource:  resources/
+  -wab:              static-pages/
+  -wablib:           lib/a.jar, lib/b.jar
+
+ +

This results in a layout of:

+
  WEB-INF/classes/com/example/impl/
+  WEB-INF/classes/com/example/service/myapi/
+  WEB-INF/classes/resources/
+  WEB-INF/lib/
+    a.jar
+    b.jar
+  index.html ( from static-pages)
+
+ +

The Bundle-ClassPath is now set to WEB-INF/classes,WEB-INF/lib/a.jar,WEB-INF/lib/a.jar

+
    /**
+     * Turn this normal bundle in a web and add any resources.
+     *
+     * @throws Exception
+     */
+    private Jar doWab(Jar dot) throws Exception {
+        String wab = getProperty(WAB);
+        String wablib = getProperty(WABLIB);
+        if (wab == null && wablib == null)
+            return dot;
+
+        trace("wab %s %s", wab, wablib);
+        setBundleClasspath(append("WEB-INF/classes", getProperty(BUNDLE_CLASSPATH)));
+
+        Set<String> paths = new HashSet<String>(dot.getResources().keySet());
+
+        for (String path : paths) {
+            if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
+                trace("wab: moving: %s", path);
+                dot.rename(path, "WEB-INF/classes/" + path);
+            }
+        }
+
+        Parameters clauses = parseHeader(getProperty(WABLIB));
+        for (String key : clauses.keySet()) {
+            File f = getFile(key);
+            addWabLib(dot, f);
+        }
+        doIncludeResource(dot, wab);
+        return dot;
+    }
+
+ +



+ + diff --git a/org.bndtools.help/docs/instructions/wablib.html b/org.bndtools.help/docs/instructions/wablib.html new file mode 100644 index 0000000000..a66c7d6341 --- /dev/null +++ b/org.bndtools.help/docs/instructions/wablib.html @@ -0,0 +1,23 @@ + + + + +-wablib FILE ( ',' FILE )* + + + +

-wablib FILE ( ',' FILE )*

+ + +

The -wablib instruction specifies additional libraries (JAR files) that should be included in a Web Archive Bundle (WAB) or WAR. These libraries are added to the WEB-INF/lib directory of the resulting archive, making them available to the web application at runtime.

+

This instruction is useful when you need to package extra dependencies with your web bundle, ensuring that all required libraries are present in the deployed artifact.

+



+ + diff --git a/org.bndtools.help/docs/instructions/workingset.html b/org.bndtools.help/docs/instructions/workingset.html new file mode 100644 index 0000000000..530661599d --- /dev/null +++ b/org.bndtools.help/docs/instructions/workingset.html @@ -0,0 +1,54 @@ + + + + +-workingset PARAMETER ( ',' PARAMETER ) * + + + +

-workingset PARAMETER ( ',' PARAMETER ) *

+ + +

A workingset is a name for a group of projects that have something in common. You can tag a project for one or more workingsets using the -workingset instruction in the bnd.bnd file. For example, to make a project member of the Implementations and Drivers working sets you can enter the following in a bnd file:

+
-workingset Implementations, Drivers
+
+ +

An IDE can use this information to provide a grouping to projects. However, this information can also be used to tag bundles in the Manifest, like:

+
Bundle-Category ${-workingset.*}
+
+ +

The syntax for the instruction is:

+
workingset := '-workingset' tag ( ',' tag )*
+tag        := NAME ( ';member=' TRUTHY )?
+NAME       := <JavaIdentifierPart+>
+
+ +

The instruction is a merged instruction so you can also set:

+
-workingset.all All
+
+ +

Note that, the name of the working set must use the pattern of Java identifier.

+

More Advanced Usage

+

As you could see in the syntax, you can also specify a member attribute on the tag. This member attribute evaluates to a truthy. A truthy is true if it is not empty, 0, nor false. The truthy is well supported by macros so you can now use the bnd macro language to decide if a project should be a member of a working set or not. This can be used in many ways. For example, you could use it to do name matching. By placing the following in the cnf/build.bnd file you do not have to place the -workingset instruction in each bnd file.

+
-workingset =  \
+  impl;member=${filter;${p};.*\.provider}, \
+  api;member=${filter;${p};.*\.api}, \
+  test;member=${filter;${p};.*\.test}
+
+ +

The feature will create working sets as demanded but will reuse existing working set with the matching name. If no -workingset instruction is given, the working sets are not touched in any way for that project. That is, they are then not removed from existing sets.

+

Manual Workingsets

+

In some cases it is necessary to maintain a working set manual. Such a workingset is then stored in Eclipse and not shared with the team. To +create a manual working set, use a name that is outside the specified NAME pattern. For example, use a name that starts with a +dot (.) like .Private. Since you cannot use these names in the -workingset instruction (they generate an error) +bnd will never look at workingsets with such a name.

+



+ + diff --git a/org.bndtools.help/docs/instructions/workspace_templates.html b/org.bndtools.help/docs/instructions/workspace_templates.html new file mode 100644 index 0000000000..925fd46ea2 --- /dev/null +++ b/org.bndtools.help/docs/instructions/workspace_templates.html @@ -0,0 +1,19 @@ + + + + +-workspace-templates + + + +

-workspace-templates

+ + +

-workspace-templates

+

The -workspace-templates instruction allows you to define templates for creating new workspaces. These templates can be referenced when initializing a workspace to ensure consistent structure and configuration.

+

See workspace templates for more details and usage examples.

+



+ + diff --git a/org.bndtools.help/docs/instructions/x_overwritestrategy.html b/org.bndtools.help/docs/instructions/x_overwritestrategy.html new file mode 100644 index 0000000000..8e96b6bf3d --- /dev/null +++ b/org.bndtools.help/docs/instructions/x_overwritestrategy.html @@ -0,0 +1,22 @@ + + + + +-x-overwritestrategy + + + +

-x-overwritestrategy

+ + + diff --git a/org.bndtools.help/docs/macros/apply.html b/org.bndtools.help/docs/macros/apply.html new file mode 100644 index 0000000000..b490e6369b --- /dev/null +++ b/org.bndtools.help/docs/macros/apply.html @@ -0,0 +1,90 @@ + + + + +apply ';' MACRO (';' LIST)* + + + +

apply ';' MACRO (';' LIST)*

+

Summary

+

Convert comma-separated lists into semicolon-separated macro arguments, effectively "applying" list elements as individual macro parameters.

+

Syntax

+
${apply;<macro-name>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Takes the specified macro name +2. Splits all provided lists into individual elements (using comma separation) +3. Constructs a new macro invocation with elements as semicolon-separated arguments +4. Expands the constructed macro

+

This is useful when you have arguments in a comma-separated list but need to pass them as separate parameters to a macro.

+

Examples

+
# Basic example - convert list to macro arguments
+args = com.example.foo, 3.12, HIGHEST
+${apply;repo;${args}}
+# Expands to: ${repo;com.example.foo;3.12;HIGHEST}
+
+# Apply multiple lists
+list1 = a, b
+list2 = c, d
+${apply;mymacro;${list1};${list2}}
+# Expands to: ${mymacro;a;b;c;d}
+
+# Use with filter macro
+packages = com.example.*, org.sample.*, com.test.*
+pattern = com\..*
+${apply;filter;${packages};${pattern}}
+# Expands to: ${filter;com.example.*,org.sample.*,com.test.*;com\..*}
+
+# Repository lookup with dynamic arguments
+repo-args = my.bundle, 1.0.0, HIGHEST
+bundle-path = ${apply;repo;${repo-args}}
+
+# Use with format macro
+format-string = %s-%s-%s
+values = group, artifact, version
+${apply;format;${format-string};${values}}
+# Expands to: ${format;%s-%s-%s;group;artifact;version}
+
+# Complex example with multiple lists
+deps1 = foo, bar
+deps2 = baz
+${apply;join;,;${deps1};${deps2}}
+# Expands to: ${join;,;foo;bar;baz}
+
+ +

Use Cases

+
    +
  1. Dynamic Macro Calls: Build macro invocations from list-based configuration
  2. +
  3. Repository Queries: Pass artifact coordinates as a list
  4. +
  5. Parameter Transformation: Convert comma-separated to semicolon-separated
  6. +
  7. Configuration Flexibility: Store macro arguments in properties as lists
  8. +
  9. Macro Composition: Combine multiple lists into a single macro call
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/average.html b/org.bndtools.help/docs/macros/average.html new file mode 100644 index 0000000000..649d40a9fd --- /dev/null +++ b/org.bndtools.help/docs/macros/average.html @@ -0,0 +1,53 @@ + + + + +average (';' LIST )* + + + +

average (';' LIST )*

+

Summary

+

The average macro calculates the arithmetic mean of all numeric values provided in one or more semicolon-separated lists. Each list element is parsed as a double-precision floating-point number, and the result is the sum of all values divided by the count.

+

Syntax

+
${average;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Calculate average of a simple list:

+
${average;1,2,3,4,5}
+# Returns: 3
+
+ +

Calculate average across multiple lists:

+
${average;10,20,30;40,50}
+# Returns: 30 (average of 10,20,30,40,50)
+
+ +

Calculate average of decimal values:

+
${average;1.5,2.5,3.5}
+# Returns: 2.5
+
+ +

Use Cases

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/base64.html b/org.bndtools.help/docs/macros/base64.html new file mode 100644 index 0000000000..4b14bcf5cf --- /dev/null +++ b/org.bndtools.help/docs/macros/base64.html @@ -0,0 +1,59 @@ + + + + +base64 ';' FILE [';' LONG ] + + + +

base64 ';' FILE [';' LONG ]

+

Summary

+

The base64 macro reads a file and returns its contents encoded as a Base64 string. This is useful for embedding binary content or file data directly in text-based configuration files.

+

Syntax

+
${base64;<file>[;fileSizeLimit]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Encode a small binary file:

+
${base64;resources/icon.png}
+
+ +

Encode with custom size limit (1MB):

+
${base64;data/config.bin;1000000}
+
+ +

Embed a certificate in a property:

+
certificate.data=${base64;certs/ca-cert.pem}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/basedir.html b/org.bndtools.help/docs/macros/basedir.html new file mode 100644 index 0000000000..cb0a71683c --- /dev/null +++ b/org.bndtools.help/docs/macros/basedir.html @@ -0,0 +1,54 @@ + + + + +basedir + + + +

basedir

+

Summary

+

The basedir macro returns the absolute path to the base directory of the current processor (project, workspace, or build context). This is the root directory from which relative paths are resolved.

+

Syntax

+
${basedir}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get the current project's base directory:

+
project.root=${basedir}
+
+ +

Build a path relative to the base directory:

+
resources.dir=${basedir}/src/main/resources
+
+ +

Reference files using the base directory:

+
Bundle-Icon: ${basedir}/icon.png
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/basename.html b/org.bndtools.help/docs/macros/basename.html new file mode 100644 index 0000000000..d87261fa35 --- /dev/null +++ b/org.bndtools.help/docs/macros/basename.html @@ -0,0 +1,71 @@ + + + + +basename ( ';' FILEPATH ) + + + + +

basename ( ';' FILEPATH ) +

+

Summary

+

The basename macro extracts the filename (last component) from one or more file paths. It returns only the filenames for files that exist.

+

Syntax

+
${basename;<filepath>[;<filepath>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get single filename:

+
${basename;/path/to/file.txt}
+# Returns: "file.txt"
+
+ +

Multiple files:

+
${basename;src/Main.java;src/Util.java}
+# Returns: "Main.java,Util.java"
+
+ +

With project-relative paths:

+
${basename;${@}}
+# Returns filename of current bundle JAR
+
+ +

Extract from full paths:

+
${basename;${buildpath}}
+# Returns basenames of all buildpath entries
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/basenameext.html b/org.bndtools.help/docs/macros/basenameext.html new file mode 100644 index 0000000000..56e9df5dfe --- /dev/null +++ b/org.bndtools.help/docs/macros/basenameext.html @@ -0,0 +1,25 @@ + + + + +basenameext ';' PATH ( ';' EXTENSION ) + + + +

basenameext ';' PATH ( ';' EXTENSION )

+

Returns the basename of the specified path optionally minus a specified extension. This is the last segment of the path. If an extension is specified, the basename is examined for a . separating the extension from the rest of the file name. If the extension of the basename matches the specified extension, this extension is removed from the basename before it is returned. The extension, if specified, may optionally start with ..

+

Examples

+
# returns 'abcdef.def'
+${basenameext;abcdef.def}
+${basenameext;/foo.bar/abcdef.def}
+${basenameext;abcdef.def;bar}
+${basenameext;/foo.bar/abcdef.def;bar}
+
+# returns 'abcdef'
+${basenameext;abcdef.def;def}
+${basenameext;/foo.bar/abcdef.def;def}
+${basenameext;abcdef.def;.def}
+${basenameext;/foo.bar/abcdef.def;.def}
+
+ + diff --git a/org.bndtools.help/docs/macros/bndversion.html b/org.bndtools.help/docs/macros/bndversion.html new file mode 100644 index 0000000000..0bd51dcb0d --- /dev/null +++ b/org.bndtools.help/docs/macros/bndversion.html @@ -0,0 +1,58 @@ + + + + +bndversion + + + +

bndversion

+

Summary

+

Returns the version number of the bnd tool currently being used to process the build.

+

Syntax

+
${bndversion}
+
+ +

Parameters

+

None. This macro takes no parameters.

+

Behavior

+

Returns the current bnd version as a string in the format major.minor.micro (without the qualifier/build timestamp).

+

For example: 7.0.0 or 6.4.0 or 5.3.0

+

Examples

+
# Display bnd version in bundle manifest
+Bundle-BuildTool: bnd-${bndversion}
+
+# Conditional logic based on bnd version
+-include ${if;${vcompare;${bndversion};7.0.0};modern.bnd;legacy.bnd}
+
+# Document which bnd version was used
+Bundle-Comment: Built with bnd ${bndversion}
+
+# Version-specific features
+-conditionalpackage: ${if;${vcompare;${bndversion};6.4.0};com.new.*;com.legacy.*}
+
+ +

Use Cases

+
    +
  1. Build Documentation: Record which version of bnd was used to build a bundle
  2. +
  3. Conditional Configuration: Apply different settings based on bnd version
  4. +
  5. Feature Detection: Enable features only available in newer bnd versions
  6. +
  7. Troubleshooting: Help identify build environment for debugging
  8. +
  9. Version Requirements: Verify minimum bnd version requirements
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/bsn.html b/org.bndtools.help/docs/macros/bsn.html new file mode 100644 index 0000000000..06cc190961 --- /dev/null +++ b/org.bndtools.help/docs/macros/bsn.html @@ -0,0 +1,56 @@ + + + + +bsn + + + +

bsn

+

Summary

+

The bsn macro returns the Bundle Symbolic Name (BSN) of the bundle currently being analyzed or built. This is particularly useful in sub-bundle scenarios where the BSN may differ from the project's main BSN.

+

Syntax

+
${bsn}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Use the BSN in a manifest header:

+
Bundle-Description: Bundle for ${bsn}
+
+ +

Create BSN-based paths:

+
output.file=${bsn}.jar
+
+ +

Reference in bundle documentation:

+
Bundle-DocURL: https://example.com/docs/${bsn}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/bytes.html b/org.bndtools.help/docs/macros/bytes.html new file mode 100644 index 0000000000..0060fb4ddd --- /dev/null +++ b/org.bndtools.help/docs/macros/bytes.html @@ -0,0 +1,67 @@ + + + + +bytes ( ';' LONG )* + + + +

bytes ( ';' LONG )*

+

Summary

+

The bytes macro converts a byte count (as long integer) into human-readable format with appropriate size units (b, Kb, Mb, Gb, etc.). It automatically selects the most appropriate unit by dividing by 1024 until the value is less than 1024. +Supports formatting a list of inputs.

+

Syntax

+
${bytes;<number>*}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Format a small byte count:

+
${bytes;1024}
+# Returns: "1.0 Kb"
+
+ +

Format megabytes:

+
${bytes;5242880}
+# Returns: "5.0 Mb" (5 * 1024 * 1024 bytes)
+
+ +

Format gigabytes:

+
${bytes;10737418240}
+# Returns: "10.0 Gb"
+
+ +

Format multiple

+
${bytes;1048576;10000048576}
+# Returns: "1.0 Mb 9.3 Gb"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/cat.html b/org.bndtools.help/docs/macros/cat.html new file mode 100644 index 0000000000..44374801f0 --- /dev/null +++ b/org.bndtools.help/docs/macros/cat.html @@ -0,0 +1,69 @@ + + + + +cat ';' FILEPATH + + + +

cat ';' FILEPATH

+

Summary

+

The cat macro reads the contents of a file, directory, or URL and returns it as a string. It's similar to the Unix cat command, allowing you to embed file contents directly in your configuration.

+

Syntax

+
${cat;<path-or-url>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Read a text file:

+
license.text=${cat;LICENSE.txt}
+
+ +

Read a property file:

+
build.info=${cat;build.properties}
+
+ +

List directory contents:

+
resource.files=${cat;resources}
+
+ +

Fetch content from a URL:

+
remote.config=${cat;https://example.com/config.txt}
+
+ +

Embed a template:

+
header=${cat;templates/header.txt}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/classes.html b/org.bndtools.help/docs/macros/classes.html new file mode 100644 index 0000000000..2595da4e14 --- /dev/null +++ b/org.bndtools.help/docs/macros/classes.html @@ -0,0 +1,127 @@ + + + + +classes ( ; QUERY ( ; PATTERN )? )* + + + +

classes ( ; QUERY ( ; PATTERN )? )*

+

The classes macro provides a query function in an analyzed bundle. While analyzing, the Analyzer stores each found class on the Bundle-Classpath with some key information. A simple query language is used to query this dictionary. For example, if you want to make a manifest header with all public classes in the bundle:

+
Public-Classes: ${classes;PUBLIC}
+
+ +

The query language is conjunctive, that is, all entries form an AND. For example, if you want to find all PUBLIC classes that are also not abstract you would do:

+
PublicConcrete-Classes: ${classes;PUBLIC;CONCRETE}
+
+ +

Some query types can also take parameters. This is a pattern that must match some aspect of the class. For example, it is possible to query for classes that extend a certain base class or is annotated by a certain annotation type:

+
Test-Cases: ${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
+Test-Cases: ${classes;CONCRETE;HIERARCHY_ANNOTATED;org.junit.Test}
+Test-Cases: ${classes;CONCRETE;HIERARCHY_INDIRECTLY_ANNOTATED;org.junit.platform.commons.annotation.Testable}
+
+ +

All pattern matching is based on fully qualified name and uses the globbing model.

+

The following table specifies what query options there are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
QueryParameterDescription
ANYMatches any class
CONCRETEClass must not be abstract.
ABSTRACTClass must be abstract.
PUBLICClass must be public.
STATICClass must be explicitly or implicitly declared static. That is, the class must not be a inner class.
INNERClass must be an inner class. That is, the class must be a nested class that is not explicitly or implicitly declared static. Inner classes include anonymous and local classes.
CLASSANNOTATIONSThe class must have some CLASS retention annotations.
RUNTIMEANNOTATIONSThe class must have some RUNTIME retention annotations.
DEFAULT_CONSTRUCTORThe class must have a default constructor. That is, the class must have a public, no-argument constructor.
IMPLEMENTSPATTERNThe class must implement at least one fully qualified interface name that matches the given pattern. This takes inheritance into account as long as super types can be found on the classpath. This query uses the Java source code fully qualified name where `.` (not `$`) separates the nested class name from the outer class name.
EXTENDSPATTERNThe class must extend at least one fully qualified class name that matches the given pattern. This takes inheritance into account as long as super types can be found on the classpath. This query uses the Java source code fully qualified name where `.` (not `$`) separates the nested class name from the outer class name.
IMPORTSPATTERNThe class must use a type from another package name that matches the given pattern
NAMEDPATTERNThe fully qualified name of the class must match the given pattern. This query uses the Java source code fully qualified name where `.` (not `$`) separates the nested class name from the outer class name.
VERSIONPATTERNThe class format of the given class must match the given version. The version is given as "major.minor", like "49.0". To select classes that are Java 6, do ${classes;VERSION;49.*}
ANNOTATEDPATTERNThe class must be directly annotated with a fully qualified annotation name that matches the pattern. The set of annotations is all annotations in the class, also the annotations on fields and methods. This query uses the Java class name fully qualified name where `$` (not `.`) separates the nested class name from the outer class name.
INDIRECTLY_ANNOTATEDPATTERNThe class must be directly or indirectly annotated with a fully qualified annotation name that matches the pattern. The set of annotations is all annotations in the class, the annotations on fields and methods, and all the annotations on those annotations recursively. This query uses the Java class name fully qualified name where `$` (not `.`) separates the nested class name from the outer class name.
HIERARCHY_ANNOTATEDPATTERNThe class, or one of its super classes, must be directly annotated with a fully qualified annotation name that matches the pattern. The set of annotations is all annotations in the class, also the annotations on fields and methods. This query uses the Java class name fully qualified name where `$` (not `.`) separates the nested class name from the outer class name.
HIERARCHY_INDIRECTLY_ANNOTATEDPATTERNThe class, or one of its super classes, must be directly or indirectly annotated with a fully qualified annotation name that matches the pattern. The set of annotations is all annotations in the class, the annotations on fields and methods, and all the annotations on those annotations recursively. This query uses the Java class name fully qualified name where `$` (not `.`) separates the nested class name from the outer class name.
+ +

Caveat

+

bnd will attempt to use the resources on the classpath if a super class or interface that is referenced from an analyzed class is not in the class space. However, bnd does not require that all dependencies are available on the classpath. In such a case it is not possible to do a complete analysis. For example, if A extends B and B extends C then it can only be determined that A extends C if B can be analyzed.

+ + diff --git a/org.bndtools.help/docs/macros/compare.html b/org.bndtools.help/docs/macros/compare.html new file mode 100644 index 0000000000..d0d664c723 --- /dev/null +++ b/org.bndtools.help/docs/macros/compare.html @@ -0,0 +1,82 @@ + + + + +compare STRING STRING + + + +

compare STRING STRING

+

Summary

+

Compare two strings lexicographically using Java's String.compareTo() method, returning -1, 0, or 1.

+

Syntax

+
${compare;<string1>;<string2>}
+
+ +

Parameters

+ +

Behavior

+

Compares the two strings lexicographically (alphabetically) and returns: +- 0 - The strings are equal +- 1 - The first string is greater than the second (comes later alphabetically) +- -1 - The first string is less than the second (comes earlier alphabetically)

+

The comparison is case-sensitive and uses Unicode character values.

+

Examples

+
# Equal strings
+${compare;hello;hello}
+# Returns: 0
+
+# First string greater
+${compare;world;hello}
+# Returns: 1
+
+# First string less
+${compare;apple;banana}
+# Returns: -1
+
+# Case-sensitive comparison
+${compare;Apple;apple}
+# Returns: -1 (uppercase comes before lowercase)
+
+# Use in conditional logic
+-include ${if;${compare;${env;MODE};production};prod.bnd;dev.bnd}
+
+# Numeric strings (lexicographic, not numeric)
+${compare;10;2}
+# Returns: -1 (because "1" < "2" alphabetically)
+
+# Empty string comparison
+${compare;;text}
+# Returns: -1 (empty string is less than any non-empty string)
+
+ +

Use Cases

+
    +
  1. Conditional Logic: Make decisions based on string comparison
  2. +
  3. Sorting Logic: Implement custom sort orders in build configurations
  4. +
  5. Version Comparison: Compare simple version strings (use vcompare for OSGi versions)
  6. +
  7. Configuration Selection: Choose configuration based on string values
  8. +
  9. Validation: Check if strings match expected values
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/currenttime.html b/org.bndtools.help/docs/macros/currenttime.html new file mode 100644 index 0000000000..30b5425a26 --- /dev/null +++ b/org.bndtools.help/docs/macros/currenttime.html @@ -0,0 +1,62 @@ + + + + +currenttime + + + +

currenttime

+

Summary

+

The currenttime macro returns the current system time as a long integer representing milliseconds since the Unix epoch (January 1, 1970, 00:00:00 UTC). This provides a precise timestamp for build-time operations.

+

Syntax

+
${currenttime}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Capture build time:

+
Build-Time: ${currenttime}
+
+ +

Use as a unique identifier component:

+
Build-Id: ${bsn}-${currenttime}
+
+ +

Create timestamped filenames:

+
output.file=bundle-${currenttime}.jar
+
+ +

Calculate elapsed time (with another timestamp):

+
# In combination with other macros for time calculations
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/decorated.html b/org.bndtools.help/docs/macros/decorated.html new file mode 100644 index 0000000000..b6d4f20518 --- /dev/null +++ b/org.bndtools.help/docs/macros/decorated.html @@ -0,0 +1,103 @@ + + + + +decorated ';' NAME [ ';' BOOLEAN ] + + + +

decorated ';' NAME [ ';' BOOLEAN ]

+

Summary

+

Get a merged and decorated Parameters object, where decoration allows pattern-based attribute addition to parameter entries.

+

Syntax

+
${decorated;<property-name>[;<include-literals>]}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Merges all properties starting with the given name (including .extra suffixes) +2. Decorates entries by matching them against decorator patterns from properties ending with + +3. Returns the merged and decorated Parameters as a string

+

Decoration Process

+

A "decorator" property (name ending with +) contains glob patterns as keys: +- Patterns are matched against keys from the merged parameters +- Matching entries receive additional attributes from the decorator +- If include-literals is true, unmatched decorator entries are also included

+

Examples

+
# Basic decoration
+parameters = a, b
+parameters.extra = c, d
+parameters+ = (c|d);attr=X
+${decorated;parameters}
+# Returns: a,b,c;attr=X,d;attr=X
+
+# Include literals
+parameters = a, b
+parameters.extra = c, d
+parameters+ = (c|d);attr=X, x, y, z
+${decorated;parameters;true}
+# Returns: a,b,c;attr=X,d;attr=X,x,y,z
+# (x,y,z are literals from decorator, included because second arg is true)
+
+# Package decoration
+-exportpackage = com.example.api, com.example.util
+-exportpackage.internal = com.example.internal
+-exportpackage+ = *.internal;version=0.0.0;x-internal:=true
+Export-Package: ${decorated;-exportpackage}
+# internal package gets version and x-internal attributes
+
+# Build path decoration
+-buildpath = commons-io, commons-lang
+-buildpath.test = junit, mockito
+-buildpath+ = junit;version=4.12, mockito;version=2.0
+${decorated;-buildpath}
+# Test dependencies get specific versions
+
+# Conditional attributes
+packages = com.example.*, org.sample.*
+packages+ = com.example.*;export=true
+packages+ = org.sample.*;export=false
+${decorated;packages}
+
+# Multiple decorators
+deps = foo, bar, baz
+deps+ = foo;version=1.0
+deps+ = bar;version=2.0
+${decorated;deps}
+# Returns: foo;version=1.0,bar;version=2.0,baz
+
+ +

Use Cases

+
    +
  1. Package Configuration: Add version or visibility attributes to packages
  2. +
  3. Dependency Management: Apply version constraints to dependencies
  4. +
  5. Conditional Attributes: Add different attributes based on patterns
  6. +
  7. Build Configuration: Decorate build paths with specific attributes
  8. +
  9. Manifest Generation: Create decorated manifest headers
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/def.html b/org.bndtools.help/docs/macros/def.html new file mode 100644 index 0000000000..9db66a5aa9 --- /dev/null +++ b/org.bndtools.help/docs/macros/def.html @@ -0,0 +1,68 @@ + + + + +def ';' KEY (';' STRING)? + + + +

def ';' KEY (';' STRING)?

+

Summary

+

The def macro looks up a property by key and returns its value, or returns a default value if the property is not set. The default is an empty string if not specified.

+

Syntax

+
${def;<key>[;<default>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get property with default:

+
${def;version;1.0.0}
+# Returns property value or "1.0.0" if not set
+
+ +

Empty default:

+
${def;optional.setting}
+# Returns property value or "" if not set
+
+ +

Use in paths:

+
output.dir=${def;custom.dir;target}
+
+ +

Conditional with default:

+
${if;${def;debug.mode;false};debug-on;debug-off}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/digest.html b/org.bndtools.help/docs/macros/digest.html new file mode 100644 index 0000000000..12eeefb7c4 --- /dev/null +++ b/org.bndtools.help/docs/macros/digest.html @@ -0,0 +1,69 @@ + + + + +digest ';' ALGORITHM ';' FILE + + + +

digest ';' ALGORITHM ';' FILE

+

Summary

+

The digest macro computes a cryptographic hash of a file using a specified algorithm (such as MD5, SHA-1, SHA-256, etc.). The result is returned as a hexadecimal string.

+

Syntax

+
${digest;<algorithm>;<file>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Calculate MD5 hash:

+
file.md5=${digest;MD5;target/mybundle.jar}
+
+ +

Calculate SHA-256 hash:

+
file.sha256=${digest;SHA-256;LICENSE.txt}
+
+ +

Calculate SHA-512 for verification:

+
Bundle-Digest-SHA512: ${digest;SHA-512;${@}}
+
+ +

Multiple checksums:

+
md5.checksum=${digest;MD5;artifact.jar}
+sha1.checksum=${digest;SHA-1;artifact.jar}
+sha256.checksum=${digest;SHA-256;artifact.jar}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/dir.html b/org.bndtools.help/docs/macros/dir.html new file mode 100644 index 0000000000..c61476edff --- /dev/null +++ b/org.bndtools.help/docs/macros/dir.html @@ -0,0 +1,69 @@ + + + + +dir ( ';' FILE )* + + + +

dir ( ';' FILE )*

+

Summary

+

The dir macro extracts and returns the parent directory path from one or more file paths. It returns the absolute path to each file's containing directory, filtering out non-existent files.

+

Syntax

+
${dir;<filepath>[;<filepath>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get directory of a single file:

+
source.dir=${dir;src/main/java/Example.java}
+# Returns: /path/to/project/src/main/java
+
+ +

Get directories of multiple files:

+
dirs=${dir;LICENSE.txt;README.md}
+# Returns: /path/to/project,/path/to/project
+
+ +

Use in path construction:

+
parent.dir=${dir;${@}}
+# Gets directory containing current bundle JAR
+
+ +

Build relative path:

+
Bundle-License: ${dir;LICENSE}/LICENSE.txt
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/driver.html b/org.bndtools.help/docs/macros/driver.html new file mode 100644 index 0000000000..d8a7278225 --- /dev/null +++ b/org.bndtools.help/docs/macros/driver.html @@ -0,0 +1,71 @@ + + + + +driver ( ';' NAME )? + + + +

driver ( ';' NAME )?

+

Summary

+

The driver macro identifies the build environment (driver) that is running bnd, such as Gradle, Ant, Eclipse, or IntelliJ. It can be used to return the driver name or check if the current driver matches specific names.

+

The driver should be set when bnd is started by the build tool and can be overridden with the -bnd-driver property. This is useful for avoiding target-dir conflicts between different build tools.

+

Syntax

+
${driver[;<name>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get current driver:

+
${driver}
+# Returns: "gradle" (if running under Gradle)
+
+ +

Check if running under Gradle:

+
${if;${driver;gradle};gradle-specific-config;}
+
+ +

Check multiple drivers:

+
${driver;gradle;maven}
+# Returns: "gradle" if gradle, or "maven" if maven, otherwise ""
+
+ +

Conditional configuration:

+
-target-dir: ${if;${driver;gradle};gradle-build;${if;${driver;eclipse};eclipse-build;build}}
+
+ +

Set via property:

+
-bnd-driver: custom-driver
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/ee.html b/org.bndtools.help/docs/macros/ee.html new file mode 100644 index 0000000000..134bae714f --- /dev/null +++ b/org.bndtools.help/docs/macros/ee.html @@ -0,0 +1,58 @@ + + + + +ee + + + +

ee

+

Summary

+

The ee macro returns the name of the highest Java Execution Environment (EE) required by the classes in the current bundle being analyzed. This is determined by analyzing the bytecode version of all classes in the JAR.

+

Syntax

+
${ee}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Set the Bundle-RequiredExecutionEnvironment based on analyzed classes:

+
Bundle-RequiredExecutionEnvironment: ${ee}
+
+ +

Use in conditional logic:

+
# Check if Java 11+ is required
+java11plus=${if;${vcompare;${ee};JavaSE-11};true;false}
+
+ +

Document the requirement:

+
Bundle-Description: Requires ${ee} or higher
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/endswith.html b/org.bndtools.help/docs/macros/endswith.html new file mode 100644 index 0000000000..de684a41ae --- /dev/null +++ b/org.bndtools.help/docs/macros/endswith.html @@ -0,0 +1,72 @@ + + + + +endswith ';' STRING ';' SUFFIX + + + +

endswith ';' STRING ';' SUFFIX

+

Summary

+

The endswith macro checks if a given string ends with a specified suffix. If the string ends with the suffix, it returns the string; otherwise, it returns an empty string (which evaluates to false in conditional contexts).

+

Syntax

+
${endswith;<string>;<suffix>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check if a filename ends with .jar:

+
${endswith;mybundle.jar;.jar}
+# Returns: "mybundle.jar"
+
+ +

Check if a string ends with specific text:

+
${endswith;com.example.api;.api}
+# Returns: "com.example.api"
+
+ +

Use in conditional logic:

+
${if;${endswith;${project};.test};test-project;regular-project}
+# Checks if project name ends with ".test"
+
+ +

Filter files with specific extension:

+
jar.file=${if;${endswith;${@};.jar};${@};}
+
+ +

Check version suffix:

+
${if;${endswith;${version};-SNAPSHOT};snapshot;release}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/env.html b/org.bndtools.help/docs/macros/env.html new file mode 100644 index 0000000000..dc86d7ca0d --- /dev/null +++ b/org.bndtools.help/docs/macros/env.html @@ -0,0 +1,69 @@ + + + + +env ';' KEY (';' STRING)? + + + +

env ';' KEY (';' STRING)?

+

Summary

+

The env macro looks up an environment variable and returns its value, or returns a default value if the variable is not set. The default is an empty string if not specified.

+

Syntax

+
${env;<variable>[;<default>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get environment variable with default:

+
${env;JAVA_HOME;/usr/lib/jvm/default}
+
+ +

Check if variable exists:

+
${if;${env;CI};running-in-ci;local-build}
+
+ +

Use in paths:

+
user.home=${env;HOME;/home/default}
+
+ +

Empty default:

+
${env;OPTIONAL_VAR}
+# Returns value or "" if not set
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/error.html b/org.bndtools.help/docs/macros/error.html new file mode 100644 index 0000000000..099f3caa8f --- /dev/null +++ b/org.bndtools.help/docs/macros/error.html @@ -0,0 +1,70 @@ + + + + +error ( ';' STRING )* + + + +

error ( ';' STRING )*

+

Summary

+

The error macro generates one or more build errors with custom messages. Each message argument is processed (macros are expanded) and then added to the build error list. This causes the build to fail.

+

Syntax

+
${error;<message>[;<message>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Generate a simple error:

+
${error;This configuration is not supported}
+
+ +

Generate error with variable substitution:

+
${error;Invalid version: ${version}}
+
+ +

Conditional error:

+
${if;${is;${someproperty}};${error;Property someproperty must not be set}}
+
+ +

Multiple error messages:

+
${error;First error message;Second error message;Third error message}
+
+ +

Error with computed values:

+
${error;Bundle ${bsn} requires Java ${ee} but ${java.version} is configured}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/exporters.html b/org.bndtools.help/docs/macros/exporters.html new file mode 100644 index 0000000000..c7ebe60ffb --- /dev/null +++ b/org.bndtools.help/docs/macros/exporters.html @@ -0,0 +1,67 @@ + + + + +exporters ';' PACKAGE + + + +

exporters ';' PACKAGE

+

Summary

+

The exporters macro returns a comma-separated list of JAR names from the classpath that contain (export) a specified package. This is useful for discovering which dependencies provide a particular package.

+

Syntax

+
${exporters;<package-name>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find which JARs provide a specific package:

+
slf4j.jars=${exporters;org.slf4j}
+# Returns: "slf4j-api-1.7.30"
+
+ +

Check if a package is available:

+
${if;${exporters;javax.servlet};servlet-available;servlet-missing}
+
+ +

List providers of multiple packages:

+
json.providers=${exporters;org.json}
+jackson.providers=${exporters;com.fasterxml.jackson.core}
+
+ +

Document dependencies:

+
# Package javax.xml.bind provided by: ${exporters;javax.xml.bind}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/exports.html b/org.bndtools.help/docs/macros/exports.html new file mode 100644 index 0000000000..1b9d751137 --- /dev/null +++ b/org.bndtools.help/docs/macros/exports.html @@ -0,0 +1,71 @@ + + + + +exports + + + +

exports

+

Summary

+

The exports macro returns a comma-separated list of packages that will be exported by the current bundle. The list can be optionally filtered by providing filter arguments.

+

Syntax

+
${exports}
+${exports;<filter>...}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get all exported packages:

+
exported.pkgs=${exports}
+# Returns: "com.example.api,com.example.impl,com.example.util"
+
+ +

Document exported packages:

+
Bundle-Description: Exports ${exports}
+
+ +

Count exported packages:

+
export.count=${size;${exports}}
+
+ +

Use in conditional logic:

+
${if;${exports};has-exports;no-exports}
+
+ +

Filter exported packages:

+
# Get only API packages (if filter parameters are supported)
+api.exports=${exports;.*\.api}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/extension.html b/org.bndtools.help/docs/macros/extension.html new file mode 100644 index 0000000000..9ac1024bc9 --- /dev/null +++ b/org.bndtools.help/docs/macros/extension.html @@ -0,0 +1,66 @@ + + + + +extension ';' PATH + + + +

extension ';' PATH

+

Summary

+

Extract the file extension from a file path, returning the part after the last dot in the filename.

+

Syntax

+
${extension;<path>}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Normalizes the path (handles different path separators) +2. Extracts the last segment (filename) from the path +3. Returns the part after the last . in the filename +4. Returns an empty string if no extension is present

+

The extension is returned without the leading dot.

+

Examples

+
# Extract extension from file path
+${extension;myfile.txt}                    # Returns: txt
+${extension;/path/to/document.pdf}        # Returns: pdf
+${extension;archive.tar.gz}               # Returns: gz (only last extension)
+
+# No extension cases
+${extension;README}                        # Returns: (empty)
+${extension;/path/to/folder/}             # Returns: (empty)
+
+# Multiple dots
+${extension;my.file.name.java}            # Returns: java
+
+# Original examples
+${extension;abcdef.def}                   # Returns: def
+${extension;/foo.bar/abcdefxyz.def}      # Returns: def
+${extension;abcdefxyz}                    # Returns: (empty)
+${extension;/foo.bar/abcdefxyz}          # Returns: (empty)
+
+# Used with other macros
+-include ${extension;${workspace}/.project} == project
+
+ +

Use Cases

+
    +
  1. File Type Detection: Determine the type of file being processed
  2. +
  3. Conditional Logic: Apply different processing based on file extension
  4. +
  5. File Filtering: Select files based on their extensions
  6. +
  7. Path Construction: Build new paths with modified extensions
  8. +
+ + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/fileuri.html b/org.bndtools.help/docs/macros/fileuri.html new file mode 100644 index 0000000000..e631875fb7 --- /dev/null +++ b/org.bndtools.help/docs/macros/fileuri.html @@ -0,0 +1,79 @@ + + + + +fileuri ';' PATH + + + +

fileuri ';' PATH

+

Summary

+

Convert a file path to a proper file URI (e.g., file:///path/to/file).

+

Syntax

+
${fileuri;<path>}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Resolves relative paths against the processor's base directory +2. Converts the path to a canonical file (resolves symbolic links, normalizes) +3. Returns the file URI representation

+

The resulting URI follows the file:/// protocol format with proper escaping of special characters.

+

The base directory depends on context: +- In a project's bnd.bnd: Resolved against the project directory +- In a workspace's cnf/build.bnd: Resolved against the workspace directory

+

Examples

+
# Current directory URI
+${fileuri;.}
+# In project: file:///workspace/my.project/
+# In workspace: file:///workspace/
+
+# Relative path (resolved against base directory)
+${fileuri;src/main/resources/config.xml}
+# Returns: file:///project/base/src/main/resources/config.xml
+
+# Absolute path
+${fileuri;/home/user/file.txt}
+# Returns: file:///home/user/file.txt
+
+# Use in manifest for resource references
+Bundle-Resource: ${fileuri;${workspace}/templates/default.html}
+
+# Reference external files
+X-Config-Location: ${fileuri;../config/settings.properties}
+
+# Handle spaces and special characters (automatically escaped)
+${fileuri;/path/with spaces/file (1).txt}
+# Returns: file:///path/with%20spaces/file%20(1).txt
+
+ +

Use Cases

+
    +
  1. Manifest Headers: Create proper file URIs for bundle manifest headers
  2. +
  3. External References: Reference files outside the bundle with proper URIs
  4. +
  5. Configuration: Specify file locations in configuration that requires URIs
  6. +
  7. Cross-Platform Paths: Generate platform-independent file URIs
  8. +
  9. Resource Location: Document file resource locations in metadata
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/filter.html b/org.bndtools.help/docs/macros/filter.html new file mode 100644 index 0000000000..c0acc316a0 --- /dev/null +++ b/org.bndtools.help/docs/macros/filter.html @@ -0,0 +1,71 @@ + + + + +filter ';' LIST ';' REGEX + + + +

filter ';' LIST ';' REGEX

+

Summary

+

The filter macro filters a list to include only those entries that match a specified regular expression pattern. Entries that don't match are removed from the result.

+

Syntax

+
${filter;<list>;<regex>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Filter for JAR files:

+
${filter;foo.jar,bar.txt,baz.jar;.*\.jar}
+# Returns: "foo.jar,baz.jar"
+
+ +

Filter package names:

+
${filter;com.example.api,com.example.impl,org.other;com\.example\..*}
+# Returns: "com.example.api,com.example.impl"
+
+ +

Filter versions:

+
${filter;1.0.0,2.0.0-SNAPSHOT,2.1.0;.*SNAPSHOT.*}
+# Returns: "2.0.0-SNAPSHOT"
+
+ +

Filter by prefix:

+
${filter;test-bundle,main-bundle,test-util;test-.*}
+# Returns: "test-bundle,test-util"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/filterout.html b/org.bndtools.help/docs/macros/filterout.html new file mode 100644 index 0000000000..d890962c1f --- /dev/null +++ b/org.bndtools.help/docs/macros/filterout.html @@ -0,0 +1,72 @@ + + + + +filterout ';' LIST ';' REGEX + + + +

filterout ';' LIST ';' REGEX

+

Summary

+

The filterout macro filters a list to exclude entries that match a specified regular expression pattern. This is the inverse of ${filter} - entries that match the pattern are removed from the result.

+

Syntax

+
${filterout;<list>;<regex>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Exclude test files:

+
${filterout;Main.java,Test.java,TestUtil.java;.*Test.*}
+# Returns: "Main.java"
+
+ +

Exclude snapshot versions:

+
${filterout;1.0.0,2.0.0-SNAPSHOT,3.0.0;.*SNAPSHOT.*}
+# Returns: "1.0.0,3.0.0"
+
+ +

Exclude specific packages:

+
${filterout;com.example.api,com.example.impl,com.example.test;.*\.test}
+# Returns: "com.example.api,com.example.impl"
+
+ +

Exclude by prefix:

+
${filterout;prod-bundle,test-bundle,dev-bundle;test-.*|dev-.*}
+# Returns: "prod-bundle"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/find.html b/org.bndtools.help/docs/macros/find.html new file mode 100644 index 0000000000..d5fb61874e --- /dev/null +++ b/org.bndtools.help/docs/macros/find.html @@ -0,0 +1,69 @@ + + + + +find ';' VALUE ';' SEARCHED + + + +

find ';' VALUE ';' SEARCHED

+

Summary

+

The find macro returns the starting index position of a substring within a target string, or -1 if not found. This is a simple string search, not a regex pattern match.

+

Syntax

+
${find;<target>;<substring>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find substring position:

+
${find;hello world;world}
+# Returns: 6
+
+ +

Search not found:

+
${find;hello world;foo}
+# Returns: -1
+
+ +

Check if string contains substring:

+
${if;${matches;${find;${path};/test/};-?[0-9]+};contains-test;no-test}
+
+ +

Find file extension:

+
${find;${filename};.}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/findfile.html b/org.bndtools.help/docs/macros/findfile.html new file mode 100644 index 0000000000..36619a2759 --- /dev/null +++ b/org.bndtools.help/docs/macros/findfile.html @@ -0,0 +1,63 @@ + + + + +findfile + + + +

findfile

+
+

layout: default +class: Project +title: findfile ';' PATH ( ';' FILTER ) +summary: Get filtered list of file paths from a directory tree

+
+

Summary

+

The findfile macro recursively searches a directory and returns a filtered list of relative file paths matching the specified filter pattern.

+

Syntax

+
${findfile;<directory>[;<filter>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find all files:

+
${findfile;src}
+
+ +

Find Java source files:

+
${findfile;src;*.java}
+
+ +

Find with exclusion pattern:

+
${findfile;resources;!*.tmp}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/findlast.html b/org.bndtools.help/docs/macros/findlast.html new file mode 100644 index 0000000000..efb03024e5 --- /dev/null +++ b/org.bndtools.help/docs/macros/findlast.html @@ -0,0 +1,68 @@ + + + + +findlast ';' VALUE ';' SEARCHED + + + +

findlast ';' VALUE ';' SEARCHED

+

Summary

+

The findlast macro returns the index position of the last occurrence of a substring within a target string, or -1 if not found. Searches from the end backwards.

+

Syntax

+
${findlast;<substring>;<target>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find last occurrence:

+
${findlast;/;/path/to/file.txt}
+# Returns: 8 (position of last /)
+
+ +

Not found:

+
${findlast;foo;hello world}
+# Returns: -1
+
+ +

Extract file extension:

+
${substring;${filename};${findlast;.;${filename}}}
+
+ +

Get last path component:

+
${substring;${path};${findlast;/;${path}}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/findname.html b/org.bndtools.help/docs/macros/findname.html new file mode 100644 index 0000000000..03ae3c5cc8 --- /dev/null +++ b/org.bndtools.help/docs/macros/findname.html @@ -0,0 +1,72 @@ + + + + +findname + + + +

findname

+
+

layout: default +class: Project +title: findname ';' REGEX ( ';' REPLACEMENT )? +summary: Find bundle resources by filename with optional regex replacement

+
+

Summary

+

The findname macro finds resources in the current bundle by matching filenames (not full paths) against a regular expression, with optional replacement to transform the results.

+

Syntax

+
${findname[;<regex>[;<replacement>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find all resources:

+
${findname}
+
+ +

Find by pattern:

+
${findname;.*\.properties}
+# Returns filenames ending in .properties
+
+ +

Find and transform:

+
${findname;(.*)\.class;$1}
+# Returns class names without .class extension
+
+ +

Extract parts of filenames:

+
${findname;config-(.*)\.xml;$1}
+# Returns: "dev,prod,test" from "config-dev.xml", "config-prod.xml", etc.
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/findpath.html b/org.bndtools.help/docs/macros/findpath.html new file mode 100644 index 0000000000..8c9ad86968 --- /dev/null +++ b/org.bndtools.help/docs/macros/findpath.html @@ -0,0 +1,67 @@ + + + + +findpath ';' REGEX ( ';' REPLACE )? + + + +

findpath ';' REGEX ( ';' REPLACE )?

+

Summary

+

The findpath macro finds resources in the current bundle by matching full resource paths against a regular expression, with optional replacement to transform the results.

+

Syntax

+
${findpath[;<regex>[;<replacement>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find all resources:

+
${findpath}
+# Returns full paths of all resources
+
+ +

Find by path pattern:

+
${findpath;META-INF/.*\.xml}
+# Returns XML files (full path) in META-INF/
+
+ +

Extract path components:

+
${findpath;com/example/(.*)/.*\.class;$1}
+# Returns middle package component
+
+ +

Find and transform:

+
${findpath;src/(.*)\.java;$1}
+# Returns paths without src/ prefix and .java extension
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/findproviders.html b/org.bndtools.help/docs/macros/findproviders.html new file mode 100644 index 0000000000..c64ac57851 --- /dev/null +++ b/org.bndtools.help/docs/macros/findproviders.html @@ -0,0 +1,72 @@ + + + + +findproviders ';' namespace ( ';' FILTER ( ';' STRATEGY)? )? + + + +

findproviders ';' namespace ( ';' FILTER ( ';' STRATEGY)? )?

+

The findproviders macro gives access to the resources in the Workspace repositories, including the projects itself. Its semantics match the OSGi Repository.findProviders() method.

+

It was added to support the use case of including a set of plugins in a resolve to create an executable. Since it is impossible to add a requirement that will add all matching resources, the findproviders macro can be used to find these resources and then turn them into initial requirements. However, this macro will likely find many other use cases since it is quite versatile. If used outside of bndrun files, it can cause circular builds because it might want to search the project that is used in. Use the REPOS Strategy in this case.

+
findproviders ::= namespace ( ';' FILTER ( ';' STRATEGY)? )?
+namespace     ::= ... OSGi namespace
+FILTER        ::= Any LDAP Styled Filter
+STRATEGY      ::= 'ALL' | 'WORKSPACE' | 'REPOS'
+
+ +

If no filter is given or the filter attribute is empty, then all resources that have a capability in the given namespace are returned.

+

The following strategies are available:

+ + + + + + + + + + + + + + + + + + + + + +
StrategyDescription
ALLSearches in the Workspace and all configured Repositories
REPOSSearches only in configured Repositories
WORKSPACESearches in Workspace projects only
+

The result is in PARAMETERS format, to common format in bnd and OSGi. In this case the key will be the Bundle Symbolic Name and the attributes will at least contain the Bundle version. For example:

+
${findproviders;osgi.service}
+
+ +

This finds all resources that have an osgi.service capability. This could return something like:

+
com.h2database;version=1.4.198,
+org.apache.aries.async;version=1.0.1,
+org.apache.felix.configadmin;version=1.9.12,
+org.apache.felix.coordinator;version=1.0.2,
+org.apache.felix.eventadmin;version=1.5.0,
+...
+
+ +

This PARAMETERS format is structured because it has attributes; that makes it harder to use with all kind of other macros. The template macro was intended to help out. This macro takes the name of macro and then treats the contents as a PARAMETERS. It then applies a template to each clause in the PARAMETERS. For example:

+
my.plugins = ${findproviders;osgi.service;\
+  (objectClass=com.example.my.Plugin)}
+-runrequires.plugins = ${template;my.plugins;\
+  osgi.identity;filter:='(osgi.identity=${@})'}
+
+ +

This would turn the previous example into:

+
-runrequires.plugins = \
+    osgi.identity;filter:='(osgi.identity=com.h2database)',
+    osgi.identity;filter:='(osgi.identity=org.apache.aries.async)',
+    ..
+
+ +

Maven support

+

The usage of the findproviders macro as depicted above also works when used in the context of one of the Maven plugins.

+ + diff --git a/org.bndtools.help/docs/macros/first.html b/org.bndtools.help/docs/macros/first.html new file mode 100644 index 0000000000..9cebf90450 --- /dev/null +++ b/org.bndtools.help/docs/macros/first.html @@ -0,0 +1,71 @@ + + + + +first (';' LIST )* + + + +

first (';' LIST )*

+

Summary

+

The first macro returns the first element from one or more comma-separated lists. If multiple lists are provided, it returns the first element from the combined lists.

+

Syntax

+
${first;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get first element from a list:

+
${first;apple,banana,cherry}
+# Returns: "apple"
+
+ +

Get first from multiple lists:

+
${first;red,green;blue,yellow}
+# Returns: "red"
+
+ +

Get first non-empty value:

+
version=${first;${custom.version};${default.version};1.0.0}
+# Returns first defined version
+
+ +

Use with property lists:

+
primary.jar=${first;${buildpath}}
+
+ +

Select first matching file:

+
config.file=${first;${lsr;config;*.properties}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/fmodified.html b/org.bndtools.help/docs/macros/fmodified.html new file mode 100644 index 0000000000..c310848a99 --- /dev/null +++ b/org.bndtools.help/docs/macros/fmodified.html @@ -0,0 +1,72 @@ + + + + +fmodified ( ';' RESOURCE )+ + + + +

fmodified ( ';' RESOURCE )+

+

Summary

+

The fmodified macro finds the most recent modification time among a list of files and returns it as a long integer (milliseconds since epoch). This is useful for detecting when files have changed.

+

Syntax

+
${fmodified;<file>[;<file>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get modification time of a single file:

+
${fmodified;build.gradle}
+# Returns: 1700000000000 (example timestamp)
+
+ +

Find latest modification among multiple files:

+
${fmodified;src/Main.java;src/Util.java;src/Config.java}
+# Returns timestamp of most recently modified file
+
+ +

Check if source files changed:

+
source.modified=${fmodified;${lsr;src;*.java}}
+
+ +

Compare modification times:

+
${if;${vcompare;${fmodified;input.txt};${fmodified;output.txt}};input-newer;output-newer}
+
+ +

Track build inputs:

+
Build-Input-Modified: ${fmodified;${buildpath}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/foreach.html b/org.bndtools.help/docs/macros/foreach.html new file mode 100644 index 0000000000..cb1ae10a22 --- /dev/null +++ b/org.bndtools.help/docs/macros/foreach.html @@ -0,0 +1,84 @@ + + + + +foreach ';' MACRO (';' LIST)* + + + +

foreach ';' MACRO (';' LIST)*

+

Summary

+

The foreach macro iterates over one or more lists and invokes a specified macro for each element, passing both the element value and its index (0-based) as arguments. The results are collected and returned as a comma-separated list.

+

Syntax

+
${foreach;<macro-name>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Transform each element:

+
# Define a macro to wrap elements
+my-macro;$1-modified
+
+# Use foreach
+${foreach;my-macro;apple,banana,cherry}
+# Invokes: ${my-macro;apple;0}, ${my-macro;banana;1}, ${my-macro;cherry;2}
+
+ +

Number items in a list:

+
# Define numbering macro
+num;$2: $1
+
+${foreach;num;first,second,third}
+# Returns: "0: first,1: second,2: third"
+
+ +

Process file list:

+
# Define file processing macro
+process-file;processed-$1
+
+${foreach;process-file;${lsr;src;*.java}}
+
+ +

Generate indexed output:

+
# Define template macro
+item-template;<item index="$2">$1</item>
+
+${foreach;item-template;red,green,blue}
+# Returns XML items with indices
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/format.html b/org.bndtools.help/docs/macros/format.html new file mode 100644 index 0000000000..fd2387dc53 --- /dev/null +++ b/org.bndtools.help/docs/macros/format.html @@ -0,0 +1,112 @@ + + + + +format ';' STRING (';' ANY )* + + + +

format ';' STRING (';' ANY )*

+

Summary

+

Format a string using printf-style format specifiers with provided arguments, similar to Java's String.format().

+

Syntax

+
${format;<format-string>[;<argument>...]}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Processes the format string using Java's Formatter syntax +2. Uses Locale.ROOT for build reproducibility +3. Automatically converts string arguments to appropriate types based on format specifiers +4. Expands arguments that look like macros (starting with ${) +5. Supports conditional formatting with %{<condition>;<true>;<false>}

+

Conditional Syntax

+
%{<condition>;<true-value>;<false-value>}
+
+ +

Where <condition> is evaluated as truthy (non-empty and not "false").

+

Examples

+
# Basic string formatting
+${format;Bundle-Version %s;1.0.0}
+# Returns: Bundle-Version 1.0.0
+
+# Multiple arguments
+${format;%s-%s-%s;com;example;bundle}
+# Returns: com-example-bundle
+
+# Number formatting
+${format;Port number: %d;8080}
+# Returns: Port number: 8080
+
+# Decimal formatting
+${format;Progress: %.2f%%;75.5}
+# Returns: Progress: 75.50%
+
+# Date/time formatting
+${format;%tF;${tstamp}}
+# Returns: 2024-01-15 (ISO date format)
+
+${format;%tY-%tm-%td;${tstamp}}
+# Returns: 2024-01-15 (custom date format)
+
+# Conditional formatting
+${format;%{${debug}};DEBUG-MODE;RELEASE-MODE}
+# Returns: DEBUG-MODE if ${debug} is set, otherwise RELEASE-MODE
+
+# Width and padding
+${format;ID: %05d;42}
+# Returns: ID: 00042
+
+# Combining with other macros
+${format;Built on %tF at %tT;${now};${now}}
+# Returns: Built on 2024-01-15 at 14:30:45
+
+ +

Format Specifiers

+

Common format specifiers include:

+ +

See Java's Formatter documentation for complete format specifier syntax.

+

Use Cases

+
    +
  1. Version Strings: Create formatted version identifiers
  2. +
  3. Manifest Headers: Generate complex manifest header values
  4. +
  5. Date/Time Stamps: Format timestamps in various formats
  6. +
  7. Numeric IDs: Format numbers with padding or specific precision
  8. +
  9. Conditional Text: Generate different text based on build properties
  10. +
  11. Reproducible Builds: Format values consistently using Locale.ROOT
  12. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/frange.html b/org.bndtools.help/docs/macros/frange.html new file mode 100644 index 0000000000..fab692b7bd --- /dev/null +++ b/org.bndtools.help/docs/macros/frange.html @@ -0,0 +1,76 @@ + + + + +frange ';' VERSION ( ';' BOOLEAN )? + + + +

frange ';' VERSION ( ';' BOOLEAN )?

+

Summary

+

The frange macro generates an OSGi filter expression representing a version range. By default, it creates a consumer-compatible range (major version increment). Optionally, you can request a provider-compatible range (minor version increment).

+

Syntax

+
${frange;<version>[;provider]}
+${frange;<version-range>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Consumer compatibility range:

+
Import-Package: org.example.*;version="${frange;1.2.3}"
+# Generates: (&(version>=1.2.3)(!(version>=2.0.0)))
+
+ +

Provider compatibility range:

+
Require-Capability: osgi.service;filter:="${frange;1.0.0;true}"
+# Generates: (&(version>=1.0.0)(!(version>=1.1.0)))
+
+ +

Use with version property:

+
bundle.range=${frange;${bundle.version}}
+
+ +

Dependency filter:

+
Require-Bundle: com.example.api;bundle-version="${frange;2.5.0}"
+
+ +

Version range input:

+
${frange;[1.0.0,3.0.0)}
+# Converts range to filter syntax
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/gestalt.html b/org.bndtools.help/docs/macros/gestalt.html new file mode 100644 index 0000000000..913d5e9208 --- /dev/null +++ b/org.bndtools.help/docs/macros/gestalt.html @@ -0,0 +1,71 @@ + + + + +gestalt ';' NAME ( ';' NAME (';' ANY )? )? + + + +

gestalt ';' NAME ( ';' NAME (';' ANY )? )?

+

Summary

+

The gestalt macro provides access to gestalt properties that describe the build environment. Gestalt is a set of parts describing the environment, where each part has a name and optional attributes. This can be configured globally or per-workspace via the -gestalt property.

+

Syntax

+
${gestalt;<part>[;<key>[;<value>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check if gestalt part exists:

+
${gestalt;ci}
+# Returns: "ci" if CI gestalt is defined, "" otherwise
+
+ +

Get attribute value:

+
${gestalt;platform;os}
+# Returns the OS attribute value from platform gestalt
+
+ +

Match specific value:

+
${if;${gestalt;ci;provider;github};github-ci;other-ci}
+
+ +

Configure gestalt:

+
-gestalt: ci;provider=github, platform;os=linux
+
+ +

Use in conditional logic:

+
${if;${gestalt;ci};ci-mode;local-mode}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/get.html b/org.bndtools.help/docs/macros/get.html new file mode 100644 index 0000000000..4a68b06f25 --- /dev/null +++ b/org.bndtools.help/docs/macros/get.html @@ -0,0 +1,75 @@ + + + + +get ';' INDEX (';' LIST )* + + + +

get ';' INDEX (';' LIST )*

+

Summary

+

The get macro retrieves an element from one or more lists at a specified index position. It supports negative indices to count from the end of the list.

+

Syntax

+
${get;<index>;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get first element (index 0):

+
${get;0;apple,banana,cherry}
+# Returns: "apple"
+
+ +

Get second element:

+
${get;1;red,green,blue}
+# Returns: "green"
+
+ +

Get last element (negative index):

+
${get;-1;one,two,three}
+# Returns: "three"
+
+ +

Get second-to-last element:

+
${get;-2;alpha,beta,gamma,delta}
+# Returns: "gamma"
+
+ +

Get from multiple lists:

+
${get;3;red,green;blue,yellow}
+# Returns: "yellow" (4th element from combined list)
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/githead.html b/org.bndtools.help/docs/macros/githead.html new file mode 100644 index 0000000000..0b18517390 --- /dev/null +++ b/org.bndtools.help/docs/macros/githead.html @@ -0,0 +1,68 @@ + + + + +githead + + + +

githead

+

Summary

+

The githead macro returns the SHA-1 hash of the current Git HEAD commit. It searches for a .git directory starting from the project base directory and walking up the file hierarchy, then resolves symbolic references to find the actual commit hash.

+

Syntax

+
${githead}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Include Git commit in manifest:

+
Bundle-SCM-Revision: ${githead}
+# Result: Bundle-SCM-Revision: 4A3B2C1D0E9F8A7B6C5D4E3F2A1B0C9D8E7F6A5B
+
+ +

Create version with Git hash:

+
Implementation-Version: ${version}-${githead}
+
+ +

Document build source:

+
Build-From: commit ${githead}
+
+ +

Conditional on Git availability:

+
git.revision=${if;${githead};${githead};not-in-git-repo}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/glob.html b/org.bndtools.help/docs/macros/glob.html new file mode 100644 index 0000000000..371217b020 --- /dev/null +++ b/org.bndtools.help/docs/macros/glob.html @@ -0,0 +1,78 @@ + + + + +glob ';' GLOBEXP + + + +

glob ';' GLOBEXP

+

Summary

+

The glob macro converts a glob pattern (shell-style wildcard pattern) into a Java regular expression. This is useful when you need regex patterns but want to write simpler glob syntax.

+

Syntax

+
${glob;<glob-pattern>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert simple wildcard:

+
${glob;*.jar}
+# Returns regex matching JAR files
+
+ +

Match with path:

+
${glob;com/example/**/*.class}
+# Returns regex for any .class file under com/example/
+
+ +

Use in filter:

+
${filter;${packages};${glob;com.example.*}}
+# Filter packages matching glob pattern
+
+ +

Negated pattern:

+
${glob;!*.test.jar}
+# Returns negative lookahead regex excluding test JARs
+
+ +

Multiple alternatives:

+
${glob;*.{jar,war,ear}}
+# Matches files with .jar, .war, or .ear extensions
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/global.html b/org.bndtools.help/docs/macros/global.html new file mode 100644 index 0000000000..b74b031bd3 --- /dev/null +++ b/org.bndtools.help/docs/macros/global.html @@ -0,0 +1,77 @@ + + + + +global ';' KEY ( ';' DEFAULT )? + + + +

global ';' KEY ( ';' DEFAULT )?

+

Summary

+

The global macro provides access to user-specific settings stored in the ~/.bnd/settings.json file. This allows builds to use machine-specific configuration like credentials, API tokens, or user preferences without storing them in project files.

+

Syntax

+
${global;<key>[;<default>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Access a custom setting:

+
maven.user=${global;maven.username}
+
+ +

Use with default value:

+
api.key=${global;example.api.key;default-key}
+
+ +

Access credentials:

+
-connection: ${global;nexus.url}; \
+             uid=${global;nexus.username}; \
+             pwd=${global;nexus.password}
+
+ +

Get public key:

+
signing.key=${global;key.public}
+
+ +

Conditional on global setting:

+
${if;${global;enable.feature};enabled;disabled}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/ide.html b/org.bndtools.help/docs/macros/ide.html new file mode 100644 index 0000000000..dced2e9a7b --- /dev/null +++ b/org.bndtools.help/docs/macros/ide.html @@ -0,0 +1,73 @@ + + + + +ide ';' ( 'javac.target' | 'javac.source' ) + + + +

ide ';' ( 'javac.target' | 'javac.source' )

+

Summary

+

The ide macro reads Java compiler source and target version settings from the Eclipse IDE's project preferences. This allows bnd builds to use the same Java version settings configured in the IDE.

+

Syntax

+
${ide;<setting>[;<default>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get target bytecode version:

+
javac.target=${ide;javac.target}
+# Returns: "1.8" (for Java 8) or "11" (for Java 11), etc.
+
+ +

Get source compatibility version:

+
javac.source=${ide;javac.source}
+
+ +

Use with default:

+
source.level=${ide;javac.source;1.8}
+target.level=${ide;javac.target;1.8}
+
+ +

Configure bundle based on IDE settings:

+
Bundle-RequiredExecutionEnvironment: JavaSE-${ide;javac.target}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/if.html b/org.bndtools.help/docs/macros/if.html new file mode 100644 index 0000000000..c03036c436 --- /dev/null +++ b/org.bndtools.help/docs/macros/if.html @@ -0,0 +1,28 @@ + + + + +if ';' STRING ';' STRING ( ';' STRING )? + + + +

if ';' STRING ';' STRING ( ';' STRING )?

+

if ::= 'if' ';' condition ';' expansion ( ';' expansion )? + condition ::= true | false + false ::= 'false' | '' + true ::= ! false + expansion ::= ...

+

The ${if} macro allows a conditional expansion. The first argument is the condition. the condition is either false (empty or 'false') or otherwise true. If the condition is true, the value of the macro is the second argument, the first expansion. Otherwise, if a third argument is specified this is returned. If no third argument is specified, an empty string is returned.

+

Notice that if a macro is not set, it will revert to its literal value. This can be confusing. For example, if the macro foo is not set, the ${if;${foo};TRUE;FALSE} will be TRUE. If you want to handle unset as false, the def might be of use.

+

Examples

+
# expands to 'B'
+aorb = ${if;;A;B}
+
+# Display ${foo} if set to a non-empty string that is not false, otherwise 'Ouch'. See also ${def} 
+whatisfoo = ${if;${foo};${foo};Ouch}
+
+# Include a file conditionally. If ${test} is not empty or false, the file is included
+-include ${if;${test};test.bnd}
+
+ + diff --git a/org.bndtools.help/docs/macros/imports.html b/org.bndtools.help/docs/macros/imports.html new file mode 100644 index 0000000000..609a9c33f5 --- /dev/null +++ b/org.bndtools.help/docs/macros/imports.html @@ -0,0 +1,73 @@ + + + + +imports + + + +

imports

+

Summary

+

The imports macro returns a comma-separated list of packages that will be imported by the current bundle. The list can be optionally filtered by providing filter arguments.

+

Syntax

+
${imports}
+${imports;<filter>...}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get all imported packages:

+
imported.pkgs=${imports}
+# Returns: "org.osgi.framework,javax.servlet,org.slf4j,..."
+
+ +

Document imported packages:

+
Bundle-Description: Depends on ${imports}
+
+ +

Count imported packages:

+
import.count=${size;${imports}}
+
+ +

Use in conditional logic:

+
${if;${imports};has-imports;no-imports}
+
+ +

Check for specific imports:

+
has.servlet=${if;${filter;${imports};javax\.servlet.*};yes;no}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/index.html b/org.bndtools.help/docs/macros/index.html new file mode 100644 index 0000000000..f925f53516 --- /dev/null +++ b/org.bndtools.help/docs/macros/index.html @@ -0,0 +1,151 @@ + + + + +Macros Reference + + + +

Macros Reference

+ + + diff --git a/org.bndtools.help/docs/macros/indexof.html b/org.bndtools.help/docs/macros/indexof.html new file mode 100644 index 0000000000..93123d9257 --- /dev/null +++ b/org.bndtools.help/docs/macros/indexof.html @@ -0,0 +1,68 @@ + + + + +indexof ';' STRING (';' LIST )* + + + +

indexof ';' STRING (';' LIST )*

+

Summary

+

The indexof macro searches for a value in combined lists and returns its 0-based index position, or -1 if not found.

+

Syntax

+
${indexof;<value>;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find value in list:

+
${indexof;green;red,green,blue}
+# Returns: 1
+
+ +

Not found:

+
${indexof;yellow;red,green,blue}
+# Returns: -1
+
+ +

Search multiple lists:

+
${indexof;target;${list1};${list2}}
+
+ +

Check if value exists:

+
${if;${matches;${indexof;test;${list}};-?[0-9]+};found;not-found}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/is.html b/org.bndtools.help/docs/macros/is.html new file mode 100644 index 0000000000..3e30b3d6ee --- /dev/null +++ b/org.bndtools.help/docs/macros/is.html @@ -0,0 +1,65 @@ + + + + +is ( ';' ANY )* + + + +

is ( ';' ANY )*

+

Summary

+

The is macro checks if all provided arguments are equal to each other. Returns true if all values match, false otherwise.

+

Syntax

+
${is;<value>;<value>[;<value>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check equality of two values:

+
${if;${is;${version};1.0.0};version-match;version-mismatch}
+
+ +

Compare multiple values:

+
${is;abc;abc;abc}
+# Returns: true
+
+ +

Check property equality:

+
${if;${is;${env};production};prod-config;dev-config}
+
+ +

Validate configuration:

+
${is;${driver};gradle;gradle}
+# Returns: true if driver is gradle
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/isdir.html b/org.bndtools.help/docs/macros/isdir.html new file mode 100644 index 0000000000..df2426405c --- /dev/null +++ b/org.bndtools.help/docs/macros/isdir.html @@ -0,0 +1,73 @@ + + + + +isdir ( ';' FILE )+ + + + +

isdir ( ';' FILE )+

+

Summary

+

The isdir macro checks whether all specified file paths are directories. It returns "true" only if all paths exist and are directories; otherwise, it returns "false".

+

Syntax

+
${isdir;<path>[;<path>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check a single directory:

+
${isdir;src/main/java}
+# Returns: "true" if src/main/java is a directory
+
+ +

Check multiple directories:

+
${isdir;src;test;resources}
+# Returns: "true" only if all three are directories
+
+ +

Use in conditional logic:

+
${if;${isdir;generated};directory-exists;directory-missing}
+
+ +

Conditional file processing:

+
${if;${isdir;${basedir}/config};${cat;config/settings.xml};default-config}
+
+ +

Validate project structure:

+
structure.valid=${isdir;src/main/java;src/main/resources;src/test/java}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/isempty.html b/org.bndtools.help/docs/macros/isempty.html new file mode 100644 index 0000000000..e4b5e45e72 --- /dev/null +++ b/org.bndtools.help/docs/macros/isempty.html @@ -0,0 +1,66 @@ + + + + +isempty ( ';' STRING )* + + + +

isempty ( ';' STRING )*

+

Summary

+

The isempty macro checks if all provided arguments are empty strings. Returns true only if all values are empty, false otherwise.

+

Syntax

+
${isempty[;<string>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check if empty:

+
${if;${isempty;${value}};value-empty;value-has-content}
+
+ +

Check multiple values:

+
${isempty;;;;}
+# Returns: true (all empty)
+
+ +

Validate required fields:

+
${if;${isempty;${name};${email}};missing-fields;fields-ok}
+
+ +

No arguments:

+
${isempty}
+# Returns: true
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/isfile.html b/org.bndtools.help/docs/macros/isfile.html new file mode 100644 index 0000000000..b8dbf74476 --- /dev/null +++ b/org.bndtools.help/docs/macros/isfile.html @@ -0,0 +1,74 @@ + + + + +isfile (';' FILE )+ + + + +

isfile (';' FILE )+

+

Summary

+

The isfile macro checks whether all specified file paths are regular files (not directories or special files). It returns "true" only if all paths exist and are regular files; otherwise, it returns "false".

+

Syntax

+
${isfile;<path>[;<path>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check a single file:

+
${isfile;build.gradle}
+# Returns: "true" if build.gradle exists and is a file
+
+ +

Check multiple files:

+
${isfile;pom.xml;build.gradle;settings.gradle}
+# Returns: "true" only if all three are files
+
+ +

Use in conditional logic:

+
${if;${isfile;custom.bnd};${cat;custom.bnd};default-settings}
+
+ +

Validate required files:

+
${if;${isfile;LICENSE;README.md};files-present;${error;Missing required files}}
+
+ +

Check file existence before processing:

+
config=${if;${isfile;config.properties};${cat;config.properties};{}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/isnumber.html b/org.bndtools.help/docs/macros/isnumber.html new file mode 100644 index 0000000000..73b381fa18 --- /dev/null +++ b/org.bndtools.help/docs/macros/isnumber.html @@ -0,0 +1,68 @@ + + + + +isnumber ( ';' STRING )* + + + +

isnumber ( ';' STRING )*

+

Summary

+

The isnumber macro checks if all provided arguments are valid numeric values. Returns true only if all arguments are numbers, false otherwise.

+

Syntax

+
${isnumber;<string>[;<string>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check if numeric:

+
${if;${isnumber;${value}};is-numeric;not-numeric}
+
+ +

Validate multiple values:

+
${isnumber;123;45.6;-78}
+# Returns: true
+
+ +

Not a number:

+
${isnumber;abc}
+# Returns: false
+
+ +

Mixed values:

+
${isnumber;123;abc}
+# Returns: false (all must be numeric)
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/join.html b/org.bndtools.help/docs/macros/join.html new file mode 100644 index 0000000000..df9423db3a --- /dev/null +++ b/org.bndtools.help/docs/macros/join.html @@ -0,0 +1,74 @@ + + + + +join ( ';' LIST )+ + + + +

join ( ';' LIST )+

+

Summary

+

The join macro combines one or more lists into a single comma-separated list. It flattens all input lists and returns them joined with commas.

+

Syntax

+
${join;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Join two lists:

+
${join;apple,banana;cherry,date}
+# Returns: "apple,banana,cherry,date"
+
+ +

Join multiple lists:

+
${join;red,green;blue;yellow,orange}
+# Returns: "red,green,blue,yellow,orange"
+
+ +

Flatten nested lists:

+
list1=a,b,c
+list2=d,e,f
+${join;${list1};${list2}}
+# Returns: "a,b,c,d,e,f"
+
+ +

Combine with other macros:

+
${join;${exports};${imports}}
+# Returns all exported and imported packages
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/js.html b/org.bndtools.help/docs/macros/js.html new file mode 100644 index 0000000000..854596e803 --- /dev/null +++ b/org.bndtools.help/docs/macros/js.html @@ -0,0 +1,70 @@ + + + + +js (';' JAVASCRIPT )* + + + +

js (';' JAVASCRIPT )*

+

Summary

+

Deprecated: Javascript script engine removed in Java 15. This macro might not work anymore and might be removed in future versions.

+

The js macro executes one or more JavaScript expressions using the Java ScriptEngine and returns the value of the last expression or any output produced.

+

Syntax

+
${js;<expression>[;<expression>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Simple calculation:

+
${js;2 + 2}
+# Returns: "4"
+
+ +

String manipulation:

+
${js;"hello".toUpperCase()}
+# Returns: "HELLO"
+
+ +

Multiple expressions:

+
${js;var x = 10;x * 2}
+# Returns: "20"
+
+ +

Access properties:

+
${js;domain.getProperty("version")}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/last.html b/org.bndtools.help/docs/macros/last.html new file mode 100644 index 0000000000..3826e75e0a --- /dev/null +++ b/org.bndtools.help/docs/macros/last.html @@ -0,0 +1,72 @@ + + + + +last (';' LIST )* + + + +

last (';' LIST )*

+

Summary

+

The last macro returns the last element from one or more comma-separated lists. If multiple lists are provided, it returns the last element from the combined lists.

+

Syntax

+
${last;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get last element from a list:

+
${last;apple,banana,cherry}
+# Returns: "cherry"
+
+ +

Get last from multiple lists:

+
${last;red,green;blue,yellow}
+# Returns: "yellow"
+
+ +

Get last defined value:

+
version=${last;1.0.0;${custom.version};${snapshot.version}}
+# Returns last defined version
+
+ +

Use with property lists:

+
latest.jar=${last;${buildpath}}
+
+ +

Select last matching file:

+
newest=${last;${sort;${lsr;logs;*.log}}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/lastindexof.html b/org.bndtools.help/docs/macros/lastindexof.html new file mode 100644 index 0000000000..a399b1c92d --- /dev/null +++ b/org.bndtools.help/docs/macros/lastindexof.html @@ -0,0 +1,68 @@ + + + + +lastindexof ';' STRING (';' LIST )* + + + +

lastindexof ';' STRING (';' LIST )*

+

Summary

+

The lastindexof macro searches for a value in combined lists and returns the 0-based index position of its last occurrence, or -1 if not found.

+

Syntax

+
${lastindexof;<value>;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find last occurrence:

+
${lastindexof;blue;red,blue,green,blue}
+# Returns: 3
+
+ +

Not found:

+
${lastindexof;yellow;red,green,blue}
+# Returns: -1
+
+ +

Search multiple lists:

+
${lastindexof;target;${list1};${list2}}
+
+ +

Check existence:

+
${if;${matches;${lastindexof;test;${list}};-?[0-9]+};found;not-found}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/length.html b/org.bndtools.help/docs/macros/length.html new file mode 100644 index 0000000000..f72dd3d07d --- /dev/null +++ b/org.bndtools.help/docs/macros/length.html @@ -0,0 +1,64 @@ + + + + +length STRING + + + +

length STRING

+

Summary

+

The length macro returns the number of characters in a string. Returns 0 if no argument is provided.

+

Syntax

+
${length[;<string>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get string length:

+
${length;hello world}
+# Returns: 11
+
+ +

Check if empty:

+
${if;${length;${value}};has-value;empty}
+
+ +

Validate input length:

+
${if;${length;${password}};password-ok;password-required}
+
+ +

No argument:

+
${length}
+# Returns: 0
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/list.html b/org.bndtools.help/docs/macros/list.html new file mode 100644 index 0000000000..b783995ecb --- /dev/null +++ b/org.bndtools.help/docs/macros/list.html @@ -0,0 +1,90 @@ + + + + +list (';' KEY)* + + + +

list (';' KEY)*

+

Summary

+

Merge multiple property values into a single comma-separated list with automatic semicolon escaping, useful for combining list-valued properties that contain semicolons.

+

Syntax

+
${list[;<property-name>...]}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Looks up each property name to get its value +2. Splits each value using quoted string parsing (respects quotes) +3. Escapes unescaped semicolons within elements (replaces ; with \;) +4. Merges all elements into a single comma-separated list +5. Returns an empty string if no properties are specified

+

This is particularly useful when list elements contain semicolons (like OSGi version ranges or attributes) and need to be passed to other macros.

+

Examples

+
# Define list properties with semicolons
+deps = com.foo;version="[1,2)", com.bar;version="[1.2,2)"
+
+# Merge and add attributes to each element
+-buildpath: ${replacelist;${list;deps};$;\\;strategy=highest}
+# Results in:
+# com.foo;version="[1,2)";strategy=highest,com.bar;version="[1.2,2)";strategy=highest
+
+# Merge multiple lists
+files = foo.jar, bar.jar
+extras = baz.jar, qux.jar
+all-files = ${list;files;extras}
+# Returns: foo.jar,bar.jar,baz.jar,qux.jar
+
+# Merge build paths with attributes
+compile-deps = javax.servlet;version=3.0, commons-io;version=2.5
+runtime-deps = slf4j-api;version=1.7
+all-deps = ${list;compile-deps;runtime-deps}
+
+# Create a combined package list with versions
+Private-Package: ${list;internal-packages;test-packages}
+
+# Handle empty properties (no-op for empty ones)
+${list;optional-deps;main-deps}
+# Only includes non-empty properties
+
+# Complex example with attributes
+base-deps = org.osgi.core;version="[6,7)", org.osgi.service.component;version="[1.3,2)"
+extra-deps = org.apache.felix.scr;version="[2,3)"
+-buildpath: ${list;base-deps;extra-deps}
+
+ +

Use Cases

+
    +
  1. Dependency Management: Combine dependencies with version ranges from different sources
  2. +
  3. Build Path Merging: Merge multiple classpath or build path properties
  4. +
  5. Package Lists: Combine package lists that include OSGi attributes
  6. +
  7. Attribute Manipulation: Prepare lists for processing with replacelist to add attributes
  8. +
  9. Configuration Merging: Merge configuration lists from different profiles
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/literal.html b/org.bndtools.help/docs/macros/literal.html new file mode 100644 index 0000000000..ce8937b821 --- /dev/null +++ b/org.bndtools.help/docs/macros/literal.html @@ -0,0 +1,70 @@ + + + + +literal ';' STRING + + + +

literal ';' STRING

+

Summary

+

The literal macro prevents macro expansion by wrapping a value with the macro prefix ${ and suffix }. This effectively creates a literal macro reference that won't be expanded in the current pass.

+

Syntax

+
${literal;<value>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Create a literal macro reference:

+
${literal;version}
+# Returns: "${version}"
+
+ +

Delay macro expansion:

+
deferred=${literal;basedir}
+# deferred contains the string "${basedir}", not the actual path
+
+ +

Pass macro syntax as a value:

+
template=${literal;project.name}
+# Later: expanded=${template} will evaluate ${project.name}
+
+ +

Store macro patterns:

+
pattern=${literal;if;condition;true;false}
+# Returns: "${if;condition;true;false}"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/long2date.html b/org.bndtools.help/docs/macros/long2date.html new file mode 100644 index 0000000000..1a18d31c20 --- /dev/null +++ b/org.bndtools.help/docs/macros/long2date.html @@ -0,0 +1,69 @@ + + + + +long2date + + + +

long2date

+

Summary

+

The long2date macro converts a long integer representing milliseconds since the Unix epoch (January 1, 1970, 00:00:00 UTC) into a human-readable date string.

+

Syntax

+
${long2date;<milliseconds>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert current time:

+
${long2date;${currenttime}}
+# Returns: "Wed Nov 20 10:30:45 UTC 2024" (example)
+
+ +

Convert stored timestamp:

+
Build-Date: ${long2date;1700000000000}
+# Returns human-readable date
+
+ +

Format file modification time:

+
Modified: ${long2date;${fmodified;${@}}}
+
+ +

Display build timestamp:

+
${long2date;${tstamp}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/lsa.html b/org.bndtools.help/docs/macros/lsa.html new file mode 100644 index 0000000000..f5958cd679 --- /dev/null +++ b/org.bndtools.help/docs/macros/lsa.html @@ -0,0 +1,70 @@ + + + + +lsa ';' DIR (';' SELECTORS ) + + + +

lsa ';' DIR (';' SELECTORS )

+

Summary

+

The lsa macro returns a comma-separated list of absolute file paths from a directory, with optional filtering using selectors.

+

Syntax

+
${lsa;<directory>[;<selector>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

List all files:

+
${lsa;src/main/java}
+# Returns absolute paths
+
+ +

Filter by pattern:

+
${lsa;lib;*.jar}
+# Lists all JAR files with absolute paths
+
+ +

Multiple filters:

+
${lsa;resources;*.xml;*.properties}
+
+ +

Use in manifest:

+
Resources: ${lsa;config}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/lsr.html b/org.bndtools.help/docs/macros/lsr.html new file mode 100644 index 0000000000..cc3839076b --- /dev/null +++ b/org.bndtools.help/docs/macros/lsr.html @@ -0,0 +1,71 @@ + + + + +lsr ';' DIR (';' SELECTORS ) + + + +

lsr ';' DIR (';' SELECTORS )

+

Summary

+

The lsr macro returns a comma-separated list of relative file paths from a directory, with optional filtering using selectors.

+

Syntax

+
${lsr;<directory>[;<selector>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

List all files:

+
${lsr;src/main/java}
+# Returns relative paths
+
+ +

Filter by pattern:

+
${lsr;lib;*.jar}
+# Lists all JAR files with relative paths
+
+ +

Find source files:

+
${lsr;src;*.java}
+# All Java source files
+
+ +

Multiple patterns:

+
${lsr;resources;*.xml;*.properties}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/map.html b/org.bndtools.help/docs/macros/map.html new file mode 100644 index 0000000000..3dbd136d48 --- /dev/null +++ b/org.bndtools.help/docs/macros/map.html @@ -0,0 +1,83 @@ + + + + +map ';' MACRO (';' LIST)* + + + +

map ';' MACRO (';' LIST)*

+

Summary

+

The map macro applies a transformation function (specified as a macro name) to each element of one or more lists, collecting the results into a new comma-separated list. This is similar to the functional programming map operation.

+

Syntax

+
${map;<macro-name>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Transform list elements:

+
# Define transformation macro
+upper;${toupper;$1}
+
+# Map to uppercase
+${map;upper;apple,banana,cherry}
+
+ +

Add prefix to each element:

+
# Define prefix macro
+add-prefix;modified-$1
+
+${map;add-prefix;file1,file2,file3}
+# Returns: "modified-file1,modified-file2,modified-file3"
+
+ +

Process file list:

+
# Define file processor
+process;${basename;$1}
+
+${map;process;/path/to/file1.jar;/path/to/file2.jar}
+# Returns basenames of files
+
+ +

Calculate transformations:

+
# Define calculation macro
+double;${multiply;$1;2}
+
+${map;double;1,2,3,4,5}
+# Returns: "2,4,6,8,10"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/matches.html b/org.bndtools.help/docs/macros/matches.html new file mode 100644 index 0000000000..d211443b1d --- /dev/null +++ b/org.bndtools.help/docs/macros/matches.html @@ -0,0 +1,66 @@ + + + + +matches STRING REGEX + + + +

matches STRING REGEX

+

Summary

+

The matches macro tests whether a string matches a given regular expression pattern. Returns true if the entire string matches, false otherwise.

+

Syntax

+
${matches;<string>;<regex>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check pattern match:

+
${if;${matches;v1.2.3;v[0-9]+\.[0-9]+\.[0-9]+};valid-version;invalid}
+
+ +

Validate format:

+
${matches;com.example.api;com\.example\..*}
+# Returns: true
+
+ +

Check numeric:

+
${if;${matches;${value};[0-9]+};is-number;not-number}
+
+ +

Test package pattern:

+
${matches;${package};com\..*\.impl}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/maven_version.html b/org.bndtools.help/docs/macros/maven_version.html new file mode 100644 index 0000000000..22f94056d6 --- /dev/null +++ b/org.bndtools.help/docs/macros/maven_version.html @@ -0,0 +1,52 @@ + + + + +maven_version ';' MAVEN-VERSION + + + +

maven_version ';' MAVEN-VERSION

+

Summary

+

Convert a Maven-style version string to OSGi version format. Note: Use version_cleanup instead, which can be used in more contexts.

+

Syntax

+
${maven_version;<version>}
+
+ +

Parameters

+ +

Behavior

+

This macro is deprecated in favor of version_cleanup.

+

Converts Maven version formats (which may use hyphens) to OSGi version format (which uses dots): +- Replaces hyphens with dots in the qualifier +- Ensures the version follows OSGi's major.minor.micro.qualifier structure

+

For example: 1.2.3-SNAPSHOT becomes 1.2.3.SNAPSHOT

+

Examples

+
# Convert Maven version
+${maven_version;1.2.3-SNAPSHOT}
+# Returns: 1.2.3.SNAPSHOT
+
+# In Bundle-Version
+Bundle-Version: ${maven_version;${project.version}}
+
+# However, prefer version_cleanup:
+Bundle-Version: ${version_cleanup;${project.version}}
+
+ +

Deprecation Note

+

This macro should not be used in new code. Use version_cleanup instead because: +- version_cleanup can be used in more contexts (not just Builder) +- version_cleanup handles more edge cases and version formats +- version_cleanup is the recommended approach going forward

+ + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/max.html b/org.bndtools.help/docs/macros/max.html new file mode 100644 index 0000000000..fed42d2fec --- /dev/null +++ b/org.bndtools.help/docs/macros/max.html @@ -0,0 +1,64 @@ + + + + +max (';' LIST )* + + + +

max (';' LIST )*

+

Summary

+

The max macro compares strings lexicographically using Java's String.compareTo() and returns the maximum (highest) value.

+

Syntax

+
${max;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find maximum string:

+
${max;apple,banana,cherry}
+# Returns: "cherry"
+
+ +

Multiple lists:

+
${max;abc,xyz;def,mno}
+# Returns: "xyz"
+
+ +

Numeric strings (lexicographic):

+
${max;1,10,2,20}
+# Returns: "20" (lexicographic, not numeric)
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/md5.html b/org.bndtools.help/docs/macros/md5.html new file mode 100644 index 0000000000..a9067b46e5 --- /dev/null +++ b/org.bndtools.help/docs/macros/md5.html @@ -0,0 +1,69 @@ + + + + +md5 ';' RESOURCE + + + +

md5 ';' RESOURCE

+

Summary

+

The md5 macro calculates the MD5 hash of a resource that exists within the current bundle JAR. The result can be returned as either Base64 (default) or hexadecimal encoding.

+

Syntax

+
${md5;<resource-path>[;<encoding>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get MD5 of a resource (Base64):

+
${md5;META-INF/services/com.example.Service}
+# Returns Base64-encoded MD5
+
+ +

Get MD5 in hexadecimal format:

+
${md5;config/application.properties;hex}
+# Returns: "5d41402abc4b2a76b9719d911017c592" (example)
+
+ +

Hash manifest file:

+
manifest.md5=${md5;META-INF/MANIFEST.MF;hex}
+
+ +

Verify resource integrity:

+
Bundle-ResourceMD5: ${md5;important-config.xml}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/min.html b/org.bndtools.help/docs/macros/min.html new file mode 100644 index 0000000000..f0b31e8fbb --- /dev/null +++ b/org.bndtools.help/docs/macros/min.html @@ -0,0 +1,64 @@ + + + + +min (';' LIST )* + + + +

min (';' LIST )*

+

Summary

+

The min macro compares strings lexicographically using Java's String.compareTo() and returns the minimum (lowest) value.

+

Syntax

+
${min;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find minimum string:

+
${min;apple,banana,cherry}
+# Returns: "apple"
+
+ +

Multiple lists:

+
${min;xyz,abc;mno,def}
+# Returns: "abc"
+
+ +

Numeric strings (lexicographic):

+
${min;1,10,2,20}
+# Returns: "1" (lexicographic, not numeric)
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/native_capability.html b/org.bndtools.help/docs/macros/native_capability.html new file mode 100644 index 0000000000..9b87ba4d78 --- /dev/null +++ b/org.bndtools.help/docs/macros/native_capability.html @@ -0,0 +1,78 @@ + + + + +native_capability ( ';' ( 'os.name' | 'os.version' | 'os.processor' ) '=' STRING )* + + + +

native_capability ( ';' ( 'os.name' | 'os.version' | 'os.processor' ) '=' STRING )*

+

Summary

+

The native_capability macro generates an OSGi native capability string in the format specified for Provide-Capability or Require-Capability headers. It represents the native platform according to OSGi RFC 188, automatically detecting the current platform or using explicit overrides.

+

Syntax

+
${native_capability[;<property>=<value>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Auto-detect current platform:

+
${native_capability}
+# On Windows 7 x64:
+# osgi.native;osgi.native.osname:List<String>="Windows7,Windows 7,Win32";
+#   osgi.native.osversion:Version=6.1.0;
+#   osgi.native.processor:List<String>="x86-64,amd64,em64t,x86_64"
+
+ +

Override OS name:

+
${native_capability;os.name=Linux}
+
+ +

Specify complete platform:

+
${native_capability;os.name=Linux;os.version=3.2.4;os.processor=x86-64}
+
+ +

Use in capability header:

+
Provide-Capability: ${native_capability}
+
+ +

Cross-platform requirement:

+
Require-Capability: ${native_capability;os.name=MacOSX;os.version=10.15.0}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/ncompare.html b/org.bndtools.help/docs/macros/ncompare.html new file mode 100644 index 0000000000..3c326ac1b9 --- /dev/null +++ b/org.bndtools.help/docs/macros/ncompare.html @@ -0,0 +1,92 @@ + + + + +ncompare NUMBER NUMBER + + + +

ncompare NUMBER NUMBER

+

Summary

+

Compare two numbers numerically using Java's Double.compare() method, returning -1, 0, or 1.

+

Syntax

+
${ncompare;<number1>;<number2>}
+
+ +

Parameters

+ +

Behavior

+

Compares the two numbers numerically and returns: +- 0 - The numbers are equal +- 1 - The first number is greater than the second +- -1 - The first number is less than the second

+

Numbers are parsed as doubles, supporting both integers and floating-point values.

+

Examples

+
# Equal numbers
+${ncompare;42;42}
+# Returns: 0
+
+# First number greater
+${ncompare;100;50}
+# Returns: 1
+
+# First number less
+${ncompare;10;20}
+# Returns: -1
+
+# Floating-point comparison
+${ncompare;3.14;2.71}
+# Returns: 1
+
+# Negative numbers
+${ncompare;-5;-10}
+# Returns: 1 (-5 is greater than -10)
+
+# Use in conditional logic
+-include ${if;${ncompare;${Bundle-Version};2.0};modern.bnd;legacy.bnd}
+
+# Compare with zero
+${ncompare;${errorcount};0}
+# Returns: 1 if errors exist, 0 if no errors
+
+# Numeric comparison (not lexicographic)
+${ncompare;10;2}
+# Returns: 1 (10 is greater than 2 numerically)
+
+# Compare with macro values
+${ncompare;${size;${errors}};5}
+# Check if more than 5 errors
+
+ +

Use Cases

+
    +
  1. Threshold Checks: Verify if a value exceeds a threshold
  2. +
  3. Conditional Builds: Make decisions based on numeric values
  4. +
  5. Validation: Check if counts, sizes, or versions meet requirements
  6. +
  7. Quality Gates: Ensure numeric metrics are within acceptable ranges
  8. +
  9. Build Optimization: Skip steps based on numeric conditions
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/nmax.html b/org.bndtools.help/docs/macros/nmax.html new file mode 100644 index 0000000000..a047268ae8 --- /dev/null +++ b/org.bndtools.help/docs/macros/nmax.html @@ -0,0 +1,63 @@ + + + + +nmax (';' LIST )* + + + +

nmax (';' LIST )*

+

Summary

+

The nmax macro compares numeric values using floating-point comparison and returns the maximum (highest) number.

+

Syntax

+
${nmax;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find maximum number:

+
${nmax;10,5,20,3}
+# Returns: "20"
+
+ +

Multiple lists:

+
${nmax;100,200;50,150}
+# Returns: "200"
+
+ +

Decimals:

+
${nmax;1.5,2.3,0.9}
+# Returns: "2.3"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/nmin.html b/org.bndtools.help/docs/macros/nmin.html new file mode 100644 index 0000000000..47b39ceee7 --- /dev/null +++ b/org.bndtools.help/docs/macros/nmin.html @@ -0,0 +1,63 @@ + + + + +nmin (';' LIST )* + + + +

nmin (';' LIST )*

+

Summary

+

The nmin macro compares numeric values using floating-point comparison and returns the minimum (lowest) number.

+

Syntax

+
${nmin;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find minimum number:

+
${nmin;10,5,20,3}
+# Returns: "3"
+
+ +

Multiple lists:

+
${nmin;100,200;50,150}
+# Returns: "50"
+
+ +

Decimals:

+
${nmin;1.5,2.3,0.9}
+# Returns: "0.9"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/now.html b/org.bndtools.help/docs/macros/now.html new file mode 100644 index 0000000000..fc0b52a6a7 --- /dev/null +++ b/org.bndtools.help/docs/macros/now.html @@ -0,0 +1,71 @@ + + + + +now ( 'long' | DATEFORMAT ) + + + +

now ( 'long' | DATEFORMAT )

+

Summary

+

The now macro returns the current date and time. It can return the raw Date object, milliseconds since epoch, or a formatted date string.

+

Syntax

+
${now[;<format>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get current time in millis:

+
${now;long}
+# Returns: 1700000000000 (example)
+
+ +

Custom format:

+
${now;yyyy-MM-dd HH:mm:ss}
+# Returns: "2024-11-20 10:30:45"
+
+ +

ISO format:

+
${now;yyyy-MM-dd'T'HH:mm:ss'Z'}
+# Returns: "2024-11-20T10:30:45Z"
+
+ +

Default format:

+
${now}
+# Returns: "Wed Nov 20 10:30:45 UTC 2024"
+
+ +

Build timestamp:

+
Build-Time: ${now;yyyy-MM-dd HH:mm z}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/nsort.html b/org.bndtools.help/docs/macros/nsort.html new file mode 100644 index 0000000000..8005b1f69f --- /dev/null +++ b/org.bndtools.help/docs/macros/nsort.html @@ -0,0 +1,71 @@ + + + + +nsort (';' LIST )+ + + + +

nsort (';' LIST )+

+

Summary

+

The nsort macro combines one or more lists and sorts their contents numerically. Unlike alphabetic sorting, it treats values as numbers, so "2" comes before "10".

+

Syntax

+
${nsort;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Sort numbers correctly:

+
${nsort;10,2,1,20,3}
+# Returns: "1,2,3,10,20" (not "1,10,2,20,3")
+
+ +

Sort with leading zeros:

+
${nsort;001,010,002,100}
+# Returns: "1,2,10,100" (leading zeros removed)
+
+ +

Combine and sort multiple lists:

+
${nsort;5,15,25;10,20,30}
+# Returns: "5,10,15,20,25,30"
+
+ +

Sort version-like numbers:

+
${nsort;1,11,2,21,3}
+# Returns: "1,2,3,11,21"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/osfile.html b/org.bndtools.help/docs/macros/osfile.html new file mode 100644 index 0000000000..0216e199ab --- /dev/null +++ b/org.bndtools.help/docs/macros/osfile.html @@ -0,0 +1,69 @@ + + + + +osfile ';' DIR ';' NAME + + + +

osfile ';' DIR ';' NAME

+

Summary

+

The osfile macro constructs an absolute file path by combining a base directory and a relative path, using the operating system's native path separator (e.g., backslash on Windows, forward slash on Unix).

+

Syntax

+
${osfile;<base>;<path>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Create OS-specific path on Unix:

+
${osfile;/home/user;project/src/Main.java}
+# Returns: "/home/user/project/src/Main.java"
+
+ +

Create OS-specific path on Windows:

+
${osfile;C:/Users/user;project\\src\\Main.java}
+# Returns: "C:\Users\user\project\src\Main.java"
+
+ +

Build path from project base:

+
config.file=${osfile;${basedir};config/app.properties}
+
+ +

Create platform-specific classpath entry:

+
jar.path=${osfile;${basedir};lib/dependency.jar}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_allsourcepath.html b/org.bndtools.help/docs/macros/p_allsourcepath.html new file mode 100644 index 0000000000..2956d35395 --- /dev/null +++ b/org.bndtools.help/docs/macros/p_allsourcepath.html @@ -0,0 +1,53 @@ + + + + +p_allsourcepath + + + +

p_allsourcepath

+
+

layout: default +class: Project +title: p_allsourcepath +summary: Get paths to all source directories

+
+

Summary

+

The p_allsourcepath macro returns all source directories for the project, including those from dependencies, as a comma-separated list.

+

Syntax

+
${p_allsourcepath}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get all source paths:

+
All-Sources: ${p_allsourcepath}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_bootclasspath.html b/org.bndtools.help/docs/macros/p_bootclasspath.html new file mode 100644 index 0000000000..d338ad3557 --- /dev/null +++ b/org.bndtools.help/docs/macros/p_bootclasspath.html @@ -0,0 +1,53 @@ + + + + +p_bootclasspath + + + +

p_bootclasspath

+
+

layout: default +class: Project +title: p_bootclasspath +summary: Get the project's boot classpath

+
+

Summary

+

The p_bootclasspath macro returns the project's boot classpath (Java runtime libraries) as a comma-separated list of paths.

+

Syntax

+
${p_bootclasspath}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get boot classpath:

+
Boot-Classpath: ${p_bootclasspath}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_buildpath.html b/org.bndtools.help/docs/macros/p_buildpath.html new file mode 100644 index 0000000000..58be720e1c --- /dev/null +++ b/org.bndtools.help/docs/macros/p_buildpath.html @@ -0,0 +1,58 @@ + + + + +p_buildpath + + + +

p_buildpath

+
+

layout: default +class: Project +title: p_buildpath +summary: Get the project's buildpath as a list

+
+

Summary

+

The p_buildpath macro returns the project's buildpath (compile-time dependencies) as a comma-separated list of file paths.

+

Syntax

+
${p_buildpath}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get buildpath:

+
Build-Dependencies: ${p_buildpath}
+
+ +

Count buildpath entries:

+
dependency.count=${size;${split;,;${p_buildpath}}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_dependson.html b/org.bndtools.help/docs/macros/p_dependson.html new file mode 100644 index 0000000000..7003664408 --- /dev/null +++ b/org.bndtools.help/docs/macros/p_dependson.html @@ -0,0 +1,52 @@ + + + + +p_dependson + + + +

p_dependson

+
+

layout: default +class: Project +title: p_dependson +summary: Get list of project names this project depends on

+
+

Summary

+

The p_dependson macro returns a comma-separated list of project names that the current project depends on (as specified in the -dependson directive).

+

Syntax

+
${p_dependson}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get dependent projects:

+
Depends-On: ${p_dependson}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_output.html b/org.bndtools.help/docs/macros/p_output.html new file mode 100644 index 0000000000..ac75295920 --- /dev/null +++ b/org.bndtools.help/docs/macros/p_output.html @@ -0,0 +1,57 @@ + + + + +p_output + + + +

p_output

+
+

layout: default +class: Project +title: p_output +summary: Get the absolute path to the project's output directory

+
+

Summary

+

The p_output macro returns the absolute path to the project's output/target directory where compiled classes and built artifacts are placed.

+

Syntax

+
${p_output}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get output directory:

+
Output-Directory: ${p_output}
+
+ +

Reference output in paths:

+
classes.location=${p_output}/classes
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_sourcepath.html b/org.bndtools.help/docs/macros/p_sourcepath.html new file mode 100644 index 0000000000..6a251b572b --- /dev/null +++ b/org.bndtools.help/docs/macros/p_sourcepath.html @@ -0,0 +1,53 @@ + + + + +p_sourcepath + + + +

p_sourcepath

+
+

layout: default +class: Project +title: p_sourcepath +summary: Get the project's source directories

+
+

Summary

+

The p_sourcepath macro returns the project's source directories as a comma-separated list of paths.

+

Syntax

+
${p_sourcepath}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get source paths:

+
Source-Directories: ${p_sourcepath}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/p_testpath.html b/org.bndtools.help/docs/macros/p_testpath.html new file mode 100644 index 0000000000..6b1a8f969c --- /dev/null +++ b/org.bndtools.help/docs/macros/p_testpath.html @@ -0,0 +1,53 @@ + + + + +p_testpath + + + +

p_testpath

+
+

layout: default +class: Project +title: p_testpath +summary: Get the project's test runtime path

+
+

Summary

+

The p_testpath macro returns the test runtime path (JARs placed on the classpath for testing) as a comma-separated list of file paths.

+

Syntax

+
${p_testpath}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get test path:

+
Test-Dependencies: ${p_testpath}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/packageattribute.html b/org.bndtools.help/docs/macros/packageattribute.html new file mode 100644 index 0000000000..6dac7c2e80 --- /dev/null +++ b/org.bndtools.help/docs/macros/packageattribute.html @@ -0,0 +1,14 @@ + + + + +packageattribute ';' PACKAGE (';' ATTRIBUTE)? + + + +

packageattribute ';' PACKAGE (';' ATTRIBUTE)?

+

The packageattribute macro returns the value of the specified attribute name for the +specified package name. These values are only available after analysis is complete. The +default attribute to return is the version.

+ + diff --git a/org.bndtools.help/docs/macros/packages.html b/org.bndtools.help/docs/macros/packages.html new file mode 100644 index 0000000000..1084dd979e --- /dev/null +++ b/org.bndtools.help/docs/macros/packages.html @@ -0,0 +1,77 @@ + + + + +packages + + + +

packages

+

The packages macro provides a query function over the contained packages of a bundle. A simple query language is used to query the packages and filter them. +For example if you want to export all packages that are annotated with the @org.example.Export annotation:

+
-exportcontents: ${packages;ANNOTATED;org.example.Export}
+
+ +

(NB. using the macro inside Export-Package/Private-Package is an error, because they define the content of the bundle. The packages macro can only be used in the final manifest calculation.).

+

All pattern matching is based on fully qualified name and uses the globbing model.

+

More examples:

+
# List all packages in the bundle, irrespective of how they were included
+All-Packages: ${packages}
+
+# List all packages, alternative syntax
+All-Packages: ${packages;ANY}
+
+# Export packages containing the substring 'export'
+-exportcontents: ${packages;NAMED;*export*}
+
+# Export packages that contain a version. Useful when wrapping existing bundles while keeping exports intact
+-exportcontents: ${packages;VERSIONED}
+
+# List of packages that were included in the bundle as conditional packages
+Added: ${packages;CONDITIONAL}
+
+ +

The following table specifies the available query options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
QueryParameterDescription
ANYMatches any package
ANNOTATEDPATTERNThe package must have an annotation that matches the pattern. The annotation must be either CLASS or RUNTIME retained, and placed on the `package-info.class` for the package.
NAMEDPATTERNThe package FQN must match the given pattern.
VERSIONEDPackages that are versioned. Usually this means exported packages.
CONDITIONALPackages that were included in the bundle as conditional packages. That is, + by using -conditionalpackage or + Conditional-Package.
+ + diff --git a/org.bndtools.help/docs/macros/path.html b/org.bndtools.help/docs/macros/path.html new file mode 100644 index 0000000000..0fc5cb8491 --- /dev/null +++ b/org.bndtools.help/docs/macros/path.html @@ -0,0 +1,70 @@ + + + + +path ( ';' FILES )+ + + + +

path ( ';' FILES )+

+

Summary

+

The path macro joins one or more lists of file paths using the operating system's path separator (: on Unix, ; on Windows). This is useful for creating classpaths and other path lists.

+

Syntax

+
${path;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Create a classpath on Unix:

+
${path;lib/a.jar,lib/b.jar,lib/c.jar}
+# Returns: "lib/a.jar:lib/b.jar:lib/c.jar"
+
+ +

Create a classpath on Windows:

+
${path;lib/a.jar,lib/b.jar,lib/c.jar}
+# Returns: "lib/a.jar;lib/b.jar;lib/c.jar"
+
+ +

Combine multiple path lists:

+
${path;${buildpath};${testpath}}
+# Joins both lists with OS separator
+
+ +

Build Java classpath:

+
-classpath=${path;${lsr;lib;*.jar}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/pathseparator.html b/org.bndtools.help/docs/macros/pathseparator.html new file mode 100644 index 0000000000..5d3a320f3f --- /dev/null +++ b/org.bndtools.help/docs/macros/pathseparator.html @@ -0,0 +1,63 @@ + + + + +pathseparator + + + +

pathseparator

+

Summary

+

The pathseparator macro returns the operating system's path separator character used to separate entries in path lists like classpaths.

+

Syntax

+
${pathseparator}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get the path separator:

+
${pathseparator}
+# Returns: ":" on Unix, ";" on Windows
+
+ +

Build a path manually:

+
classpath=lib/a.jar${pathseparator}lib/b.jar${pathseparator}lib/c.jar
+
+ +

Use in conditionals:

+
${if;${equals;${pathseparator};:};unix;windows}
+
+ +

Split paths:

+
${split;${pathseparator};${some.path}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/permissions.html b/org.bndtools.help/docs/macros/permissions.html new file mode 100644 index 0000000000..dfcc623e62 --- /dev/null +++ b/org.bndtools.help/docs/macros/permissions.html @@ -0,0 +1,77 @@ + + + + +permissions (';' ( 'packages' | 'admin' | 'permissions' ) )+ + + + +

permissions (';' ( 'packages' | 'admin' | 'permissions' ) )+

+

Summary

+

The permissions macro generates OSGi permission declarations in the format required for the OSGi permissions resource (OSGI-INF/permissions.perm). It can generate package permissions and admin permissions.

+

Syntax

+
${permissions[;<type>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Generate package permissions:

+
${permissions;packages}
+# Returns:
+# (org.osgi.framework.PackagePermission "com.example.api" "import")
+# (org.osgi.framework.PackagePermission "com.example.impl" "export")
+
+ +

Generate admin permissions:

+
${permissions;admin}
+# Returns: (org.osgi.framework.AdminPermission)
+
+ +

Generate all permissions:

+
${permissions;all}
+
+ +

Use in permissions file:

+
# In OSGI-INF/permissions.perm
+${permissions;packages}
+${permissions;admin}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/propertiesdir.html b/org.bndtools.help/docs/macros/propertiesdir.html new file mode 100644 index 0000000000..50d86b92db --- /dev/null +++ b/org.bndtools.help/docs/macros/propertiesdir.html @@ -0,0 +1,65 @@ + + + + +propertiesdir + + + +

propertiesdir

+
+

layout: default +title: propertiesdir +class: Processor +summary: Get the directory containing the current properties file

+
+

Summary

+

The propertiesdir macro returns the absolute path to the directory containing the current properties file being processed.

+

Syntax

+
${propertiesdir}
+
+ +

Parameters

+

None - this macro takes no parameters and will error if arguments are provided.

+

Behavior

+ +

Examples

+

Get properties directory:

+
Config-Directory: ${propertiesdir}
+
+ +

Reference sibling files:

+
license.file=${propertiesdir}/LICENSE.txt
+
+ +

Relative resources:

+
resources=${propertiesdir}/resources
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/propertiesname.html b/org.bndtools.help/docs/macros/propertiesname.html new file mode 100644 index 0000000000..1bfdd77922 --- /dev/null +++ b/org.bndtools.help/docs/macros/propertiesname.html @@ -0,0 +1,65 @@ + + + + +propertiesname + + + +

propertiesname

+
+

layout: default +title: propertiesname +class: Project +summary: Get the filename of the current properties file

+
+

Summary

+

The propertiesname macro returns the filename (without path) of the properties file being processed. This is typically bnd.bnd for projects or workspace configuration files.

+

Syntax

+
${propertiesname}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get current file name:

+
Current-File: ${propertiesname}
+# Returns: "bnd.bnd" or "my.bndrun", etc.
+
+ +

Use in logging:

+
Build-Info: Built from ${propertiesname}
+
+ +

Conditional based on file:

+
${if;${equals;${propertiesname};test.bnd};test-mode;normal-mode}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/rand.html b/org.bndtools.help/docs/macros/rand.html new file mode 100644 index 0000000000..f931cd2079 --- /dev/null +++ b/org.bndtools.help/docs/macros/rand.html @@ -0,0 +1,68 @@ + + + + +rand (';' MIN ' (;' MAX )?)? + + + +

rand (';' MIN ' (;' MAX )?)?

+

Summary

+

The rand macro generates a random integer. By default it returns a number between 0 and 100, or within a specified min/max range (inclusive).

+

Syntax

+
${rand[;<max>[;<min>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Default range (0-100):

+
${rand}
+# Returns: 42 (example)
+
+ +

Custom max:

+
${rand;10}
+# Returns: 7 (between 0-10)
+
+ +

Custom range:

+
${rand;100;50}
+# Returns: 73 (between 50-100)
+
+ +

Generate unique build number:

+
build.number=${rand;9999;1000}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/random.html b/org.bndtools.help/docs/macros/random.html new file mode 100644 index 0000000000..2601ba0ac4 --- /dev/null +++ b/org.bndtools.help/docs/macros/random.html @@ -0,0 +1,72 @@ + + + + +random + + + +

random

+

Summary

+

The random macro generates a random string that is guaranteed to be a valid Java identifier. The first character is always a letter, and subsequent characters are letters or numbers.

+

Syntax

+
${random[;<length>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Generate default 8-character identifier:

+
${random}
+# Returns: "aB3xY9kL" (example)
+
+ +

Generate specific length:

+
${random;12}
+# Returns: "K5mPqR7sT2uV" (example, 12 chars)
+
+ +

Create unique package name:

+
test.package=${random;16}
+
+ +

Generate unique property:

+
temp.id.${random;6}=value
+
+ +

Create unique class names:

+
TestClass${random;4}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/range.html b/org.bndtools.help/docs/macros/range.html new file mode 100644 index 0000000000..4aae91f470 --- /dev/null +++ b/org.bndtools.help/docs/macros/range.html @@ -0,0 +1,53 @@ + + + + +range ';' RANGE_MASK ( ';' VERSION ) + + + +

range ';' RANGE_MASK ( ';' VERSION )

+

The range macro takes a version range mask/template and uses it calculate a range from a given version. The primary reason for the ${range} macro is to be used in the version policy. With the version policy we have a version of an exported package and we need to calculate the range for that. The rules come from the consumer or provider policy. However, this policy can be overridden on the Import-Package header by specifying the version as a range macro:

+
Import-Package: com.example.myownpolicy; version="${range;[==,=+)}", *
+
+ +

Since the version for the exported package is set as ${@}, the macro will calculate the proper semantic range for a provider.

+

The syntax for the range macro is:

+
range ::= ( '\[' |'\( ) mask ',' mask ( '\)' | '\]' )
+mask  ::= m ( m ( m )? )? q
+m     ::= [0-9=+-~]
+q     ::= [0-9=~Ss]
+
+ +

The meaning of the characters is:

+ +

Examples

+

With ${range}:

+ +

With ${versionmask}:

+ +

Also see versionmask / version.

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/reject.html b/org.bndtools.help/docs/macros/reject.html new file mode 100644 index 0000000000..ba87efaa77 --- /dev/null +++ b/org.bndtools.help/docs/macros/reject.html @@ -0,0 +1,72 @@ + + + + +reject ';' LIST ';' REGEX + + + +

reject ';' LIST ';' REGEX

+

Summary

+

Filter a list to exclude elements that match a regular expression. This macro is an alias for the filterout macro.

+

Syntax

+
${reject;<list>;<regex>}
+
+ +

Parameters

+ +

Behavior

+

Returns a new list containing only the elements from the input list that do not match the specified regular expression pattern.

+

This macro is functionally identical to filterout.

+

Examples

+
# Reject items starting with "test"
+packages = com.example.api, com.example.test, com.example.impl
+${reject;${packages};.*\.test}
+# Returns: com.example.api,com.example.impl
+
+# Exclude test files
+files = Main.java, Test.java, Helper.java, TestHelper.java
+${reject;${files};.*Test.*}
+# Returns: Main.java,Helper.java
+
+# Exclude internal packages
+all-packages = com.company.api, com.company.internal, com.company.util
+-exportpackage: ${reject;${all-packages};.*\.internal.*}
+# Returns: com.company.api,com.company.util
+
+# Remove snapshot versions
+versions = 1.0.0, 2.0.0-SNAPSHOT, 3.0.0
+${reject;${versions};.*SNAPSHOT.*}
+# Returns: 1.0.0,3.0.0
+
+ +

Use Cases

+
    +
  1. Package Exclusion: Exclude internal or test packages from exports
  2. +
  3. File Filtering: Remove unwanted files from a list
  4. +
  5. Dependency Filtering: Exclude specific dependencies by pattern
  6. +
  7. Clean-up: Remove items matching unwanted patterns
  8. +
+

Notes

+ + + +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/removeall.html b/org.bndtools.help/docs/macros/removeall.html new file mode 100644 index 0000000000..dfe8051ebc --- /dev/null +++ b/org.bndtools.help/docs/macros/removeall.html @@ -0,0 +1,82 @@ + + + + +removeall ';' LIST ';' LIST + + + +

removeall ';' LIST ';' LIST

+

Summary

+

Remove all elements from the first list that are present in the second list, returning the filtered result.

+

Syntax

+
${removeall;<list1>[;<list2>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+
# Remove specific packages
+all-packages = com.example.api, com.example.impl, com.example.test
+test-packages = com.example.test
+production-packages = ${removeall;${all-packages};${test-packages}}
+# Returns: com.example.api,com.example.impl
+
+# Remove dependencies
+all-deps = foo.jar, bar.jar, baz.jar, test.jar
+test-deps = test.jar
+runtime-deps = ${removeall;${all-deps};${test-deps}}
+# Returns: foo.jar,bar.jar,baz.jar
+
+# Remove multiple items
+items = a, b, c, d, e
+to-remove = b, d
+result = ${removeall;${items};${to-remove}}
+# Returns: a,c,e
+
+# No second list - returns empty
+${removeall;foo,bar,baz}
+# Returns: (empty)
+
+# Remove from build path
+full-buildpath = ${buildpath}, ${testpath}
+exclude-items = junit, mockito
+-buildpath: ${removeall;${full-buildpath};${exclude-items}}
+
+ +

Use Cases

+
    +
  1. Package Exclusion: Remove specific packages from export or import lists
  2. +
  3. Dependency Management: Exclude certain dependencies from build paths
  4. +
  5. List Filtering: Remove known unwanted elements from a list
  6. +
  7. Configuration: Filter out test or development-only items from production builds
  8. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/replace.html b/org.bndtools.help/docs/macros/replace.html new file mode 100644 index 0000000000..0d727511d0 --- /dev/null +++ b/org.bndtools.help/docs/macros/replace.html @@ -0,0 +1,73 @@ + + + + +replace ';' LIST ';' REGEX (';' STRING (';' STRING)? )? + + + +

replace ';' LIST ';' REGEX (';' STRING (';' STRING)? )?

+

Summary

+

The replace macro applies regex-based replacement to each element in a comma-separated list. Uses simple comma splitting (doesn't handle quoted sections).

+

Syntax

+
${replace;<list>;<regex>[;<replacement>[;<delimiter>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Add file extension:

+
impls: foo,bar
+${replace;${impls};$;.jar}
+# Returns: "foo.jar,bar.jar"
+
+ +

Replace pattern:

+
${replace;v1.0,v2.0,v3.0;^v;version-}
+# Returns: "version-1.0,version-2.0,version-3.0"
+
+ +

Using back-references:

+
${replace;com.example.api,com.example.impl;com\.example\.(.+);$1}
+# Returns: "api,impl"
+
+ +

Custom delimiter:

+
${replace;a,b,c;$;-suffix;;}
+# Returns: "a-suffix;b-suffix;c-suffix"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/replacelist.html b/org.bndtools.help/docs/macros/replacelist.html new file mode 100644 index 0000000000..5d3bdd6879 --- /dev/null +++ b/org.bndtools.help/docs/macros/replacelist.html @@ -0,0 +1,67 @@ + + + + +replacelist ';' LIST ';' REGEX (';' STRING (';' STRING)? )? + + + +

replacelist ';' LIST ';' REGEX (';' STRING (';' STRING)? )?

+

Summary

+

The replacelist macro applies regex-based replacement to each element in a list. Unlike ${replace}, it uses a sophisticated splitter that handles quoted sections, preserving commas within quotes.

+

Syntax

+
${replacelist;<list>;<regex>[;<replacement>[;<delimiter>]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Add to quoted elements:

+
impls: foo;version="[1,2)", bar;version="[1.2,2)"
+${replacelist;${list;impls};$;\\;strategy=highest}
+# Returns: foo;version="[1,2)";strategy=highest,bar;version="[1.2,2)";strategy=highest
+
+ +

Process dependencies:

+
deps: lib;version="1.0,2.0",tool;version="2.0"
+${replacelist;${deps};$;,optional}
+
+ +

Back-references with quotes:

+
${replacelist;a="x,y",b="z";(.+)="(.+)";$1:$2}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/replacestring.html b/org.bndtools.help/docs/macros/replacestring.html new file mode 100644 index 0000000000..30f5e19843 --- /dev/null +++ b/org.bndtools.help/docs/macros/replacestring.html @@ -0,0 +1,77 @@ + + + + +replacestring ';' STRING ';' REGEX (';' STRING )? + + + +

replacestring ';' STRING ';' REGEX (';' STRING )?

+

Summary

+

The replacestring macro applies regex-based replacement to a single string, supporting back-references for captured groups.

+

Syntax

+
${replacestring;<string>;<regex>[;<replacement>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Simple replacement:

+
description: This is, possibly, the best implementation ever!
+${replacestring;${description};possibly;definitely}
+# Returns: "This is, definitely, the best implementation ever!"
+
+ +

Remove pattern:

+
${replacestring;version-1.2.3;version-;}
+# Returns: "1.2.3"
+
+ +

Using back-references:

+
${replacestring;com.example.impl;com\.(.+)\.impl;$1}
+# Returns: "example"
+
+ +

Multiple replacements:

+
${replacestring;hello world;[aeiou];*}
+# Returns: "h*ll* w*rld"
+
+ +

Path normalization:

+
${replacestring;${path};\\;/}
+# Replace backslashes with forward slashes
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/repo.html b/org.bndtools.help/docs/macros/repo.html new file mode 100644 index 0000000000..d324d72578 --- /dev/null +++ b/org.bndtools.help/docs/macros/repo.html @@ -0,0 +1,25 @@ + + + + +repo ';' BSN ( ';' VERSION ( ';' STRATEGY )? )? + + + +

repo ';' BSN ( ';' VERSION ( ';' STRATEGY )? )?

+

Returns the absolute file system paths to the specified artifacts in the repositories.

+

BSN is be a comma-separated list of bundle symbolic names. If the artifact +is not a bundle, then the synthetic bundle symbolic names of groupId:artifactId +can be used. Normally only a single bundle symbolic name is used since the remainder of the options apply to all the bundle symbolic names.

+

VERSION is a OSGi version-range for the artifact. Special values supported are: +* project - This return the built artifact from a project in the Bnd workspace. +* snapshot - Synonym for project. +* latest - The highest version available in a project in the Bnd workspace or the repositories. The built artifact from a project in the Bnd workspace is always used if it exists under the assumption the Bnd workspace is always building the latest version of the artifact. +If the version range is not specified, the version range [0,∞) is used.

+

Note about version-range: It is important to know that this is needs to be a version range according to OSGi version semantics (not Maven! version). That means for example, to refer to the maven version 4.6.0-dcm you have to write 4.6.0.-dcm which then internally will be translated to the maven equivalent if you are using e.g. MavenBndRepository.

+

STRATEGY is the selection strategy to be used when multiple artifacts with the bundle symbolic name exist within the version range. The strategies supported are: +* HIGHEST - The highest version for the artifact which is included by the version range. This is the default strategy and is the strategy always used by the special version range latest. +* LOWEST - The lowest version for the artifact which is included by the version range. +* EXACT - When this strategy is used, the version range must be a single version which is the version which is searched for. If multiple repositories contain the the exact version of the artifact, the artifact from the first repository is used.

+ + diff --git a/org.bndtools.help/docs/macros/repodigests.html b/org.bndtools.help/docs/macros/repodigests.html new file mode 100644 index 0000000000..3ceaaead1a --- /dev/null +++ b/org.bndtools.help/docs/macros/repodigests.html @@ -0,0 +1,68 @@ + + + + +repodigests ( ';' NAME )* + + + +

repodigests ( ';' NAME )*

+

Summary

+

The repodigests macro returns hexadecimal cryptographic digests representing the contents of all repositories or specific named repositories. This is useful for detecting changes in repository state.

+

Syntax

+
${repodigests[;<repo-name>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get all repository digests:

+
${repodigests}
+# Returns: "a1b2c3d4e5f6...,f6e5d4c3b2a1..."
+
+ +

Specific repositories:

+
${repodigests;Maven Central;Local}
+
+ +

Check for changes:

+
repo.state=${repodigests}
+
+ +

Conditional on digest:

+
${if;${repodigests;Release};has-digest;no-digest}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/repos.html b/org.bndtools.help/docs/macros/repos.html new file mode 100644 index 0000000000..8df4aff899 --- /dev/null +++ b/org.bndtools.help/docs/macros/repos.html @@ -0,0 +1,63 @@ + + + + +repos + + + +

repos

+

Summary

+

The repos macro returns a comma-separated list of the names of all repositories configured in the current project or workspace.

+

Syntax

+
${repos}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get all repository names:

+
${repos}
+# Returns: "Maven Central, Local, Workspace, Release" (example)
+
+ +

Document available repositories:

+
Bundle-RepositoriesUsed: ${repos}
+
+ +

Count repositories:

+
repo.count=${size;${split;,;${repos}}}
+
+ +

Check for specific repository:

+
${if;${findlast;${repos};Maven Central};has-central;no-central}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/retainall.html b/org.bndtools.help/docs/macros/retainall.html new file mode 100644 index 0000000000..d6d8abffce --- /dev/null +++ b/org.bndtools.help/docs/macros/retainall.html @@ -0,0 +1,87 @@ + + + + +retainall ';' LIST ';' LIST + + + +

retainall ';' LIST ';' LIST

+

Summary

+

Keep only elements from the first list that are also present in the second list, effectively computing the intersection of two lists.

+

Syntax

+
${retainall;<list1>;<list2>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+
# Find common packages
+packages1 = com.example.api, com.example.impl, com.example.util
+packages2 = com.example.api, com.example.util, com.other.api
+common-packages = ${retainall;${packages1};${packages2}}
+# Returns: com.example.api,com.example.util
+
+# Keep only approved dependencies
+all-deps = foo.jar, bar.jar, baz.jar, qux.jar
+approved-deps = foo.jar, baz.jar
+used-deps = ${retainall;${all-deps};${approved-deps}}
+# Returns: foo.jar,baz.jar
+
+# List intersection
+list-a = a, b, c, d
+list-b = c, d, e, f
+intersection = ${retainall;${list-a};${list-b}}
+# Returns: c,d
+
+# Filter build path to allowed items
+buildpath = ${workspace.buildpath}
+allowed-libs = commons-io, commons-lang, slf4j-api
+-buildpath: ${retainall;${buildpath};${allowed-libs}}
+
+# No common elements
+list-x = a, b, c
+list-y = d, e, f
+${retainall;${list-x};${list-y}}
+# Returns: (empty)
+
+ +

Use Cases

+
    +
  1. Whitelist Filtering: Keep only approved/allowed elements from a list
  2. +
  3. Set Intersection: Find common elements between two lists
  4. +
  5. Dependency Validation: Ensure only permitted dependencies are used
  6. +
  7. Package Filtering: Keep only packages that meet certain criteria
  8. +
  9. Configuration Merging: Identify common configuration items
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/reverse.html b/org.bndtools.help/docs/macros/reverse.html new file mode 100644 index 0000000000..8cc250b9d7 --- /dev/null +++ b/org.bndtools.help/docs/macros/reverse.html @@ -0,0 +1,67 @@ + + + + +reverse (';' LIST )* + + + +

reverse (';' LIST )*

+

Summary

+

The reverse macro reverses the order of elements from one or more combined lists. The last element becomes first, and the first becomes last.

+

Syntax

+
${reverse;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Reverse a simple list:

+
${reverse;1,2,3,4,5}
+# Returns: "5,4,3,2,1"
+
+ +

Reverse text items:

+
${reverse;apple,banana,cherry}
+# Returns: "cherry,banana,apple"
+
+ +

Reverse multiple lists:

+
${reverse;red,green;blue,yellow}
+# Returns: "yellow,blue,green,red"
+
+ +

Reverse file list:

+
${reverse;${lsr;src;*.java}}
+# Returns files in reverse order
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/select.html b/org.bndtools.help/docs/macros/select.html new file mode 100644 index 0000000000..031fb88e3b --- /dev/null +++ b/org.bndtools.help/docs/macros/select.html @@ -0,0 +1,70 @@ + + + + +select ';' LIST ';' REGEX + + + +

select ';' LIST ';' REGEX

+

Summary

+

Filter a list to include only elements that match a regular expression. This macro is an alias for the filter macro.

+

Syntax

+
${select;<list>;<regex>}
+
+ +

Parameters

+ +

Behavior

+

Returns a new list containing only the elements from the input list that match the specified regular expression pattern.

+

This macro is functionally identical to filter.

+

Examples

+
# Select items starting with "com."
+packages = com.example.api, org.sample.impl, com.example.util
+${select;${packages};com\..*}
+# Returns: com.example.api,com.example.util
+
+# Select files with specific extension
+files = foo.jar, bar.txt, baz.jar
+${select;${files};.*\.jar}
+# Returns: foo.jar,baz.jar
+
+# Select numbered items
+items = item1, item2, other, item3
+${select;${items};item\d+}
+# Returns: item1,item2,item3
+
+# Select packages matching pattern
+-conditionalpackage: ${select;${packages};com\.company\.internal\..*}
+
+ +

Use Cases

+
    +
  1. Package Filtering: Select packages matching a naming pattern
  2. +
  3. File Selection: Filter file lists by extension or pattern
  4. +
  5. Dependency Filtering: Select specific dependencies from a larger list
  6. +
  7. Pattern Matching: Include only items matching a specific format
  8. +
+

Notes

+ + + +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/separator.html b/org.bndtools.help/docs/macros/separator.html new file mode 100644 index 0000000000..f4b22a28bf --- /dev/null +++ b/org.bndtools.help/docs/macros/separator.html @@ -0,0 +1,61 @@ + + + + +separator + + + +

separator

+

Summary

+

The separator macro returns the operating system's file separator character used in file paths.

+

Syntax

+
${separator}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get the file separator:

+
${separator}
+# Returns: "/" on Unix, "\" on Windows
+
+ +

Build paths manually:

+
path=${basedir}${separator}src${separator}main${separator}java
+
+ +

Use in conditionals:

+
${if;${equals;${separator};/};unix;windows}
+
+ +

Replace separators:

+
${replacestring;${path};${separator};/}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/sha1.html b/org.bndtools.help/docs/macros/sha1.html new file mode 100644 index 0000000000..3c4ba90b57 --- /dev/null +++ b/org.bndtools.help/docs/macros/sha1.html @@ -0,0 +1,69 @@ + + + + +sha1 ';' RESOURCE + + + +

sha1 ';' RESOURCE

+

Summary

+

The sha1 macro calculates the SHA-1 hash of a resource that exists within the current bundle JAR. The result can be returned as either Base64 (default) or hexadecimal encoding.

+

Syntax

+
${sha1;<resource-path>[;<encoding>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get SHA-1 of a resource (Base64):

+
${sha1;META-INF/services/com.example.Service}
+# Returns Base64-encoded SHA-1
+
+ +

Get SHA-1 in hexadecimal format:

+
${sha1;config/application.properties;hex}
+# Returns: "356a192b7913b04c54574d18c28d46e6395428ab" (example)
+
+ +

Hash manifest file:

+
manifest.sha1=${sha1;META-INF/MANIFEST.MF;hex}
+
+ +

Verify resource integrity:

+
Bundle-ResourceSHA1: ${sha1;important-config.xml}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/size.html b/org.bndtools.help/docs/macros/size.html new file mode 100644 index 0000000000..1478054e11 --- /dev/null +++ b/org.bndtools.help/docs/macros/size.html @@ -0,0 +1,65 @@ + + + + +size ( ';' LIST )* + + + +

size ( ';' LIST )*

+

Summary

+

The size macro counts and returns the total number of elements across one or more comma-separated lists.

+

Syntax

+
${size;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Count elements in a list:

+
${size;a,b,c,d}
+# Returns: 4
+
+ +

Count multiple lists:

+
${size;red,green;blue,yellow}
+# Returns: 4
+
+ +

Count packages:

+
package.count=${size;${packages}}
+
+ +

Conditional on list size:

+
${if;${size;${exports}};has-exports;no-exports}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/sjoin.html b/org.bndtools.help/docs/macros/sjoin.html new file mode 100644 index 0000000000..900d1a28e7 --- /dev/null +++ b/org.bndtools.help/docs/macros/sjoin.html @@ -0,0 +1,74 @@ + + + + +sjoin ';' SEPARATOR ( ';' LIST )+ + + + +

sjoin ';' SEPARATOR ( ';' LIST )+

+

Summary

+

The sjoin macro combines one or more lists into a single string using a custom separator. Unlike ${join} which always uses commas, this allows you to specify any separator.

+

Syntax

+
${sjoin;<separator>;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Join with space:

+
${sjoin; ;apple,banana,cherry}
+# Returns: "apple banana cherry"
+
+ +

Join with custom separator:

+
${sjoin; | ;red,green,blue}
+# Returns: "red | green | blue"
+
+ +

Join with newline:

+
${sjoin;\n;line1,line2,line3}
+# Returns multi-line text
+
+ +

Join multiple lists with colon:

+
${sjoin;:;${exports};${imports}}
+# Returns packages separated by colons
+
+ +

Create formatted list:

+
${sjoin;, and ;first,second,third}
+# Returns: "first, and second, and third"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/sort.html b/org.bndtools.help/docs/macros/sort.html new file mode 100644 index 0000000000..9537361f67 --- /dev/null +++ b/org.bndtools.help/docs/macros/sort.html @@ -0,0 +1,66 @@ + + + + +sort (';' LIST )+ + + + +

sort (';' LIST )+

+

Summary

+

The sort macro combines one or more lists and sorts their contents alphabetically (lexicographically). The sorting is case-sensitive with uppercase letters before lowercase.

+

Syntax

+
${sort;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Sort a simple list:

+
${sort;cherry,apple,banana}
+# Returns: "apple,banana,cherry"
+
+ +

Sort with mixed case:

+
${sort;Zebra,apple,Ant,banana}
+# Returns: "Ant,Zebra,apple,banana"
+
+ +

Sort multiple lists:

+
${sort;red,green;blue,yellow}
+# Returns: "blue,green,red,yellow"
+
+ +

Sort and filter:

+
${sort;${filter;${packages};com\.example\..*}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/split.html b/org.bndtools.help/docs/macros/split.html new file mode 100644 index 0000000000..21040460bf --- /dev/null +++ b/org.bndtools.help/docs/macros/split.html @@ -0,0 +1,72 @@ + + + + +split ';' REGEX (';' STRING )* + + + +

split ';' REGEX (';' STRING )*

+

Summary

+

The split macro splits one or more strings into a list using a regular expression as the delimiter. Empty segments are filtered out.

+

Syntax

+
${split;<regex>[;<string>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Split on comma:

+
${split;,;red,green,blue}
+# Returns: "red,green,blue"
+
+ +

Split on whitespace:

+
${split;\s+;one two  three   four}
+# Returns: "one,two,three,four"
+
+ +

Split on pipe:

+
${split;\|;apple|banana|cherry}
+# Returns: "apple,banana,cherry"
+
+ +

Split multiple strings:

+
${split;:;path1:path2;path3:path4}
+# Returns: "path1,path2,path3,path4"
+
+ +

Split path on separator:

+
${split;${pathseparator};${some.path}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/startswith.html b/org.bndtools.help/docs/macros/startswith.html new file mode 100644 index 0000000000..e590f8a086 --- /dev/null +++ b/org.bndtools.help/docs/macros/startswith.html @@ -0,0 +1,66 @@ + + + + +startswith ';' STRING ';' PREFIX + + + +

startswith ';' STRING ';' PREFIX

+

Summary

+

The startswith macro checks if a given string starts with a specified prefix. Returns the string if it matches, empty string otherwise.

+

Syntax

+
${startswith;<string>;<prefix>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Check string prefix:

+
${startswith;com.example.api;com.example}
+# Returns: "com.example.api"
+
+ +

Check with non-matching prefix:

+
${startswith;org.other.package;com.example}
+# Returns: ""
+
+ +

Use in conditional:

+
${if;${startswith;${project};test.};test-project;regular-project}
+
+ +

Filter list by prefix:

+
${filter;${packages};${startswith;.*;com\.example}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/stem.html b/org.bndtools.help/docs/macros/stem.html new file mode 100644 index 0000000000..9824c52933 --- /dev/null +++ b/org.bndtools.help/docs/macros/stem.html @@ -0,0 +1,73 @@ + + + + +stem ';' STRING + + + +

stem ';' STRING

+

Summary

+

The stem macro returns the portion of a string up to (but not including) the first dot character. If no dot is found, returns the entire string.

+

Syntax

+
${stem;<string>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Extract file basename:

+
${stem;example.txt}
+# Returns: "example"
+
+ +

Get package prefix:

+
${stem;com.example.api}
+# Returns: "com"
+
+ +

Extract version major:

+
${stem;1.2.3}
+# Returns: "1"
+
+ +

No dot present:

+
${stem;filename}
+# Returns: "filename"
+
+ +

Multiple dots:

+
${stem;archive.tar.gz}
+# Returns: "archive" (only first dot)
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/sublist.html b/org.bndtools.help/docs/macros/sublist.html new file mode 100644 index 0000000000..dd7f1d8516 --- /dev/null +++ b/org.bndtools.help/docs/macros/sublist.html @@ -0,0 +1,77 @@ + + + + +sublist ';' START ';' END (';' LIST )* + + + +

sublist ';' START ';' END (';' LIST )*

+

Summary

+

The sublist macro extracts elements from a list between start and end positions. It supports negative indices to count from the end of the list.

+

Syntax

+
${sublist;<start>;<end>;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get first 3 elements:

+
${sublist;0;3;apple,banana,cherry,date,elderberry}
+# Returns: "apple,banana,cherry"
+
+ +

Get last 2 elements:

+
${sublist;-2;-0;apple,banana,cherry}
+# Returns: "banana,cherry"
+
+ +

Skip first element:

+
${sublist;1;-0;red,green,blue}
+# Returns: "green,blue"
+
+ +

Get middle elements:

+
${sublist;2;5;a,b,c,d,e,f,g}
+# Returns: "c,d,e"
+
+ +

Extract from multiple lists:

+
${sublist;0;3;one,two;three,four,five}
+# Returns: "one,two,three"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/subst.html b/org.bndtools.help/docs/macros/subst.html new file mode 100644 index 0000000000..dd8314f232 --- /dev/null +++ b/org.bndtools.help/docs/macros/subst.html @@ -0,0 +1,96 @@ + + + + +subst ';' STRING ';' REGEX (';' STRING (';' NUMBER )? )? + + + +

subst ';' STRING ';' REGEX (';' STRING (';' NUMBER )? )?

+

Summary

+

Perform regex-based substring substitution on a target string, with optional replacement limit.

+

Syntax

+
${subst;<target>;<regex>[;<replacement>[;<count>]]}
+
+ +

Parameters

+ +

Behavior

+

The macro: +1. Finds all substrings in target that match regex +2. Replaces them with replacement (or empty string if not specified) +3. Limits replacements to count if specified (otherwise replaces all) +4. Returns the modified string

+

This is similar to Java's String.replaceAll() but with optional replacement count.

+

Examples

+
# Remove file extension
+${subst;foo.bar;\.bar}
+# Returns: foo
+
+# Replace dots with dashes
+${subst;com.example.package;\.;-}
+# Returns: com-example-package
+
+# Replace with specified text
+${subst;Hello World;World;Universe}
+# Returns: Hello Universe
+
+# Limit replacements
+${subst;a,b,c,d;,;-;2}
+# Returns: a-b-c,d (only first 2 replacements)
+
+# Remove all digits
+${subst;version1.2.3;\d}
+# Returns: version.. (empty replacement)
+
+# Replace spaces with underscores
+${subst;My Project Name; ;_}
+# Returns: My_Project_Name
+
+# Complex regex - remove version info
+${subst;bundle-1.0.0.jar;-[\d.]+\.jar;.jar}
+# Returns: bundle.jar
+
+# Multiple occurrences
+${subst;test-test-test;test;prod}
+# Returns: prod-prod-prod
+
+# With capture groups
+${subst;com.example.api;com\.(.*)\.api;org.$1.impl}
+# Returns: org.example.impl
+
+ +

Use Cases

+
    +
  1. Path Manipulation: Modify file paths or package names
  2. +
  3. String Cleaning: Remove unwanted patterns from strings
  4. +
  5. Format Conversion: Transform string formats
  6. +
  7. Version Stripping: Remove version numbers from names
  8. +
  9. Pattern Replacement: Replace specific patterns with alternatives
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/substring.html b/org.bndtools.help/docs/macros/substring.html new file mode 100644 index 0000000000..0993984625 --- /dev/null +++ b/org.bndtools.help/docs/macros/substring.html @@ -0,0 +1,76 @@ + + + + +substring ';' STRING ';' START ( ';' END )? + + + +

substring ';' STRING ';' START ( ';' END )?

+

Summary

+

The substring macro extracts a portion of a string between start and end positions. It supports negative indices to count from the end of the string.

+

Syntax

+
${substring;<string>;<start>[;<end>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get first 5 characters:

+
${substring;hello world;0;5}
+# Returns: "hello"
+
+ +

Get last 5 characters:

+
${substring;hello world;-5}
+# Returns: "world"
+
+ +

Remove first 2 characters:

+
${substring;hello;2}
+# Returns: "llo"
+
+ +

Extract middle portion:

+
${substring;hello world;6;11}
+# Returns: "world"
+
+ +

Use negative indices:

+
${substring;hello world;-5;-1}
+# Returns: "worl"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/sum.html b/org.bndtools.help/docs/macros/sum.html new file mode 100644 index 0000000000..36ebe9dbd0 --- /dev/null +++ b/org.bndtools.help/docs/macros/sum.html @@ -0,0 +1,65 @@ + + + + +sum (';' LIST )* + + + +

sum (';' LIST )*

+

Summary

+

The sum macro calculates the sum of all numeric values provided in one or more lists. Each element is parsed as a double-precision floating-point number.

+

Syntax

+
${sum;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Sum a simple list:

+
${sum;1,2,3,4,5}
+# Returns: "15"
+
+ +

Sum multiple lists:

+
${sum;10,20;30,40}
+# Returns: "100"
+
+ +

Sum decimal values:

+
${sum;1.5,2.5,3.5}
+# Returns: "7.5"
+
+ +

Calculate total from properties:

+
total=${sum;${value1};${value2};${value3}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/system.html b/org.bndtools.help/docs/macros/system.html new file mode 100644 index 0000000000..b0f049ffe6 --- /dev/null +++ b/org.bndtools.help/docs/macros/system.html @@ -0,0 +1,76 @@ + + + + +system ';' STRING ( ';' STRING )? + + + +

system ';' STRING ( ';' STRING )?

+

Summary

+

The system macro executes an operating system command and returns its standard output. The command runs in the project's base directory. The build fails if the command returns a non-zero exit code.

+

Syntax

+
${system;<command>[;<input>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Get Git commit hash:

+
Git-Commit: ${system;git rev-parse HEAD}
+
+ +

Get current date:

+
Build-Date: ${system;date}
+
+ +

Execute command with input:

+
${system;wc -l;line1\nline2\nline3}
+
+ +

Get Maven version:

+
mvn.version=${system;mvn --version}
+
+ +

List files:

+
files=${system;ls -la}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/system_allow_fail.html b/org.bndtools.help/docs/macros/system_allow_fail.html new file mode 100644 index 0000000000..c5a4bb4870 --- /dev/null +++ b/org.bndtools.help/docs/macros/system_allow_fail.html @@ -0,0 +1,72 @@ + + + + +system_allow_fail ';' STRING ( ';' STRING )? + + + +

system_allow_fail ';' STRING ( ';' STRING )?

+

Summary

+

The system-allow-fail macro executes an operating system command and returns its output, but unlike ${system}, it does not fail the build if the command returns a non-zero exit code. Failed commands generate a warning instead.

+

Syntax

+
${system-allow-fail;<command>[;<input>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Try to get Git info (may not be in repo):

+
Git-Branch: ${system-allow-fail;git branch --show-current}
+
+ +

Optional version check:

+
tool.version=${system-allow-fail;tool --version}
+
+ +

Check for optional tool:

+
${if;${system-allow-fail;which docker};docker-available;docker-not-found}
+
+ +

Get info with fallback:

+
host=${def;${system-allow-fail;hostname};unknown-host}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/template.html b/org.bndtools.help/docs/macros/template.html new file mode 100644 index 0000000000..7bc0d4c1d4 --- /dev/null +++ b/org.bndtools.help/docs/macros/template.html @@ -0,0 +1,52 @@ + + + + +template ';' NAME [ ';' template ]+ + + + +

template ';' NAME [ ';' template ]+

+

The template macro is intended to make it very simple to generate new information based on a Parameters. Parameters +are the Bnd workhorse to store information. The macro takes the following arguments:

+
macro name  The name of the macro (not the value)
+template+   the templates (these are  joined with the ';' as separator)
+
+ +

The template is expanded for each entry of the Parameters. They key can be referred by ${@} and the attributes can be +referred by ${@<name>}, where the name is the name of the attribute. All entries are then joined with a comma (,) as +separator.

+

For example, the following example shows how to extract and attribute as a list:

+
bnd shell
+> parameters = key;attr=1, key;attr="2"
+> ${template;parameters;${@attr}}
+1,2
+
+ +

The template macro takes the NAME of the macro that contains the value. I.e. it does not take the expanded value as +argument. The reason is that the referred macro gets merged and decorated. Merge takes all properties that start with the given name.

+
> parameters = key;attr=1, key;attr="2"
+> parameters.extra = KEY;attr=3, KEY;attr="4"
+> ${template;parameters;${@attr}}
+1,2,3,4
+
+ +

Decorate means that the property with the same name but with a + at the end will be matched with the value. In this property the +key is a glob. It is matched against the key from the original merged properties. Any matching properties get the attributes +from the decorator.

+
> parameters = a;attr=1, b;attr="2"
+> parameters.extra = c;attr=3, d;attr="4"
+> parameters+ = (c|d);attr=X
+> ${template;parameters;${@attr}}
+1,2,X,X
+
+ +

The macro accepts any number of arguments after the macro name. These values are joined with a semi-colon as separator. +The reason is that then the ; in the templates do not have to be escaped:

+
bnd shell
+> parameters = a;attr=1, b;attr="2"
+> ${template;parameters;${@};key=${@};${@}=${@attr}}
+a;a=1,b;b=2
+
+ + diff --git a/org.bndtools.help/docs/macros/thisfile.html b/org.bndtools.help/docs/macros/thisfile.html new file mode 100644 index 0000000000..97df4ffa44 --- /dev/null +++ b/org.bndtools.help/docs/macros/thisfile.html @@ -0,0 +1,63 @@ + + + + +thisfile + + + +

thisfile

+

Summary

+

The thisfile macro returns the absolute path to the properties file being processed. This provides the full path to the current .bnd, .bndrun, or other bnd configuration file.

+

Syntax

+
${thisfile}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get current file path:

+
Current-Config: ${thisfile}
+# Returns: "/path/to/project/bnd.bnd"
+
+ +

Use in logging:

+
Processing: ${thisfile}
+
+ +

Reference in documentation:

+
# Configuration defined in: ${thisfile}
+
+ +

Conditional based on file:

+
${if;${endswith;${thisfile};test.bnd};test-mode;normal-mode}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/toclaspath.html b/org.bndtools.help/docs/macros/toclaspath.html new file mode 100644 index 0000000000..11eb49edd4 --- /dev/null +++ b/org.bndtools.help/docs/macros/toclaspath.html @@ -0,0 +1,67 @@ + + + + +toclasspath ';' LIST ( ';' BOOLEAN )? + + + +

toclasspath ';' LIST ( ';' BOOLEAN )?

+

Summary

+

The toclasspath macro converts fully qualified class names to file paths by replacing dots with path separators and optionally adding .class extension.

+

Syntax

+
${toclasspath;<class-names>[;<add-extension>]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert class names with extension:

+
${toclasspath;com.example.Main,com.example.Util}
+# Returns: "com/example/Main.class,com/example/Util.class"
+
+ +

Convert without extension:

+
${toclasspath;org.test.TestCase;false}
+# Returns: "org/test/TestCase"
+
+ +

Create paths for lookup:

+
paths=${toclasspath;${classes};true}
+
+ +

Package paths without extension:

+
${toclasspath;com.example.api;false}
+# Returns: "com/example/api"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/toclassname.html b/org.bndtools.help/docs/macros/toclassname.html new file mode 100644 index 0000000000..d1228026b0 --- /dev/null +++ b/org.bndtools.help/docs/macros/toclassname.html @@ -0,0 +1,68 @@ + + + + +toclassname ';' FILES + + + +

toclassname ';' FILES

+

Summary

+

The toclassname macro converts a list of file paths (.class or .java files) to fully qualified class names by removing the extension and converting path separators to dots.

+

Syntax

+
${toclassname;<file-paths>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert class file paths:

+
${toclassname;com/example/Main.class,com/example/Util.class}
+# Returns: "com.example.Main,com.example.Util"
+
+ +

Convert Java source paths:

+
${toclassname;org/test/TestCase.java}
+# Returns: "org.test.TestCase"
+
+ +

Use with file lists:

+
classes=${toclassname;${lsr;bin;*.class}}
+
+ +

Mixed extensions:

+
${toclassname;com/Foo.java,com/Bar.class}
+# Returns: "com.Foo,com.Bar"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/tolower.html b/org.bndtools.help/docs/macros/tolower.html new file mode 100644 index 0000000000..caa9921945 --- /dev/null +++ b/org.bndtools.help/docs/macros/tolower.html @@ -0,0 +1,64 @@ + + + + +tolower STRING + + + +

tolower STRING

+

Summary

+

The tolower macro converts a string to lowercase using the default locale.

+

Syntax

+
${tolower;<string>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert simple string:

+
${tolower;HELLO WORLD}
+# Returns: "hello world"
+
+ +

Convert mixed case:

+
${tolower;MyClassName}
+# Returns: "myclassname"
+
+ +

Normalize for comparison:

+
${if;${equals;${tolower;${input}};${tolower;${expected}}};match;no-match}
+
+ +

Convert package names:

+
normalized=${tolower;Com.Example.API}
+# Returns: "com.example.api"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/toupper.html b/org.bndtools.help/docs/macros/toupper.html new file mode 100644 index 0000000000..ee06dd2160 --- /dev/null +++ b/org.bndtools.help/docs/macros/toupper.html @@ -0,0 +1,63 @@ + + + + +toupper STRING + + + +

toupper STRING

+

Summary

+

The toupper macro converts a string to uppercase using the default locale.

+

Syntax

+
${toupper;<string>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Convert simple string:

+
${toupper;hello world}
+# Returns: "HELLO WORLD"
+
+ +

Convert mixed case:

+
${toupper;MyClassName}
+# Returns: "MYCLASSNAME"
+
+ +

Create constants:

+
constant.name=${toupper;${property.name}}
+
+ +

Format identifiers:

+
Bundle-Id: ${toupper;${bsn}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/trim.html b/org.bndtools.help/docs/macros/trim.html new file mode 100644 index 0000000000..45f031ad5a --- /dev/null +++ b/org.bndtools.help/docs/macros/trim.html @@ -0,0 +1,68 @@ + + + + +trim ';' STRING + + + +

trim ';' STRING

+

Summary

+

The trim macro removes leading and trailing whitespace from a string. It uses Java's String.trim() method, which removes spaces, tabs, newlines, and other whitespace characters.

+

Syntax

+
${trim;<string>}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Remove extra spaces:

+
${trim;  hello world  }
+# Returns: "hello world"
+
+ +

Clean up property value:

+
cleaned.value=${trim;${some.property}}
+
+ +

Trim after concatenation:

+
${trim;${first} ${second} }
+
+ +

Process multiline value:

+
${trim;
+    some value
+}
+# Returns: "some value"
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/tstamp.html b/org.bndtools.help/docs/macros/tstamp.html new file mode 100644 index 0000000000..10e5538cec --- /dev/null +++ b/org.bndtools.help/docs/macros/tstamp.html @@ -0,0 +1,82 @@ + + + + +tstamp ( ';' DATEFORMAT ( ';' TIMEZONE ( ';' LONG )? )? )? + + + +

tstamp ( ';' DATEFORMAT ( ';' TIMEZONE ( ';' LONG )? )? )?

+

Summary

+

The tstamp macro creates a formatted timestamp string using a custom date format pattern, timezone, and optional timestamp value.

+

Syntax

+
${tstamp[;<format>[;<timezone>[;<millis>]]]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Default format (UTC):

+
${tstamp}
+# Returns: "202411201030" (example)
+
+ +

Custom format:

+
${tstamp;yyyy-MM-dd HH:mm:ss}
+# Returns: "2024-11-20 10:30:45"
+
+ +

With timezone:

+
${tstamp;yyyy-MM-dd HH:mm;America/New_York}
+# Returns: "2024-11-20 05:30"
+
+ +

ISO 8601 format:

+
${tstamp;yyyy-MM-dd'T'HH:mm:ss'Z'}
+# Returns: "2024-11-20T10:30:45Z"
+
+ +

Specific timestamp:

+
${tstamp;yyyy-MM-dd;;1700000000000}
+# Formats the provided timestamp
+
+ +

Build timestamp in manifest:

+
Build-Timestamp: ${tstamp;yyyy-MM-dd HH:mm:ss z;UTC}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/unescape.html b/org.bndtools.help/docs/macros/unescape.html new file mode 100644 index 0000000000..de1e4d9d6c --- /dev/null +++ b/org.bndtools.help/docs/macros/unescape.html @@ -0,0 +1,76 @@ + + + + +unescape ( ';' STRING )* + + + +

unescape ( ';' STRING )*

+

Summary

+

The unescape macro converts escape sequences in strings to their corresponding control characters. It concatenates all input arguments and processes escape sequences.

+

Syntax

+
${unescape;<string>[;<string>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Unescape newline:

+
${unescape;line1\nline2}
+# Returns: "line1
+# line2"
+
+ +

Unescape tab:

+
${unescape;col1\tcol2\tcol3}
+# Returns: "col1    col2    col3"
+
+ +

Multiple strings:

+
${unescape;first\n;second\n;third}
+# Returns: "first
+# second
+# third"
+
+ +

Mixed escapes:

+
${unescape;Name:\tJohn\nAge:\t30}
+
+ +

Use Cases

+ +

Notes

+ +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/uniq.html b/org.bndtools.help/docs/macros/uniq.html new file mode 100644 index 0000000000..dd63e29f98 --- /dev/null +++ b/org.bndtools.help/docs/macros/uniq.html @@ -0,0 +1,68 @@ + + + + +uniq (';' LIST )* + + + +

uniq (';' LIST )*

+

Summary

+

The uniq macro combines one or more lists and removes all duplicate elements, preserving insertion order (first occurrence is kept).

+

Syntax

+
${uniq;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Remove duplicates from single list:

+
${uniq;1,2,3,1,2,4}
+# Returns: "1,2,3,4"
+
+ +

Remove duplicates from multiple lists:

+
${uniq;red,green,blue;red,yellow}
+# Returns: "red,green,blue,yellow"
+
+ +

Clean package list:

+
${uniq;${exports};${imports}}
+# Returns unique packages
+
+ +

Deduplicate configuration:

+
unique.values=${uniq;${list1};${list2};${list3}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/uri.html b/org.bndtools.help/docs/macros/uri.html new file mode 100644 index 0000000000..4b4f67e985 --- /dev/null +++ b/org.bndtools.help/docs/macros/uri.html @@ -0,0 +1,92 @@ + + + + +uri ';' URI (';' URI)? + + + +

uri ';' URI (';' URI)?

+

Summary

+

Resolve a URI against a base URI, handling relative URIs and file scheme URIs appropriately.

+

Syntax

+
${uri;<uri>[;<base-uri>]}
+
+ +

Parameters

+ +

Behavior

+

The macro resolves URIs based on these rules: +1. If the URI is absolute (has a scheme like http:, https:) and not a file: scheme, returns it unchanged +2. If the URI is relative or uses the file: scheme: + - Resolves it against the specified base URI (if provided) + - Or resolves it against the processor's base URI (project or workspace root) +3. Returns the resolved URI

+

The base URI depends on context when not explicitly provided: +- In a project's bnd.bnd: Project directory URI +- In a workspace's cnf/build.bnd: Workspace directory URI

+

Examples

+
# Current directory URI
+${uri;.}
+# In project: file:///workspace/my.project/
+# In workspace: file:///workspace/
+
+# Resolve relative path
+${uri;src/main/resources}
+# Returns: file:///project/base/src/main/resources
+
+# Resolve against custom base
+${uri;config/settings.xml;file:///opt/app/}
+# Returns: file:///opt/app/config/settings.xml
+
+# Absolute HTTP URI (returned unchanged)
+${uri;https://example.com/resource}
+# Returns: https://example.com/resource
+
+# File URI (resolved against base)
+${uri;file:./local/path}
+# Returns: file:///project/base/local/path
+
+# Parent directory reference
+${uri;../config}
+# Resolved relative to base
+
+# Use in configuration
+Bundle-DocURL: ${uri;docs/index.html;${Bundle-Site}}
+
+# Reference workspace files
+config-location = ${uri;cnf/config.properties}
+
+ +

Use Cases

+
    +
  1. URI Resolution: Convert relative URIs to absolute
  2. +
  3. Configuration: Resolve configuration file locations
  4. +
  5. Documentation: Create proper URIs for documentation references
  6. +
  7. Resource Linking: Link to external or internal resources
  8. +
  9. Cross-Platform: Generate platform-independent URIs
  10. +
+

Notes

+ + + +
+

TODO Needs review - AI Generated content

+
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/user.html b/org.bndtools.help/docs/macros/user.html new file mode 100644 index 0000000000..5289227d96 --- /dev/null +++ b/org.bndtools.help/docs/macros/user.html @@ -0,0 +1,12 @@ + + + + +user ';' KEY ( ';' DEFAULT )? + + + +

user ';' KEY ( ';' DEFAULT )?

+

The user macro is an alias to the global macro.

+ + diff --git a/org.bndtools.help/docs/macros/vcompare.html b/org.bndtools.help/docs/macros/vcompare.html new file mode 100644 index 0000000000..630eb7185b --- /dev/null +++ b/org.bndtools.help/docs/macros/vcompare.html @@ -0,0 +1,97 @@ + + + + +vcompare VERSION VERSION + + + +

vcompare VERSION VERSION

+

Summary

+

Compare two OSGi version strings using proper version semantics, returning -1, 0, or 1.

+

Syntax

+
${vcompare;<version1>;<version2>}
+
+ +

Parameters

+ +

Behavior

+

Compares two OSGi version strings using semantic version comparison and returns: +- 0 - The versions are equal +- 1 - The first version is greater than the second (newer) +- -1 - The first version is less than the second (older)

+

OSGi versions follow the format: major.minor.micro.qualifier +- Numeric parts (major, minor, micro) are compared numerically +- Qualifier is compared lexicographically

+

Examples

+
# Equal versions
+${vcompare;1.0.0;1.0.0}
+# Returns: 0
+
+# First version greater
+${vcompare;2.0.0;1.5.0}
+# Returns: 1
+
+# First version less
+${vcompare;1.0.0;2.0.0}
+# Returns: -1
+
+# Micro version comparison
+${vcompare;1.2.3;1.2.2}
+# Returns: 1
+
+# With qualifiers
+${vcompare;1.0.0.SNAPSHOT;1.0.0.RELEASE}
+# Returns: 1 (SNAPSHOT > RELEASE lexicographically)
+
+# Different lengths
+${vcompare;1.0;1.0.0}
+# Returns: 0 (1.0 equals 1.0.0.0)
+
+# Use in conditional logic
+-include ${if;${vcompare;${bndversion};7.0.0};modern.bnd;legacy.bnd}
+
+# Check minimum version requirement
+-include ${if;${vcompare;${Bundle-Version};2.0.0};compatible.bnd;incompatible.bnd}
+
+# Version range check
+is-current = ${if;${vcompare;${Bundle-Version};3.0.0};true;false}
+
+# Compare with project version
+${vcompare;${version;===;${Bundle-Version}};${minimum-version}}
+
+ +

Use Cases

+
    +
  1. Version Requirements: Check if a version meets minimum requirements
  2. +
  3. Conditional Configuration: Apply different settings based on version
  4. +
  5. Build Compatibility: Ensure compatibility with specific versions
  6. +
  7. Version Validation: Verify version constraints are met
  8. +
  9. Feature Gating: Enable features only in certain version ranges
  10. +
+

Notes

+ + + +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/version.html b/org.bndtools.help/docs/macros/version.html new file mode 100644 index 0000000000..0279bd2a79 --- /dev/null +++ b/org.bndtools.help/docs/macros/version.html @@ -0,0 +1,12 @@ + + + + +version MASK VERSION? + + + +

version MASK VERSION?

+

The version macro is an alias to the versionmask macro for backward compatibility reasons.

+ + diff --git a/org.bndtools.help/docs/macros/version_cleanup.html b/org.bndtools.help/docs/macros/version_cleanup.html new file mode 100644 index 0000000000..29ad0b467a --- /dev/null +++ b/org.bndtools.help/docs/macros/version_cleanup.html @@ -0,0 +1,22 @@ + + + + +version_cleanup ';' VERSION + + + +

version_cleanup ';' VERSION

+

The version_cleanup macro takes a version-ish string and cleans it up, producing the OSGi Version syntax.

+

For example, a Maven version can be turned into the OSGi Version syntax:

+
${version_cleanup;1.2.3-SNAPSHOT} -> 1.2.3.SNAPSHOT
+
+ +
    +
  1. If the argument passed in is null, the version returned is 0.
  2. +
  3. If the argument passed is a valid OSGi version range the range is returned unaltered.
  4. +
  5. If the argument is a version range matching the regular expression (\\(|\\[)\\s*([-.\\w]+)\\s*,\\s*([-.\\w]+)\\s*(\\]|\\)) (with java.util.regex.Pattern.DOTALL enabled) a sufficiently cleaned up OSGi Version range is returned.
  6. +
  7. If the argument is a version string matching the regular expression (\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^\\p{Alnum}](.*))? (with java.util.regex.Pattern.DOTALL enabled) a sufficiently cleaned up OSGi Version string is returned.
  8. +
+ + diff --git a/org.bndtools.help/docs/macros/versionmask.html b/org.bndtools.help/docs/macros/versionmask.html new file mode 100644 index 0000000000..e0d7dafee0 --- /dev/null +++ b/org.bndtools.help/docs/macros/versionmask.html @@ -0,0 +1,61 @@ + + + + +versionmask MASK VERSION? + + + +

versionmask MASK VERSION?

+

The versionmask macro takes a template (MASK) and a version. It then uses the template +to modify the version. This is useful to get rid of parts of the version. For example, +to get rid of the qualifier the following macro is useful:

+
${versionmask;===;1.2.3.awfulqualifier} -> 1.2.3
+
+ +

It is also possible to modify the template. For example, if the next minor version is +sought, then the following macro is useful:

+
${versionmask;=+;1.2.3.awfulqualifier} -> 1.3
+
+ +

The syntax for the versionmask macro is:

+
versionmask ::= mask
+mask        ::= m ( m ( m ( q )? )? )?
+m     ::= [0-9=+-~]
+q     ::= [0-9=~Ss]
+
+ +

The MASK can consists of 1 to 4 template characters. Each character maps to a version +part.The first character maps to the major, the second to the minor, the third to the +micro, and the last to the qualifier. These characters can be:

+ +

In many places in bnd, the ${@} macro is set as an implicit variable. For example, if +the bnd analyzer calculates the import range it sets this to the version of the package +that is imported. Therefore, if the version is not specified in this macro as the second +argument then the ${@} macro is expanded and used as the value for the version. A use +of this is in the Import Package statement. There you can use the ${versionmask} macro +to clean up the imported version. (Though the range macro is better suited for +this.)

+
Import-Package com.exmaple.foo;version=${versionmask;==}
+
+ +

This macro is also available under the name version. The name was changed because this +often collided with macros that were defined by the user.

+ + diff --git a/org.bndtools.help/docs/macros/vmax.html b/org.bndtools.help/docs/macros/vmax.html new file mode 100644 index 0000000000..d22d5f5668 --- /dev/null +++ b/org.bndtools.help/docs/macros/vmax.html @@ -0,0 +1,61 @@ + + + + +vmax (';' LIST )* + + + +

vmax (';' LIST )*

+

Summary

+

The vmax macro compares version strings using OSGi semantic versioning rules and returns the maximum (highest) version.

+

Syntax

+
${vmax;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find maximum version:

+
${vmax;1.2.3,2.0.0,1.0.5}
+# Returns: "2.0.0"
+
+ +

Multiple lists:

+
${vmax;1.5.0,2.0.0;1.2.3,3.0.0}
+# Returns: "3.0.0"
+
+ +

Get latest version:

+
latest.version=${vmax;${available.versions}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/vmin.html b/org.bndtools.help/docs/macros/vmin.html new file mode 100644 index 0000000000..9693d334cd --- /dev/null +++ b/org.bndtools.help/docs/macros/vmin.html @@ -0,0 +1,61 @@ + + + + +vmin (';' LIST )* + + + +

vmin (';' LIST )*

+

Summary

+

The vmin macro compares version strings using OSGi semantic versioning rules and returns the minimum (lowest) version.

+

Syntax

+
${vmin;<list>[;<list>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Find minimum version:

+
${vmin;1.2.3,2.0.0,1.0.5}
+# Returns: "1.0.5"
+
+ +

Multiple lists:

+
${vmin;1.5.0,2.0.0;1.2.3,3.0.0}
+# Returns: "1.2.3"
+
+ +

Check compatibility:

+
min.required=${vmin;${bundle.versions}}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/warning.html b/org.bndtools.help/docs/macros/warning.html new file mode 100644 index 0000000000..92dcc92fc6 --- /dev/null +++ b/org.bndtools.help/docs/macros/warning.html @@ -0,0 +1,70 @@ + + + + +warning ( ';' STRING )* + + + +

warning ( ';' STRING )*

+

Summary

+

The warning macro generates one or more build warnings with custom messages. Each message argument is processed (macros are expanded) and then added to the build warning list. Unlike errors, warnings do not fail the build.

+

Syntax

+
${warning;<message>[;<message>...]}
+
+ +

Parameters

+ +

Behavior

+ +

Examples

+

Generate a simple warning:

+
${warning;This configuration is deprecated}
+
+ +

Generate warning with variable substitution:

+
${warning;Using default version: ${version}}
+
+ +

Conditional warning:

+
${if;${is;${someproperty}};${warning;Property someproperty is set and may cause issues}}
+
+ +

Multiple warning messages:

+
${warning;First warning;Second warning;Third warning}
+
+ +

Warning with computed values:

+
${warning;Bundle ${bsn} is using experimental features}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/macros/workspace.html b/org.bndtools.help/docs/macros/workspace.html new file mode 100644 index 0000000000..0928a4d8eb --- /dev/null +++ b/org.bndtools.help/docs/macros/workspace.html @@ -0,0 +1,55 @@ + + + + +workspace + + + +

workspace

+

Summary

+

The workspace macro returns the absolute file path to the current bnd workspace directory.

+

Syntax

+
${workspace}
+
+ +

Parameters

+

None - this macro takes no parameters.

+

Behavior

+ +

Examples

+

Get workspace path:

+
Workspace-Location: ${workspace}
+
+ +

Reference workspace files:

+
config.file=${workspace}/cnf/build.bnd
+
+ +

Relative to workspace:

+
${if;${startswith;${basedir};${workspace}};in-workspace;external}
+
+ +

Use Cases

+ +

Notes

+ +
+

See test cases in MacroTestsForDocsExamples.java

+ + diff --git a/org.bndtools.help/docs/manual/about.html b/org.bndtools.help/docs/manual/about.html new file mode 100644 index 0000000000..fe5a1abde7 --- /dev/null +++ b/org.bndtools.help/docs/manual/about.html @@ -0,0 +1,18 @@ + + + + +Introduction + + + +

Introduction

+

Bndtools is an Eclipse Plugin based on bnd with the goal to make programming for OSGi easier than in +any other environment. Correction, to make programming in Java easier than any other environment!

+

As a plugin Bndtools hooks into the IDE in numerous places. Clearly, Eclipse already provides a very comprehensive +Java programming environment and Bndtools leverages this to the hilt.

+

The following image provides an overview of the most important views in the Bndtools plugin. You can click on the +view and it should take you to the appropriate place.

+

+ + diff --git a/org.bndtools.help/docs/manual/bndeditor.html b/org.bndtools.help/docs/manual/bndeditor.html new file mode 100644 index 0000000000..8f9c5823b7 --- /dev/null +++ b/org.bndtools.help/docs/manual/bndeditor.html @@ -0,0 +1,32 @@ + + + + +Bnd Editor + + + +

Bnd Editor

+

The bnd editor provides a number of tabs with graphic editors. The following tabs are available:

+ +

Contents

+

+

Description

+

+

Build

+

+

Run

+

+

Tests

+

+

Source

+

+ + diff --git a/org.bndtools.help/docs/manual/index.html b/org.bndtools.help/docs/manual/index.html new file mode 100644 index 0000000000..426afbdfd2 --- /dev/null +++ b/org.bndtools.help/docs/manual/index.html @@ -0,0 +1,23 @@ + + + + +Bndtools UI Manual + + + +

Bndtools UI Manual

+

This manual describes the Bndtools Eclipse plugin user interface components.

+ +

Full documentation available at https://bndtools.org/manual/

+ + diff --git a/org.bndtools.help/docs/manual/jareditor.html b/org.bndtools.help/docs/manual/jareditor.html new file mode 100644 index 0000000000..3ac4ca3e2e --- /dev/null +++ b/org.bndtools.help/docs/manual/jareditor.html @@ -0,0 +1,32 @@ + + + + +JAR Viewer + + + +

JAR Viewer

+

Double clicking a JAR or ZIP file wil open the Bndtools JAR Editor. It will display the JAR file's content with the following tabs:

+ +

If the JAR file changes on the file system, it will be automatically updated.

+

Content

+

In the content tab you can double click entries, this will open a new editor on that file. You can also drag files from the list on the file system or the Eclipse lists that accepts files.

+

+

You can view the files as text or as binary. The JAR Editor guess what the preferred view is. In the text display, a special character set can be selected.

+

+

Print

+

+

Find

+

In the print page, if you use cmd/ctrl+f, this will open a "find..." text box in the header. Once the "find" text box is open, you can close it with the "close" button on right hand side.

+

Find feature

+

Once you type in some search text, it will highlight all of the matches in the whole page, and for the first occurrence it will set the selection on it as well as modify the highlight to signal its the "current" highlight.

+

Search highlights

+

You can advance to next and previous match using arrows and the match/totalCount is displayed. Also you can use the global "next" and "previous" shortcuts as well. cmd/ctrl+., shift+cmd/ctrl+. respectively.

+

Navigation arrows

+

If the next occurrence is out of the current viewport of the text area, it will scroll the text view to show the new highlight.

+ + diff --git a/org.bndtools.help/docs/manual/packageexplorer.html b/org.bndtools.help/docs/manual/packageexplorer.html new file mode 100644 index 0000000000..d4fa9a0e77 --- /dev/null +++ b/org.bndtools.help/docs/manual/packageexplorer.html @@ -0,0 +1,101 @@ + + + + +Bndtools Explorer + + + +

Bndtools Explorer

+

The Bndtools Package Explorer is an extension of the Eclipse Package Explorer. The explorer provides an overview of the projects and their contents. It is extended with a search bar for projects and some extra filters. You can make simple searches or use the bnd globbing. That is, you can use wildcards (example*bar) but also multiple searches in one, for example, foo|bar to find multiple projects.

+

Icons are used extensively to mark the projects in the explorer. They are either used as direct icons for an object (e.g. a bnd.bnd file) or are used to decorate existing icons. For example, if a package is exported or not. The following image shows all icons in their context.

+

Bndtools Explorer

+

Pseudo Targets

+

You can filter on the following additional targets:

+ +

pseudo targets

+

Note that you can combine the pseudo targets with the '|' operator, e.g. :e|lib.

+

All Green

+

The All Green field shows the aggregate status of the workspace. If there is any project with an error, it will be red. If there are no errors, but a project has warnings it will be orange. In all other cases it is green.

+

Refresh

+

The refresh button will refresh all projects from the workspace and will then reload the workspace. This will reinitialize all the repositories and tend to rebuild all projects.

+

Pinning

+

You can pin a project. A pinned project will always be visible.

+

Icons

+

Bndtools adds the following icons in the Package Explorer:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconDescription
bnd-projectContains all the project configuration. The project configuration inherits properties from cnf/build.bnd and any bnd files in cnf/ext/
*.bnd fileA general bnd file. This is either a bnd file in the cnf directory to configure the workspace or it can be a sub bundle when in a project. Bndtools contains a special editor for the bnd files. This type of file is generally used in an inheritance hierarchy.
*.bndrun fileDescribes a launch configuration. The required bundles can be indicated with initial requirements that the Bndtools resolver can turn into a list of bundles. An extensive editor is available to edit the launch configuration. A project can contain many bndrun files.
build.bndThis is the master configuration file of the workspace. When Bndtools starts, bnd first reads the bnd files in the cnf/ext/ directory, and then the cnf/build.bnd file. Any property or header set in this file is available to any project. There is only one such file in a workspace and it is also used as the marker file for a workspace.
Bnd Bundle PathBnd Bundle Path – This is an Eclipse Library container for Bndtools. The children of the container are specified in the project's bnd.bnd file in the -buildpath and -testpath instructions.
Dependency with sourceA Bnd Bundle Path dependency with source code attached. If the icon is darker then it is a test dependency.
DependencyA Bnd Bundle Path dependency without source code attached. If the icon is darker then it is a test dependency.
Test DependencyA Bnd Bundle Path dependency without source code attached that is only used for test code.
Component classA class that is a DS component. The general icon for a component is an eco friendly green LED.
Component packageA package that contains DS components
src folderThe source folder classes that are part of the bundle
test folderThe source folder for test code.
Private packageA private package in a bundle. This package is included but not exported.
Exported packageAn exported package of a bundle. If the package has a version it will also be displayed.
Excluded packageA package that is not included in any bundle. This is rare and not a good practice so it is generally a warning sign.
+

If you're looking for other icons, the Eclipse Help shows a further reference of all icons.

+ + diff --git a/org.bndtools.help/docs/manual/repositories-view.html b/org.bndtools.help/docs/manual/repositories-view.html new file mode 100644 index 0000000000..81e4279964 --- /dev/null +++ b/org.bndtools.help/docs/manual/repositories-view.html @@ -0,0 +1,59 @@ + + + + +Repositories View + + + +

Repositories View

+

+

Bndtools uses repositories to supply dependencies to be used at build-time and at runtime.

+

A repository is essentially a collection of bundles, optionally with some kind of index.

+

It may be located anywhere: in the workspace, somewhere else on the local file system, or on a remote server.

+

Bndtools uses repositories in the following ways:

+ +

Repositories are implemented as bnd plug-ins, and can be configured by editing the Plugins sections of the workspace configuration file (Bndtools menu » Open main bnd config). +Repositories can be tagged to control how they are used for resolving dependencies.

+

+

Since repositories are implemented as plug-ins, it is theoretically possible to support almost any kind of repository, by developing a new plug-in type; though of course it is more convenient to use an existing repository plug-in.

+

The special repo bnd-cache is a mini cache repo that is expanded in the cnf directory to cache some intermediate files.

+

Indexed Repositories

+

Bndtools supports a collection of repositories based on an index file that reports the content of the repository along with the capabilities and requirements of each resource listed. There are multiple available formats for the index:

+ +

The advantage of using indexed repositories is that they can be used for automatic Resolution in the bndrun editor.

+

Maven Central (MavenBndRepository)

+

This repository is one of "indexed" repositories, therefore index property points to central.maven file that contains GAV coordinates to libraries located in Maven Central.

+

central.maven file doesn't fill itself automatically. Think of this repository like an empty <dependencies> section in maven. In order to fill it you need to add GAVs (one per line) to it.

+

Example:

+
# List repository contents using GAV coordinates
+org.apache.camel:camel-core:2.23.1
+
+ + +

OSGiRepositories / Fixed Index Repositories

+

The OSGiRepository can use index files compatible to the OSGi Repository Service Specification. A OSGiRepository cannot be modified from within bnd or Bndtools.

+ +

Local Indexed Repository

+

This repository maintains a local filesystem directory of bundles. The repository is editable from within bnd/Bndtools and the index file is regenerated automatically when bundles are deployed into it.

+ +

File Repository

+

This type of repository is based on a very simple file system directory structure.

+ + + diff --git a/org.bndtools.help/docs/manual/resolution-view.html b/org.bndtools.help/docs/manual/resolution-view.html new file mode 100644 index 0000000000..e6f7e9f301 --- /dev/null +++ b/org.bndtools.help/docs/manual/resolution-view.html @@ -0,0 +1,33 @@ + + + + +Resolution View + + + +

Resolution View

+

+

The Resolution View is a powerful tool to analyse the requirements and capabilities of bundles and their dependencies. This shows the requirements and capabilities side by side of one or multiple selected resources such as JAR file(s), a bnd.bnd file or entries in the Repository Browser (bundles in a repository or repositories).

+

Especially when it comes to resolution issues (e.g. required package cannot be satisfied by another bundle) this is the tool to make resolution issues visible.

+

Example

+

By selecting a bundle A and a repository R in the Repository View, it allows you to see the aggregated Requirements and Capabilities of both. In other words it shows you:

+ +

If there is a requirement for which no other bundle provides a capability, then the Resolve would fail - and you can make that visible in the resolution view.

+

This makes it a valuable tool used after a failed resolution (see the Resolve button in the .bnd / .bndrun editor) and its (sometimes cryptic) error message.

+

Features

+ +

More information

+

Background information can also be found in the manual at Resolving Dependencies.

+ + diff --git a/org.bndtools.help/docs/manual/templates-osgi-service.html b/org.bndtools.help/docs/manual/templates-osgi-service.html new file mode 100644 index 0000000000..ada62bd8b5 --- /dev/null +++ b/org.bndtools.help/docs/manual/templates-osgi-service.html @@ -0,0 +1,44 @@ + + + + +Java OSGi Service + + + +

Java OSGi Service

+

Java OSGi Service (api, impl, consumer)

+

This template is based on the idea of this tutorial and will create three bundles for a typical OSGi service scenario:

+ +

Requirements:

+ +

1. Open the wizard, select File->New->Other...

+

+

2. Then select OSGi Services -> Java OSGi Service (api, impl, consumer) and Next>

+

+

3. Fill in desired values for the Project Name and the Service Name fields

+

+

4. Click Finish

+

+

There are three projects created: org.myorg.test.hello (api), org.myorg.test.hello.impl, and org.myorg.test.hello.consumer.

+

5. Run/Debug the project

+

Included in the generated org.myorg.test.hello project is a Hello.bndrun file that can be used to launch a framework, register the HelloServiceImpl, inject (via SCR) into the HelloServiceConsumer and have the HelloServiceConsumer call the service.

+

+

6. Resolving dependencies

+

Click Resolve and then Update to let bndtools figure out the bundles to run (-runbundles).

+

+

7. Run the project

+

+

Then click on Run OSGi (or Debug OSGi). Results in the service method being called and the console output.

+

Next steps

+

Now you have a good starting point to develop your service. +In an existing project you probably do not need the generated consumer bundle if you already have other bundles consuming the service.

+ + diff --git a/org.bndtools.help/docs/manual/templates.html b/org.bndtools.help/docs/manual/templates.html new file mode 100644 index 0000000000..56b528a2a3 --- /dev/null +++ b/org.bndtools.help/docs/manual/templates.html @@ -0,0 +1,15 @@ + + + + +Project Templates + + + +

Project Templates

+

The Bndtools supports wizard-based creation of various elements required for OSGi development. There are templates for Bnd-Workspaces, Projects, Components, .bnd and .bndrun files and even for creating services consisting of multiple bundles.

+ + + diff --git a/org.bndtools.help/toc.xml b/org.bndtools.help/toc.xml new file mode 100644 index 0000000000..1cc8aa16ad --- /dev/null +++ b/org.bndtools.help/toc.xml @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.bndtools.p2/bnd.bnd b/org.bndtools.p2/bnd.bnd index 34ebceb6f4..4989795b3b 100644 --- a/org.bndtools.p2/bnd.bnd +++ b/org.bndtools.p2/bnd.bnd @@ -23,6 +23,7 @@ Bundle-SymbolicName: org.bndtools.p2 org.bndtools.versioncontrol.ignores.plugin.git, \ org.bndtools.templating, \ org.bndtools.templating.gitrepo, \ + org.bndtools.help, \ biz.aQute.bnd.embedded-repo, \ biz.aQute.bnd.maven, \ biz.aQute.bnd.util, \ diff --git a/org.bndtools.p2/bndtools.main.feature.bndrun b/org.bndtools.p2/bndtools.main.feature.bndrun index 058af12a88..4ec94e1864 100644 --- a/org.bndtools.p2/bndtools.main.feature.bndrun +++ b/org.bndtools.p2/bndtools.main.feature.bndrun @@ -25,6 +25,7 @@ Require-Capability \ org.bndtools.headless.build.manager, \ org.bndtools.headless.build.plugin.ant, \ org.bndtools.headless.build.plugin.gradle, \ + org.bndtools.help, \ org.bndtools.launch, \ org.bndtools.remoteinstall, \ org.bndtools.versioncontrol.ignores.manager, \