/*
* 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 WARRANTIES OR 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.blueprint.itests;
import static org.apache.aries.blueprint.itests.Helper.mvnBundle;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import org.apache.aries.blueprint.BeanProcessor;
import org.apache.aries.blueprint.testbundlea.NSHandlerOne;
import org.apache.aries.blueprint.testbundlea.NSHandlerTwo;
import org.apache.aries.blueprint.testbundlea.ProcessableBean;
import org.apache.aries.blueprint.testbundlea.ProcessableBean.Phase;
import org.apache.aries.blueprint.testbundleb.OtherBean;
import org.apache.aries.blueprint.testbundleb.TestBean;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.service.blueprint.container.BlueprintContainer;
@RunWith(PaxExam.class)
public class ASMMultiBundleTest extends AbstractBlueprintIntegrationTest {
private void checkInterceptorLog(String []expected, List<String> log){
assertNotNull("interceptor log should not be null",log);
System.out.println("Log:");
for(String entry: log){
System.out.println(""+entry);
}
assertEquals("interceptor log size does not match expected size",expected.length,log.size());
List<String> extra=new ArrayList<String>();
boolean[] found = new boolean[expected.length];
for(String s : log){
boolean used=false;
for(int i=0; i<expected.length; i++){
if(s.startsWith(expected[i])){
found[i]=true;
used=true;
}
}
if(!used){
extra.add(s);
}
}
if(extra.size()!=0){
String extraFormatted="{";
for(String e:extra){
extraFormatted+=e+" ";
}
extraFormatted+="}";
fail("surplus interceptor invocations present in invocation log "+extraFormatted);
}
for(int i=0; i<found.length; i++){
assertTrue("interceptor invocation "+expected[i]+" not found",found[i]);
}
}
// TODO This test seems to fail on some runs. Need to stabilize and reenable
@Test
@Ignore
public void multiBundleTest() throws Exception {
//bundlea provides the ns handlers, bean processors, interceptors etc for this test.
Bundle bundlea = context().getBundleByName("org.apache.aries.blueprint.testbundlea");
assertNotNull(bundlea);
bundlea.start();
//bundleb makes use of the extensions provided by bundlea
Bundle bundleb = context().getBundleByName("org.apache.aries.blueprint.testbundleb");
assertNotNull(bundleb);
bundleb.start();
//bundleb's container will hold the beans we need to query to check the function
//provided by bundlea functioned as expected
BlueprintContainer beanContainer =
Helper.getBlueprintContainerForBundle(context(), "org.apache.aries.blueprint.testbundleb");
assertNotNull(beanContainer);
//TestBeanA should have the values below, no interference should be present from other sources.
Object obj1 = beanContainer.getComponentInstance("TestBeanA");
assertTrue(obj1 instanceof TestBean);
TestBean testBeanA = (TestBean)obj1;
org.junit.Assert.assertEquals("RED", testBeanA.getRed());
org.junit.Assert.assertEquals("GREEN", testBeanA.getGreen());
org.junit.Assert.assertEquals("BLUE", testBeanA.getBlue());
//TestBeanB tests that a custom ns handler is able to inject custom components to the blueprint,
//and modify existing components, and use injected components as modifications.
Object obj2 = beanContainer.getComponentInstance("TestBeanB");
assertTrue(obj2 instanceof TestBean);
TestBean testBeanB = (TestBean)obj2;
//value should be set in via the added passthroughmetadata via the nshandler.
org.junit.Assert.assertEquals("ONE_VALUE", testBeanB.getRed());
org.junit.Assert.assertEquals("GREEN", testBeanB.getGreen());
org.junit.Assert.assertEquals("BLUE", testBeanB.getBlue());
//TestBeanC tests that custom ns handlers can add interceptors to beans.
Object obj3 = beanContainer.getComponentInstance("TestBeanC");
assertTrue(obj3 instanceof TestBean);
TestBean testBeanC = (TestBean)obj3;
//handlers are in bundlea, with its own container.
BlueprintContainer handlerContainer =
Helper.getBlueprintContainerForBundle( context(), "org.apache.aries.blueprint.testbundlea");
assertNotNull(handlerContainer);
Object ns1 = handlerContainer.getComponentInstance("NSHandlerOne");
assertTrue(ns1 instanceof NSHandlerOne);
Object ns2 = handlerContainer.getComponentInstance("NSHandlerTwo");
assertTrue(ns2 instanceof NSHandlerTwo);
NSHandlerTwo nstwo = (NSHandlerTwo)ns2;
//now we have a handle to the nshandler2, we can query what it 'saw', and ensure
//that the interceptors are functioning as expected.
List<String> log = nstwo.getLog();
//TestBeanC has the interceptor configured, and is injected to OtherBeanA & OtherBeanB
//which then uses the injected bean during their init method call, to invoke a method
checkInterceptorLog(new String[] {
"PRECALL:TestBeanC:methodToInvoke:[RED]:",
"POSTCALL[true]:TestBeanC:methodToInvoke:[RED]:",
"PRECALL:TestBeanC:methodToInvoke:[BLUE]:",
"POSTCALL[false]:TestBeanC:methodToInvoke:[BLUE]:"
}, log);
//invoking GREEN is hardwired to cause an exception response, we do this
//from here to ensure the exception occurs and is visible as expected
RuntimeException re=null;
try{
testBeanC.methodToInvoke("GREEN");
}catch(RuntimeException e){
re=e;
}
assertNotNull("invocation of Green did not cause an exception as expected",re);
//Exception responses should be intercepted too, test for the POSTCALLWITHEXCEPTION log entry.
log = nstwo.getLog();
checkInterceptorLog(new String[] {
"PRECALL:TestBeanC:methodToInvoke:[RED]:",
"POSTCALL[true]:TestBeanC:methodToInvoke:[RED]:",
"PRECALL:TestBeanC:methodToInvoke:[BLUE]:",
"POSTCALL[false]:TestBeanC:methodToInvoke:[BLUE]:",
"PRECALL:TestBeanC:methodToInvoke:[GREEN]:",
"POSTCALLEXCEPTION[java.lang.RuntimeException: MATCHED ON GREEN (GREEN)]:TestBeanC:methodToInvoke:[GREEN]:"
}, log);
//ProcessedBean is a test to ensure that BeanProcessors are called..
//The test has the BeanProcessor look for ProcessableBeans, and log itself with them
Object obj4 = beanContainer.getComponentInstance("ProcessedBean");
assertTrue(obj4 instanceof ProcessableBean);
ProcessableBean pb = (ProcessableBean)obj4;
//Note, the BeanProcessor exists in the same container as the beans it processes!!
Object bp = beanContainer.getComponentInstance("http://ns.handler.three/BeanProcessor");
assertNotNull(bp);
assertTrue(bp instanceof BeanProcessor);
assertEquals(1,pb.getProcessedBy().size());
//check we were invoked..
assertEquals(pb.getProcessedBy().get(0),bp);
//check invocation for each phase.
assertEquals(pb.getProcessedBy(Phase.BEFORE_INIT).get(0),bp);
assertEquals(pb.getProcessedBy(Phase.AFTER_INIT).get(0),bp);
//destroy invocation will only occur at tear down.. TODO, how to test after teardown.
//assertEquals(pb.getProcessedBy(Phase.BEFORE_DESTROY).get(0),bp);
//assertEquals(pb.getProcessedBy(Phase.AFTER_DESTROY).get(0),bp);
Object objOther = beanContainer.getComponentInstance("PlaceHolderTestBean");
assertTrue(objOther instanceof OtherBean);
assertEquals("test1value", ((OtherBean)objOther).getTestValue());
}
@Configuration
public Option[] configuration() {
return new Option[] {
baseOptions(),
Helper.blueprintBundles(),
mvnBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundlea", false),
mvnBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundleb", false)
};
}
}