package test.component;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.Manifest;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.log.LogService;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import aQute.bnd.annotation.component.Activate;
import aQute.bnd.annotation.component.Component;
import aQute.bnd.annotation.component.ConfigurationPolicy;
import aQute.bnd.annotation.component.Deactivate;
import aQute.bnd.annotation.component.Modified;
import aQute.bnd.annotation.component.Reference;
import aQute.bnd.annotation.metatype.Meta;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Domain;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Resource;
import aQute.bnd.service.RepositoryPlugin;
import aQute.bnd.service.repository.SearchableRepository;
import aQute.bnd.test.BndTestCase;
import junit.framework.AssertionFailedError;
/**
* Test for use of DS components specified using bnd proprietary annotations.
*/
@SuppressWarnings({
"resource", "unused", "rawtypes"
})
public class BNDAnnotationTest extends BndTestCase {
static final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
static final XPathFactory xpathf = XPathFactory.newInstance();
static final XPath xpath = xpathf.newXPath();
static DocumentBuilder db;
static {
try {
dbf.setNamespaceAware(true);
db = dbf.newDocumentBuilder();
xpath.setNamespaceContext(new NamespaceContext() {
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
return Arrays.asList("md", "scr").iterator();
}
@Override
public String getPrefix(String namespaceURI) {
if (namespaceURI.equals("http://www.osgi.org/xmlns/metatype/v1.1.0"))
return "md";
if (namespaceURI.equals("http://www.osgi.org/xmlns/scr/v1.1.0"))
return "scr";
return null;
}
@Override
public String getNamespaceURI(String prefix) {
if (prefix.equals("md"))
return "http://www.osgi.org/xmlns/metatype/v1.1.0";
else if (prefix.equals("scr"))
return "http://www.osgi.org/xmlns/scr/v1.1.0";
else
return null;
}
});
} catch (ParserConfigurationException e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
private Builder builder(String spec) throws Exception {
return builder(spec, 0, 0);
}
private Builder builder(String spec, int errors, int warnings) throws IOException, Exception, AssertionFailedError {
Builder b = new Builder();
b.setExceptions(true);
b.setClasspath(new File[] {
new File("bin")
});
b.setProperty("Service-Component", spec);
b.setProperty("Private-Package", "test.component");
b.setProperty("-dsannotations", "");
b.setProperty("-fixupmessages.bndannodeprecated", "Bnd DS annotations are deprecated");
b.build();
assertOk(b, errors, warnings);
return b;
}
/**
* Whitespace in Component name causes Component initialization to fail #548
*/
@Component(name = "Hello World Bnd ^ % / \\ $")
static class BrokenNameDS {
}
@Component(name = "Hello World")
static class BrokenNameBnd {
}
public void testBrokenName() throws Exception {
Builder b = builder("*Broken*", 0, 2);
Jar build = b.getJar();
assertTrue(b.check("Invalid component name"));
Domain m = Domain.domain(build.getManifest());
Parameters parameters = m.getParameters("Service-Component");
assertEquals(2, parameters.size());
System.out.println(parameters);
assertTrue(parameters.keySet().contains("OSGI-INF/Hello-World-Bnd---------$.xml"));
assertTrue(parameters.keySet().contains("OSGI-INF/Hello-World.xml"));
}
/**
* Can we order the references? References are ordered by their name as Java
* does not define the order of the methods.
*
*/
@Component
static class TestReferenceOrdering {
@Reference(service = LogService.class)
void setA(@SuppressWarnings("unused") ServiceReference< ? > ref) {}
@Reference
void setC(@SuppressWarnings("unused") LogService log) {}
@Reference(service = LogService.class)
void setB(@SuppressWarnings("unused") Map<String,Object> map) {}
}
public void testAnnotationReferenceOrdering() throws Exception {
Builder b = builder("*TestReferenceOrdering");
Document doc = doc(b, "test.component.BNDAnnotationTest$TestReferenceOrdering");
NodeList nodes = (NodeList) xpath.evaluate("//reference", doc, XPathConstants.NODESET);
assertEquals("a", nodes.item(0).getAttributes().getNamedItem("name").getTextContent());
assertEquals("b", nodes.item(1).getAttributes().getNamedItem("name").getTextContent());
assertEquals("c", nodes.item(2).getAttributes().getNamedItem("name").getTextContent());
}
/**
* Test config with metatype
*/
@Component(name = "config", designateFactory = Config.class, configurationPolicy = ConfigurationPolicy.require)
static class MetatypeConfig {
interface Config {
String name();
}
}
@Component(designate = Config.class)
static class MetatypeConfig2 {
interface Config {
String name();
}
}
@Component(designate = RepositoryPlugin.class, designateFactory = SearchableRepository.class)
static class MetatypeConfig3 {}
@Component(designateFactory = SearchableRepository.class)
static class MetatypeConfig4 {}
public void testConfig() throws Exception {
Builder b = builder("*MetatypeConfig*");
assertTrue(b.check());
System.err.println(b.getJar().getResources().keySet());
// Check component name
{
Resource cr = b.getJar().getResource("OSGI-INF/config.xml");
cr.write(System.err);
Document d = db.parse(cr.openInputStream());
assertEquals("config", xpath.evaluate("/scr:component/@name", d, XPathConstants.STRING));
}
// Check if config properly linked
{
Resource mr = b.getJar().getResource("OSGI-INF/metatype/config.xml");
mr.write(System.err);
Document d = db.parse(mr.openInputStream());
assertEquals("config", xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
assertEquals("config", xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
}
// Now with default name
{
Resource cr2 = b.getJar().getResource("OSGI-INF/test.component.BNDAnnotationTest$MetatypeConfig2.xml");
cr2.write(System.err);
Document d = db.parse(cr2.openInputStream());
assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
xpath.evaluate("//scr:component/@name", d, XPathConstants.STRING));
}
{
Resource mr2 = b.getJar()
.getResource("OSGI-INF/metatype/test.component.BNDAnnotationTest$MetatypeConfig2.xml");
mr2.write(System.err);
Document d = db.parse(mr2.openInputStream());
assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
}
}
/**
* Test properties
*/
@Meta.OCD
static interface Config {
String name();
}
@Component(name = "props", properties = {
" a =1", "b=3", "c=1|2|3", "d=1|"
}, designate = Config.class, designateFactory = Config.class)
static class PropertiesAndConfig {
@Activate
protected void activate(@SuppressWarnings("unused") ComponentContext c) {}
}
public void testPropertiesAndConfig() throws Exception {
Builder b = builder("*PropertiesAndConfig");
Resource cr = b.getJar().getResource("OSGI-INF/props.xml");
cr.write(System.err);
{
Document doc = doc(b, "props");
assertEquals("1", xpath.evaluate("scr:component/property[@name='a']/@value", doc));
assertEquals("3", xpath.evaluate("scr:component/property[@name='b']/@value", doc));
assertEquals("1\n2\n3", xpath.evaluate("scr:component/property[@name='c']", doc).trim());
assertEquals("1", xpath.evaluate("scr:component/property[@name='d']", doc).trim());
}
}
/**
* Test if a package private method gives us 1.1 + namespace in the XML
* using bnd annotations
*/
@Component(name = "protected")
static class PackageProtectedActivateMethod {
@Activate
protected void activatex(@SuppressWarnings("unused") ComponentContext c) {}
}
@Component(name = "packageprivate")
static class PackagePrivateActivateMethod {
@Activate
void activatex(@SuppressWarnings("unused") ComponentContext c) {}
}
@Component(name = "private")
static class PrivateActivateMethod {
@SuppressWarnings("unused")
@Activate
private void activatex(ComponentContext c) {}
}
@Component(name = "default-private")
static class DefaultPrivateActivateMethod {
@SuppressWarnings("unused")
@Activate
private void activate(ComponentContext c) {}
}
@Component(name = "default-protected")
static class DefaultProtectedActivateMethod {
@Activate
protected void activate(@SuppressWarnings("unused") ComponentContext c) {}
}
@Component(name = "public")
static class PublicActivateMethod {
@Activate
public void activatex(@SuppressWarnings("unused") ComponentContext c) {}
}
public void testPackagePrivateActivateMethodBndAnnos() throws Exception {
Builder b = builder("*ActivateMethod");
assertTrue(b.check());
{
Document doc = doc(b, "default-private");
Object o = xpath.evaluate("scr:component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("", xpath.evaluate("component/@activate", doc));
}
{
Document doc = doc(b, "default-protected");
Object o = xpath.evaluate("component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("", xpath.evaluate("component/@activate", doc));
}
{
Document doc = doc(b, "public");
Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
}
{
Document doc = doc(b, "private");
Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
}
{
Document doc = doc(b, "protected");
Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
}
{
Document doc = doc(b, "packageprivate");
Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
assertNotNull(o);
assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
}
}
/**
* Test an attribute on an annotation
*/
@Component(name = "annotated")
static class Annotated {
@Reference
protected void setLog(@SuppressWarnings("unused") LogService log) {}
}
public void testAnnotatedWithAttribute() throws Exception {
Builder b = builder("*NoUnbind;log=org.osgi.service.log.LogService");
Jar jar = b.getJar();
Manifest manifest = jar.getManifest();
String sc = manifest.getMainAttributes().getValue(Constants.SERVICE_COMPONENT);
assertFalse(sc.contains(";"));
}
/**
* Imported default package because JSR14 seems to do something weird with
* annotations.
*
* @throws Exception
*/
public void testJSR14ComponentAnnotations() throws Exception {
Builder b = new Builder();
b.setProperty("Include-Resource",
"org/osgi/impl/service/coordinator/AnnotationWithJSR14.class=jar/AnnotationWithJSR14.jclass");
b.setProperty("Service-Component", "*");
b.setProperty("-resourceonly", "true");
Jar jar = b.build();
System.err.println(b.getErrors());
System.err.println(b.getWarnings());
assertEquals(0, b.getErrors().size());
assertEquals(1, b.getWarnings().size());
Manifest manifest = jar.getManifest();
String component = manifest.getMainAttributes().getValue("Service-Component");
System.err.println(component);
assertNull(component);
}
@Component(name = "nounbind")
static class NoUnbind {
@Reference
protected void setLog(@SuppressWarnings("unused") LogService log) {}
}
public void testNoUnbind() throws Exception {
Builder b = builder("*NoUnbind");
Document doc = doc(b, "nounbind");
assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
assertEquals("", xpath.evaluate("component/reference/@unbind", doc));
}
@Component(name = "nounbind_dynamic")
static class NoUnbindDynamic {
@Reference(dynamic = true)
protected void setLog(@SuppressWarnings("unused") LogService log) {}
}
public void testNoUnbindDynamic() throws Exception {
Builder b = builder("*NoUnbindDynamic", 1, 0);
assertTrue(b.getErrors().get(0).endsWith("dynamic but has no unbind method."));
}
// this is a bnd annotation not a DS annotation
@Component(name = "explicitunbind")
static class ExplicitUnbind {
@Reference(unbind = "killLog")
protected void setLog(@SuppressWarnings("unused") LogService log) {}
}
public void testExplicitUnbind() throws Exception {
Builder b = builder("*ExplicitUnbind", 1, 0);
Document doc = doc(b, "explicitunbind");
assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
assertEquals("killLog", xpath.evaluate("component/reference/@unbind", doc));
}
/**
* Test to see if we get a namespace when we use 1.1 semantics on the
* activate and deactivate
*/
@Component(name = "ncomp", provide = {})
static class NewActivateVersion {
@Activate
protected void activate(@SuppressWarnings("unused") ComponentContext context) {}
}
@Component(name = "ndcomp", provide = {})
static class NewDeActivateVersion {
@Deactivate
protected void deactivate() {}
}
@Component(name = "nbcomp", provide = {})
static class NewBindVersion {
@SuppressWarnings("rawtypes")
@Reference
protected void bind(ServiceReference ref, Map<String,Object> map) {}
}
public void testNewVersion() throws Exception {
Builder b = builder("*Version");
assertTrue(b.check());
{
Document doc = doc(b, "ncomp");
Node o = (Node) xpath.evaluate("scr:component", doc, XPathConstants.NODE);
assertNull("Expected ncomp to have old namespace", o);
o = (Node) xpath.evaluate("component", doc, XPathConstants.NODE);
assertNotNull("Expected ncomp to have old namespace", o);
}
}
/**
* Test the same bind method names
*/
@Component(name = "cpcomp")
static class SameRefName {
@Reference
protected void bind(@SuppressWarnings("unused") LogService log) {
}
@Reference
protected void bind(@SuppressWarnings("unused") EventAdmin event) {
}
}
public void testSameRefName() throws Exception {
Builder b = builder("*.SameRefName", 1, 0);
// Document doc = doc(b, "cpcomp");
}
/**
* Test the configuration policy
*/
@Component(name = "cpcomp", configurationPolicy = ConfigurationPolicy.require, provide = {
Serializable.class, EventAdmin.class
})
static class ConfigurationPolicyTest {
}
public void testConfigurationPolicy() throws Exception {
Builder b = builder("*.ConfigurationPolicyTest");
Document doc = doc(b, "cpcomp");
assertEquals("java.io.Serializable",
doc.getElementsByTagName("provide").item(0).getAttributes().getNamedItem("interface").getTextContent());
assertEquals("org.osgi.service.event.EventAdmin",
doc.getElementsByTagName("provide").item(1).getAttributes().getNamedItem("interface").getTextContent());
}
/**
* Test to see if we use defaults we get the old version of the namespace
*/
@Component(name = "vcomp", provide = {})
static class OldVersion {
@Activate
protected void activate(@SuppressWarnings("unused") ComponentContext cc) {}
@Deactivate
protected void deactivate(@SuppressWarnings("unused") ComponentContext cc) {}
@Reference
protected void bindLog(@SuppressWarnings("unused") LogService log) {
}
}
/**
* Test if an activate/deactivate method that has wrong prototype
*/
@Component(name = "wacomp", provide = {})
static class ActivateWithWrongArguments {
@Activate
// Is not allowed, must give an error
protected void whatever(@SuppressWarnings("unused") String x) {}
}
public void testActivateWithActivateWithWrongArguments() throws Exception {
Builder b = builder("*.ActivateWithWrongArguments", 2, 0);// same error
// detected
// twice
Document doc = doc(b, "wacomp");
assertAttribute(doc, "", "scr:component/@activate"); // validation
// removes the
// non-existent
// method.
}
/**
* Test if an activate/deactivate method can have multiple args
*/
@Component(name = "amcomp", provide = {})
static class ActivateWithMultipleArguments {
@Activate
protected void whatever(@SuppressWarnings("unused") Map< ? , ? > map,
@SuppressWarnings("unused") ComponentContext cc, @SuppressWarnings("unused") BundleContext bc,
@SuppressWarnings("unused") Map< ? , ? > x) {}
}
public void testActivateWithMultipleArguments() throws Exception {
Builder b = builder("*.ActivateWithMultipleArguments");
Document doc = doc(b, "amcomp");
assertAttribute(doc, "whatever", "scr:component/@activate");
}
/**
* Test components with references that have multiple arguments.
*/
@Component(name = "mcomp", provide = {})
static class MultipleArguments {
@Reference
protected void bindWithMap(@SuppressWarnings("unused") LogService log,
@SuppressWarnings("unused") Map< ? , ? > map) {}
}
@Component(name = "rcomp", provide = {})
static class ReferenceArgument {
@Reference(service = LogService.class)
protected void bindReference(@SuppressWarnings("unused") ServiceReference ref) {}
}
public void testMultipleArguments() throws Exception {
Builder b = builder("*.(MultipleArguments|ReferenceArgument)");
Document doc = doc(b, "mcomp");
assertAttribute(doc, "bindWithMap", "scr:component/reference/@bind");
assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/reference/@interface");
doc = doc(b, "rcomp");
assertAttribute(doc, "bindReference", "scr:component/reference/@bind");
assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/reference/@interface");
}
/**
* Test components with weird bind methods.
*/
@Component(name = "xcomp", provide = {})
static class TypeVersusDetailed {
@Reference(type = '*')
protected void bind(@SuppressWarnings("unused") LogService log) {}
protected void unbind(@SuppressWarnings("unused") LogService log) {}
@Reference(multiple = true, optional = true, dynamic = true)
protected void bind2(@SuppressWarnings("unused") LogService log) {}
protected void unbind2(@SuppressWarnings("unused") LogService log) {}
}
public void testTypeVersusDetailed() throws Exception {
Builder b = builder("*.TypeVersusDetailed");
Document doc = doc(b, "xcomp");
print(doc, "");
assertAttribute(doc, "bind2", "component/reference[1]/@bind");
assertAttribute(doc, "dynamic", "component/reference[1]/@policy");
assertAttribute(doc, "0..n", "component/reference[1]/@cardinality");
assertAttribute(doc, "bind", "component/reference[2]/@bind");
assertAttribute(doc, "dynamic", "component/reference[2]/@policy");
assertAttribute(doc, "0..n", "component/reference[2]/@cardinality");
}
/**
* Test components with weird bind methods.
*/
@Component(name = "acomp", provide = {})
static class MyComponent4 {
@Activate
protected void xyz() {}
}
public void testAnnotationsNamespaceVersion() throws Exception {
Builder b = builder("*MyComponent4");
Document doc = doc(b, "acomp");
System.err.println(doc.getDocumentElement().getNamespaceURI());
}
/**
* Test components with weird bind methods.
*/
@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.require)
static class MyComponent2 {
@Reference
protected void addLogMultiple(@SuppressWarnings("unused") LogService log) {
}
}
public void testAnnotationsStrangeBindMethods() throws Exception {
Builder b = builder("*MyComponent2");
Document doc = doc(b, "acomp");
assertEquals("addLogMultiple", xpath.evaluate("//@bind", doc));
assertEquals("", xpath.evaluate("//@unbind", doc));
assertAttribute(doc, "logMultiple", "scr:component/reference[1]/@name");
assertAttribute(doc, "addLogMultiple", "scr:component/reference[1]/@bind");
}
/**
* Test setting the unbind method
*/
@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.ignore)
static class MyComponent3 {
@Reference(unbind = "destroyX")
protected void putX(@SuppressWarnings("unused") LogService log) {
}
}
public void testAnnotationsSettingUnbind() throws Exception {
Builder b = builder("*MyComponent3", 1, 0);
Document doc = doc(b, "acomp");
assertAttribute(doc, "putx", "scr:component/reference[1]/@name");
assertAttribute(doc, "putX", "scr:component/reference[1]/@bind");
assertAttribute(doc, "destroyX", "scr:component/reference[1]/@unbind");
}
/**
* Test some more components
*
* @author aqute
*/
@Component(name = "acomp", enabled = true, factory = "abc", immediate = false, provide = LogService.class, servicefactory = true, configurationPolicy = ConfigurationPolicy.optional)
static class MyComponent implements Serializable {
private static final long serialVersionUID = 1L;
LogService log;
@Activate
protected void activatex() {}
@Deactivate
protected void deactivatex() {}
@Modified
protected void modifiedx() {}
@Reference(type = '~', target = "(abc=3)")
protected void setLog(LogService log) {
this.log = log;
}
protected void unsetLog(@SuppressWarnings("unused") LogService log) {
this.log = null;
}
}
public void testAnnotations() throws Exception {
Builder b = builder("*MyComponent");
Document doc = doc(b, "acomp");
print(doc, "");
assertAttribute(doc, "test.component.BNDAnnotationTest$MyComponent", "scr:component/implementation/@class");
assertAttribute(doc, "acomp", "scr:component/@name");
assertAttribute(doc, "abc", "scr:component/@factory");
assertAttribute(doc, "true", "scr:component/service/@servicefactory");
assertAttribute(doc, "activatex", "scr:component/@activate");
assertAttribute(doc, "modifiedx", "scr:component/@modified");
assertAttribute(doc, "deactivatex", "scr:component/@deactivate");
assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/service/provide/@interface");
assertAttribute(doc, "(abc=3)", "scr:component/reference/@target");
assertAttribute(doc, "setLog", "scr:component/reference/@bind");
assertAttribute(doc, "unsetLog", "scr:component/reference/@unbind");
assertAttribute(doc, "0..1", "scr:component/reference/@cardinality");
}
public static void assertAttribute(Document doc, String value, String expr) throws XPathExpressionException {
System.err.println(expr);
String o = (String) xpath.evaluate(expr, doc, XPathConstants.STRING);
if (o == null) {
}
assertNotNull(o);
assertEquals(value, o);
}
static Document doc(Builder b, String name) throws Exception {
Jar jar = b.getJar();
Resource r = jar.getResource("OSGI-INF/" + name + ".xml");
assertNotNull(r);
Document doc = db.parse(r.openInputStream());
r.write(System.err);
return doc;
}
private static void print(Node doc, String indent) {
System.err.println(indent + doc);
NamedNodeMap attributes = doc.getAttributes();
if (attributes != null)
for (int i = 0; i < attributes.getLength(); i++) {
print(attributes.item(i), indent + " ");
}
NodeList nl = doc.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
print(nl.item(i), indent + " ");
}
}
@Component(name = "mixed-bnd-std")
static class MixedBndStd {
@org.osgi.service.component.annotations.Reference
EventAdmin ea;
@org.osgi.service.component.annotations.Reference
protected void setLog(@SuppressWarnings("unused") LogService log) {}
@org.osgi.service.component.annotations.Activate
void start() {}
@org.osgi.service.component.annotations.Modified
void update(Map<String,Object> map) {}
@org.osgi.service.component.annotations.Deactivate
void stop() {}
}
public void testMixedBndStandard() throws Exception {
Builder b = builder("*MixedBndStd", 5, 0);
List<String> errors = new ArrayList<String>(b.getErrors());
Collections.sort(errors);
assertEquals(
"The DS component mixed-bnd-std uses bnd annotations to declare it as a component, but also uses the standard DS annotation: org.osgi.service.component.annotations.Activate on method start with signature ()V. It is an error to mix these two types of annotations",
errors.get(0));
assertEquals(
"The DS component mixed-bnd-std uses bnd annotations to declare it as a component, but also uses the standard DS annotation: org.osgi.service.component.annotations.Deactivate on method stop with signature ()V. It is an error to mix these two types of annotations",
errors.get(1));
assertEquals(
"The DS component mixed-bnd-std uses bnd annotations to declare it as a component, but also uses the standard DS annotation: org.osgi.service.component.annotations.Modified on method update with signature (Ljava/util/Map;)V. It is an error to mix these two types of annotations",
errors.get(2));
assertEquals(
"The DS component mixed-bnd-std uses bnd annotations to declare it as a component, but also uses the standard DS annotation: org.osgi.service.component.annotations.Reference on field ea. It is an error to mix these two types of annotations",
errors.get(3));
assertEquals(
"The DS component mixed-bnd-std uses bnd annotations to declare it as a component, but also uses the standard DS annotation: org.osgi.service.component.annotations.Reference on method setLog with signature (Lorg/osgi/service/log/LogService;)V. It is an error to mix these two types of annotations",
errors.get(4));
}
}