/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.application.modelling.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.aries.application.modelling.ModellingManager;
import org.apache.aries.application.modelling.ParsedServiceElements;
import org.apache.aries.application.modelling.ParserProxy;
import org.apache.aries.application.modelling.WrappedReferenceMetadata;
import org.apache.aries.application.modelling.WrappedServiceMetadata;
import org.apache.aries.application.modelling.standalone.OfflineModellingFactory;
import org.apache.aries.blueprint.container.NamespaceHandlerRegistry;
import org.apache.aries.blueprint.container.ParserServiceImpl;
import org.apache.aries.blueprint.namespace.NamespaceHandlerRegistryImpl;
import org.apache.aries.blueprint.services.ParserService;
import org.apache.aries.mocks.BundleContextMock;
import org.apache.aries.unittest.mocks.Skeleton;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.osgi.framework.BundleContext;
@RunWith(Parameterized.class)
public class ParserProxyTest {
@Parameters
public static List<Object[]> parserProxies() {
return Arrays.asList(new Object[][] {
{getMockParserServiceProxy()},
{OfflineModellingFactory.getOfflineParserProxy()}});
}
public static ParserProxy getMockParserServiceProxy() {
BundleContext mockCtx = Skeleton.newMock(new BundleContextMock(), BundleContext.class);
NamespaceHandlerRegistry nhri = new NamespaceHandlerRegistryImpl (mockCtx);
ParserService parserService = new ParserServiceImpl(nhri);
mockCtx.registerService(ParserService.class.getName(), parserService, new Hashtable<String, String>());
ParserProxyImpl parserProxyService = new ParserProxyImpl();
parserProxyService.setParserService(parserService);
parserProxyService.setBundleContext(mockCtx);
parserProxyService.setModellingManager(new ModellingManagerImpl());
return parserProxyService;
}
@AfterClass
public static void teardown() {
BundleContextMock.clear();
}
private final ModellingManager _modellingManager;
private final ParserProxy _parserProxy;
private final File resourceDir;
public ParserProxyTest(ParserProxy sut) throws IOException {
_parserProxy = sut;
_modellingManager = new ModellingManagerImpl();
// make sure paths work in Eclipse as well as Maven
if (new File(".").getCanonicalFile().getName().equals("target")) {
resourceDir = new File("../src/test/resources");
} else {
resourceDir = new File("src/test/resources");
}
}
@Test
public void basicTest1() throws Exception {
File bpXml = new File (resourceDir, "appModeller/test1.eba/bundle1.jar/OSGI-INF/blueprint/bp.xml");
File bp2Xml = new File (resourceDir, "appModeller/test1.eba/bundle1.jar/OSGI-INF/blueprint/bp2.xml");
List<URL> urls = new ArrayList<URL>();
urls.add ((bpXml.toURI()).toURL());
urls.add ((bp2Xml.toURI()).toURL());
List<? extends WrappedServiceMetadata> results = _parserProxy.parse(urls);
assertTrue ("Four results expected, not " + results.size(), results.size() == 4);
Set<WrappedServiceMetadata> resultSet = new HashSet<WrappedServiceMetadata>(results);
Set<WrappedServiceMetadata> expectedResults = getTest1ExpectedResults();
assertEquals ("Blueprint parsed xml is not as expected: " + resultSet.toString() + " != " + expectedResults,
resultSet, expectedResults);
}
@Test
public void testParseAllServiceElements() throws Exception {
File bpXml = new File (resourceDir, "appModeller/test1.eba/bundle1.jar/OSGI-INF/blueprint/bp.xml");
File bp2Xml = new File (resourceDir, "appModeller/test1.eba/bundle1.jar/OSGI-INF/blueprint/bp2.xml");
List<WrappedServiceMetadata> services = new ArrayList<WrappedServiceMetadata>();
List<WrappedReferenceMetadata> references = new ArrayList<WrappedReferenceMetadata>();
FileInputStream fis = new FileInputStream (bpXml);
ParsedServiceElements bpelem = _parserProxy.parseAllServiceElements(fis);
services.addAll(bpelem.getServices());
references.addAll(bpelem.getReferences());
fis = new FileInputStream (bp2Xml);
bpelem = _parserProxy.parseAllServiceElements(fis);
services.addAll(bpelem.getServices());
references.addAll(bpelem.getReferences());
// We expect:
// bp.xml: 3 services and 2 references
// bp2.xml: 3 services and a reference list
//
assertTrue ("Six services expected, not " + services.size(), services.size() == 6);
assertTrue ("Three references expected, not " + references.size(), references.size() == 3);
Set<WrappedServiceMetadata> expectedServices = getTest2ExpectedServices();
// ServiceResultSet will contain some services with autogenerated names starting '.' so we can't
// use a straight Set.equals(). We could add the autogenerated names to the expected results but instead
// let's test that differsOnlyByName() works
int serviceMatchesFound = 0;
for (WrappedServiceMetadata result : services) {
Iterator<WrappedServiceMetadata> it = expectedServices.iterator();
while (it.hasNext()) {
WrappedServiceMetadata next = it.next();
if (result.equals(next) || result.identicalOrDiffersOnlyByName(next)) {
serviceMatchesFound++;
it.remove();
}
}
}
assertEquals ("Parsed services are wrong: " + expectedServices + " unmatched ",
6, serviceMatchesFound);
Set<WrappedReferenceMetadata> expectedReferences = getTest2ExpectedReferences();
Set<WrappedReferenceMetadata> results = new HashSet<WrappedReferenceMetadata>(references);
assertTrue ("Parsed references are not as we'd expected: " + results.toString() + " != " + expectedReferences,
results.equals(expectedReferences));
}
@Test
public void checkMultiValues() throws Exception {
File bpXml = new File (resourceDir, "appModeller/test1.eba/bundle1.jar/OSGI-INF/blueprint/bpMultiValues.xml");
List<WrappedServiceMetadata> services = new ArrayList<WrappedServiceMetadata>();
FileInputStream fis = new FileInputStream (bpXml);
ParsedServiceElements bpelem = _parserProxy.parseAllServiceElements(fis);
services.addAll(bpelem.getServices());
assertEquals ("Multi valued service not parsed correctly", services.size(), 1);
WrappedServiceMetadata wsm = services.get(0);
Map<String, Object> props = wsm.getServiceProperties();
String [] intents = (String[]) props.get("service.intents");
assertEquals ("Service.intents[0] wrong", intents[0], "propagatesTransaction");
assertEquals ("Service.intents[1] wrong", intents[1], "confidentiality");
}
// model
// <reference id="fromOutside" interface="foo.bar.MyInjectedService"/>
// <reference-list id="refList1" interface="my.logging.services" filter="(active=true)"/>
//
private Set<WrappedReferenceMetadata> getTest2ExpectedReferences() throws Exception {
Set<WrappedReferenceMetadata> expectedResults = new HashSet<WrappedReferenceMetadata>();
expectedResults.add(_modellingManager.getImportedService(false, "foo.bar.MyInjectedService", null,
null, "fromOutside", false));
expectedResults.add(_modellingManager.getImportedService(true, "foo.bar.MyInjectedService", null,
null, "anotherOptionalReference", false));
expectedResults.add(_modellingManager.getImportedService(false, "my.logging.service", null, "(&(trace=on)(debug=true))", "refList1", true));
return expectedResults;
}
// Test 2 includes anonymous services: the expected results are a superset of test1
private Set<WrappedServiceMetadata> getTest2ExpectedServices() {
Set<WrappedServiceMetadata> expectedResults = getTest1ExpectedResults();
expectedResults.add(_modellingManager.getExportedService("", 0, Arrays.asList("foo.bar.AnonService"), null));
expectedResults.add(_modellingManager.getExportedService("", 0, Arrays.asList("foo.bar.NamedInnerBeanService"), null));
return expectedResults;
}
private Set<WrappedServiceMetadata> getTest1ExpectedResults() {
Set<WrappedServiceMetadata> expectedResults = new HashSet<WrappedServiceMetadata>();
Map<String, Object> props = new HashMap<String, Object>();
props.put ("priority", "9");
props.put("volume", "11");
props.put("property.list", Arrays.asList("1", "2", "3", "2", "1"));
//Deliberately miss off duplicate entries and reorder, the parser should still match this
props.put("property.set", new LinkedHashSet<String>(Arrays.asList("1", "2", "3")));
props.put("property.array", new String[]{"1", "2", "3", "2", "1"});
props.put("osgi.service.blueprint.compname", "myBean");
expectedResults.add(_modellingManager.getExportedService("myService", 0, Arrays.asList("foo.bar.MyService"), props));
props = new HashMap<String, Object>();
props.put ("priority", "7");
props.put ("volume", "11");
props.put ("osgi.service.blueprint.compname", "bean1");
expectedResults.add(_modellingManager.getExportedService("service1.should.be.exported", 0, Arrays.asList("foo.bar.MyService"), props));
props = new HashMap<String, Object>();
props.put ("customer", "pig");
props.put ("osgi.service.blueprint.compname", "bean2");
expectedResults.add(_modellingManager.getExportedService("service2.should.not.be.exported", 0, Arrays.asList("com.acme.Delivery"), props));
props = new HashMap<String, Object>();
props.put ("customer", "pig");
props.put ("target", "rabbit");
props.put ("payload", "excessive");
props.put ("osgi.service.blueprint.compname", "bean3");
expectedResults.add(_modellingManager.getExportedService("bean3", 0, Arrays.asList("com.acme.Delivery"), props));
return expectedResults;
}
}