Skip to content

Commit 450c62e

Browse files
committed
do not concat BUNDLE_ACTIVATOR
fixes a problem in Verifier.verifyActivator() ("The Bundle-Activator header only supports a single type. The following types were found") when the bnd instructions already define a Bundle-Activator but a processed jar also contributed a Bundle-Activator. Before this fix the Bundle-Activator header was concatenated to the existing Bundle-Activator header in bnd.bnd and thus contained multiple values (separated by comma). But for Bundle-Activator this does not make sense as it supports only a single value. Added Constants.BUNDLE_HEADERS_SINGLE_VALUE for a list of other headers which should also not be concatenated Signed-off-by: Christoph Rueger <[email protected]>
1 parent 7411173 commit 450c62e

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

biz.aQute.bndlib.tests/test/test/BuilderTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,6 +3091,86 @@ public void testFindActivator() throws Exception {
30913091
}
30923092
}
30933093

3094+
/**
3095+
* Check that the defined activator is found, and not concatenated by the
3096+
* Bundle-Activator annotation in TypeInVersionedPackage
3097+
*
3098+
* @throws Exception
3099+
*/
3100+
@Test
3101+
public void testBundleActivatorShouldNotBeConcatenated() throws Exception {
3102+
Builder bmaker = new Builder();
3103+
try {
3104+
bmaker.setProperty("Bundle-Activator", "test.activator.Activator");
3105+
bmaker.setProperty("build", "xyz"); // for @Version annotation
3106+
bmaker.setProperty("Private-Package", "test.*");
3107+
bmaker.setProperty("-bundleannotations",
3108+
"test.annotationheaders.attrs.std.activator.TypeInVersionedPackage");
3109+
// bmaker.setProperty("-dsannotations", "!*");
3110+
// bmaker.setProperty("-metatypeannotations", "!*");
3111+
bmaker.setClasspath(new File[] {
3112+
new File("bin_test")
3113+
});
3114+
bmaker.setProperty("-fixupmessages.export",
3115+
"The annotation aQute.bnd.annotation.Export applied to package test.versionpolicy.api is deprecated and will be removed in a future release. The org.osgi.annotation.bundle.Export should be used instead");
3116+
bmaker.setProperty("-fixupmessages.directive",
3117+
"Unknown directive foobar: in Export-Package, allowed directives are uses:,mandatory:,include:,exclude:,-import:, and 'x-*'");
3118+
3119+
Jar jar = bmaker.build();
3120+
report("testBundleActivatorShouldNotBeConcatenated", bmaker, jar);
3121+
3122+
Attributes main = jar.getManifest()
3123+
.getMainAttributes();
3124+
assertEquals("test.activator.Activator", main.getValue(Constants.BUNDLE_ACTIVATOR));
3125+
assertFalse(
3126+
bmaker
3127+
.check(
3128+
"The Bundle-Activator header only supports a single type. The following types were found: test.activator.Activator,test.annotationheaders.attrs.std.activator.TypeInVersionedPackage. This usually happens when a macro resolves to multiple types"));
3129+
} finally {
3130+
bmaker.close();
3131+
}
3132+
}
3133+
3134+
/**
3135+
* Check that the Bundle-Activator annotation in TypeInVersionedPackage
3136+
* defines the Bundle-Activator of our bundle.
3137+
*
3138+
* @throws Exception
3139+
*/
3140+
@Test
3141+
public void testBundleActivatorFromAnnotation() throws Exception {
3142+
Builder bmaker = new Builder();
3143+
try {
3144+
// bmaker.setProperty("Bundle-Activator",
3145+
// "test.activator.Activator");
3146+
bmaker.setProperty("build", "xyz"); // for @Version annotation
3147+
bmaker.setProperty("Private-Package", "test.*");
3148+
bmaker.setProperty("-bundleannotations",
3149+
"test.annotationheaders.attrs.std.activator.TypeInVersionedPackage,*");
3150+
bmaker.setClasspath(new File[] {
3151+
new File("bin_test")
3152+
});
3153+
bmaker.setProperty("-fixupmessages.export",
3154+
"The annotation aQute.bnd.annotation.Export applied to package test.versionpolicy.api is deprecated and will be removed in a future release. The org.osgi.annotation.bundle.Export should be used instead");
3155+
bmaker.setProperty("-fixupmessages.directive",
3156+
"Unknown directive foobar: in Export-Package, allowed directives are uses:,mandatory:,include:,exclude:,-import:, and 'x-*'");
3157+
3158+
Jar jar = bmaker.build();
3159+
// assertTrue(bmaker.check());
3160+
report("testBundleActivatorFromAnnotation", bmaker, jar);
3161+
3162+
Attributes main = jar.getManifest()
3163+
.getMainAttributes();
3164+
assertEquals("test.annotationheaders.attrs.std.activator.TypeInVersionedPackage",
3165+
main.getValue(Constants.BUNDLE_ACTIVATOR));
3166+
3167+
assertFalse(bmaker.check(
3168+
"The Bundle-Activator header only supports a single type*"));
3169+
} finally {
3170+
bmaker.close();
3171+
}
3172+
}
3173+
30943174
@Test
30953175
public void testImportVersionRange() throws Exception {
30963176
assertVersionEquals("[1.1,2.0)", "[1.1,2.0)");

biz.aQute.bndlib/src/aQute/bnd/osgi/AnnotationHeaders.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package aQute.bnd.osgi;
22

33
import static aQute.bnd.exceptions.ConsumerWithException.asConsumer;
4+
import static aQute.bnd.osgi.Constants.BUNDLE_HEADERS_SINGLE_VALUE;
45
import static java.util.Collections.emptySet;
56

67
import java.io.Closeable;
@@ -1030,11 +1031,20 @@ private void add(Annotation annotation, String name, String value) throws IOExce
10301031
/*
10311032
* This method is a pass thru for the properties of the analyzer. If we have
10321033
* such a header, we get the analyzer header and concatenate our values
1033-
* after removing dups.
1034+
* after removing dups. But there are exceptions: Some headers (e.g.
1035+
* Bundle-Activator) only allow a single value and for them concatenating to
1036+
* the analyzer header does not make sense.
10341037
*/
10351038

10361039
public String getHeader(String name) {
10371040
String value = analyzer.getProperty(name);
1041+
1042+
// for some OSGi headers we do not want to concatenate to existing
1043+
// analyzer value (analyzer value wins)
1044+
if (value != null && BUNDLE_HEADERS_SINGLE_VALUE.contains(name)) {
1045+
return value;
1046+
}
1047+
10381048
if (headers.containsKey(name)) {
10391049
//
10401050
// Remove duplicates and sort

biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,21 @@ public interface Constants {
348348

349349
// Ignore bundle specific headers. These headers do not make a lot of sense
350350
// to inherit
351+
// (https://docs.osgi.org/specification/osgi.core/8.0.0/framework.lifecycle.html#i3293513)
351352
Set<String> BUNDLE_SPECIFIC_HEADERS = Sets.of(INCLUDE_RESOURCE, INCLUDERESOURCE,
352353
BUNDLE_ACTIVATOR, BUNDLE_CLASSPATH, BUNDLE_NAME, BUNDLE_NATIVECODE, BUNDLE_SYMBOLICNAME, IMPORT_PACKAGE,
353354
EXPORT_PACKAGE, DYNAMICIMPORT_PACKAGE, FRAGMENT_HOST, REQUIRE_BUNDLE, PRIVATE_PACKAGE, PRIVATEPACKAGE,
354355
INCLUDEPACKAGE, EXPORT_CONTENTS, TESTCASES, NOMANIFEST, WAB, WABLIB, REQUIRE_CAPABILITY, PROVIDE_CAPABILITY,
355356
DSANNOTATIONS, SERVICE_COMPONENT, SIGNATURE_TEST, METATYPE_ANNOTATIONS, CDIANNOTATIONS, AUTOMATIC_MODULE_NAME,
356357
EXPORT_APIGUARDIAN, DEFINE_CONTRACT);
357358

359+
/**
360+
* OSGi Bundle headers, which only allow a single value (i.e. not multiple
361+
* values concatenated by comma)
362+
*/
363+
Set<String> BUNDLE_HEADERS_SINGLE_VALUE = Sets.of(BUNDLE_ACTIVATOR, BUNDLE_ACTIVATIONPOLICY,
364+
BUNDLE_SYMBOLICNAME, BUNDLE_VERSION, BUNDLE_MANIFESTVERSION);
365+
358366
char DUPLICATE_MARKER = '~';
359367
String INTERNAL_EXPORTED_DIRECTIVE = "-internal-exported:";
360368
String INTERNAL_BUNDLESYMBOLICNAME_DIRECTIVE = "-internal-bundlesymbolicname:";

0 commit comments

Comments
 (0)