/*
* 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.felix.scr.integration;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.felix.scr.integration.components.annoconfig.AnnoComponent;
import org.apache.felix.scr.integration.components.annoconfig.AnnoComponent.A1;
import org.apache.felix.scr.integration.components.annoconfig.AnnoComponent.A1Arrays;
import org.apache.felix.scr.integration.components.annoconfig.AnnoComponent.E1;
import org.apache.felix.scr.integration.components.annoconfig.NestedAnnoComponent;
import org.apache.felix.scr.integration.components.annoconfig.NestedAnnoComponent.A2;
import org.apache.felix.scr.integration.components.annoconfig.NestedAnnoComponent.B2;
import org.apache.felix.scr.integration.components.annoconfig.NestedAnnoComponent.E2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.service.cm.Configuration;
import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
import junit.framework.TestCase;
@RunWith(PaxExam.class)
public class AnnoConfigTest extends ComponentTestBase
{
static
{
// uncomment to enable debugging of this test class
// paxRunnerVmOption = DEBUG_VM_OPTION;
descriptorFile = "/integration_test_annoconfig.xml";
COMPONENT_PACKAGE = COMPONENT_PACKAGE + ".annoconfig";
}
@Test
public void testAnnoConfig() throws Exception
{
String name = "org.apache.felix.scr.integration.components.annoconfig";
ComponentConfigurationDTO dto = findComponentConfigurationByName(name, ComponentConfigurationDTO.SATISFIED);
AnnoComponent ac = getServiceFromConfiguration(dto, AnnoComponent.class);
checkA1NoValues(ac.m_a1_activate);
checkA1ArraysNoValues(ac.m_a1Arrays_activate);
Configuration c = configure(name, null, allValues());
delay();
checkA1(ac.m_a1_modified);
checkA1Array(ac.m_a1Arrays_modified);
ungetServiceFromConfiguration(dto, AnnoComponent.class);
checkA1(ac.m_a1_deactivate);
checkA1Array(ac.m_a1Arrays_deactivate);
ac = getServiceFromConfiguration(dto, AnnoComponent.class);
checkA1(ac.m_a1_activate);
checkA1Array(ac.m_a1Arrays_activate);
c.delete();
delay();
checkA1NoValues(ac.m_a1_modified);
checkA1ArraysNoValues(ac.m_a1Arrays_modified);
c = configure(name, null, arrayValues());
delay();
checkA1FromArray(ac.m_a1_modified);
checkA1ArrayFromArray(ac.m_a1Arrays_modified, false);
c.delete();
delay();
checkA1NoValues(ac.m_a1_modified);
checkA1ArraysNoValues(ac.m_a1Arrays_modified);
c = configure(name, null, collectionValues());
delay();
checkA1FromArray(ac.m_a1_modified);
checkA1ArrayFromArray(ac.m_a1Arrays_modified, true);
}
private Hashtable<String, Object> allValues()
{
Hashtable<String, Object> values = new Hashtable<String, Object>();
values.put("bool", "true");
values.put("byt", 12l);
values.put("clas", String.class.getName());
values.put("e1", E1.a.toString());
values.put("doubl", "3.14");
values.put("floa", 500l);
values.put("integer", 3.0d);
values.put("lon", "12345678");
values.put("shor", 3l);
values.put("string", 3);
return values;
}
private Hashtable<String, Object> arrayValues()
{
Hashtable<String, Object> values = new Hashtable<String, Object>();
values.put("bool", new boolean[] {true, false});
values.put("byt", new byte[] {12, 3});
values.put("clas", new String[] {String.class.getName(), Integer.class.getName()});
values.put("e1", new String[] {E1.a.name(), E1.b.name()});
values.put("doubl", new double[] {3.14, 2.78, 9});
values.put("floa", new float[] {500, 37.44f});
values.put("integer", new int[] {3, 6, 9});
values.put("lon", new long[] {12345678l, -1});
values.put("shor", new short[] {3, 88});
values.put("string", new String[] {});
return values;
}
private Hashtable<String, Object> collectionValues()
{
Hashtable<String, Object> values = arrayValues();
Hashtable<String, Object> collectionValues = new Hashtable<String, Object>();
for (Map.Entry<String, Object> entry: values.entrySet())
{
collectionValues.put(entry.getKey(), toList(entry.getValue()));
}
//yuck
collectionValues.remove("string");
return collectionValues;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List<?> toList(Object value)
{
List result = new ArrayList();
for (int i = 0; i < Array.getLength(value); i++)
{
result.add(Array.get(value, i));
}
return result;
}
private void checkA1(A1 a)
{
TestCase.assertEquals(true, a.bool());
TestCase.assertEquals((byte)12, a.byt());
TestCase.assertEquals(String.class, a.clas());
TestCase.assertEquals(E1.a, a.e1());
TestCase.assertEquals(3.14d, a.doubl());
TestCase.assertEquals(500f, a.floa());
TestCase.assertEquals(3, a.integer());
TestCase.assertEquals(12345678l, a.lon());
TestCase.assertEquals((short)3, a.shor());
TestCase.assertEquals("3", a.string());
}
private void checkA1FromArray(A1 a)
{
TestCase.assertEquals(true, a.bool());
TestCase.assertEquals((byte)12, a.byt());
TestCase.assertEquals(String.class, a.clas());
TestCase.assertEquals(E1.a, a.e1());
TestCase.assertEquals(3.14d, a.doubl());
TestCase.assertEquals(500f, a.floa());
TestCase.assertEquals(3, a.integer());
TestCase.assertEquals(12345678l, a.lon());
TestCase.assertEquals((short)3, a.shor());
TestCase.assertEquals(null, a.string());
}
private void checkA1Array(A1Arrays a)
{
assertArrayEquals(new boolean[] {true}, a.bool());
assertArrayEquals(new byte[] {(byte)12}, a.byt());
assertArrayEquals(new Class<?>[] {String.class}, a.clas());
assertArrayEquals(new E1[] {E1.a}, a.e1());
assertArrayEquals(new double[] {3.14d}, a.doubl());
assertArrayEquals(new float[] {500f}, a.floa());
assertArrayEquals(new int[] {3}, a.integer());
assertArrayEquals(new long[] {12345678l}, a.lon());
assertArrayEquals(new short[] {(short)3}, a.shor());
assertArrayEquals(new String[] {"3"}, a.string());
}
private void checkA1ArrayFromArray(A1Arrays a, boolean caBug)
{
assertArrayEquals(new boolean[] {true, false}, a.bool());
assertArrayEquals(new byte[] {12, 3}, a.byt());
assertArrayEquals(new Class<?>[] {String.class, Integer.class}, a.clas());
assertArrayEquals(new E1[] {E1.a, E1.b}, a.e1());
assertArrayEquals(new double[] {3.14, 2.78, 9}, a.doubl());
assertArrayEquals(new float[] {500f, 37.44f}, a.floa());
assertArrayEquals(new int[] {3, 6, 9}, a.integer());
assertArrayEquals(new long[] {12345678l, -1}, a.lon());
assertArrayEquals(new short[] {(short)3, 88}, a.shor());
if (!caBug)
{
assertArrayEquals(new String[] {}, a.string());
}
}
private void assertArrayEquals(Object a, Object b)
{
TestCase.assertTrue(a.getClass().isArray());
TestCase.assertTrue(b.getClass().isArray());
TestCase.assertEquals("wrong length", Array.getLength(a), Array.getLength(b));
TestCase.assertEquals("wrong type", a.getClass().getComponentType(), b.getClass().getComponentType());
for (int i = 0; i < Array.getLength(a); i++)
{
TestCase.assertEquals("different value at " + i, Array.get(a, i), Array.get(b, i));
}
}
private void checkA1NoValues(A1 a)
{
TestCase.assertEquals(false, a.bool());
TestCase.assertEquals((byte)0, a.byt());
TestCase.assertEquals(null, a.clas());
TestCase.assertEquals(null, a.e1());
TestCase.assertEquals(0d, a.doubl());
TestCase.assertEquals(0f, a.floa());
TestCase.assertEquals(0, a.integer());
TestCase.assertEquals(0l, a.lon());
TestCase.assertEquals((short)0, a.shor());
TestCase.assertEquals(null, a.string());
}
private void checkA1ArraysNoValues(A1Arrays a)
{
TestCase.assertEquals(0, a.bool().length);
TestCase.assertEquals(0, a.byt().length);
TestCase.assertEquals(0, a.clas().length);
TestCase.assertEquals(0, a.e1().length);
TestCase.assertEquals(0, a.doubl().length);
TestCase.assertEquals(0, a.floa().length);
TestCase.assertEquals(0, a.integer().length);
TestCase.assertEquals(0, a.lon().length);
TestCase.assertEquals(0, a.shor().length);
TestCase.assertEquals(0, a.string().length);
}
@Test
public void testNestedAnnoConfig() throws Exception
{
String name = "org.apache.felix.scr.integration.components.nestedannoconfig";
ComponentConfigurationDTO dto = findComponentConfigurationByName(name, ComponentConfigurationDTO.SATISFIED);
NestedAnnoComponent ac = getServiceFromConfiguration(dto, NestedAnnoComponent.class);
checkA2NoValues(ac.m_a2_activate);
configure(name, null, allNestedValues());
delay();
checkA2(ac.m_a2_modified);
ungetServiceFromConfiguration(dto, NestedAnnoComponent.class);
checkA2(ac.m_a2_deactivate);
ac = getServiceFromConfiguration(dto, NestedAnnoComponent.class);
checkA2(ac.m_a2_activate);
}
private Hashtable<String, Object> allNestedValues()
{
Hashtable<String, Object> values = new Hashtable<String, Object>();
values.put("b2.0.bool", "true");
values.put("b2.0.e2", E2.a.toString());
values.put("b2s.0.bool", "true");
values.put("b2s.0.e2", E2.a.toString());
values.put("b2s.1.bool", "true");
values.put("b2s.1.e2", E2.b.toString());
values.put("b2s.2.bool", "true");
values.put("b2s.2.e2", E2.c.toString());
return values;
}
private void checkA2NoValues(A2 a)
{
TestCase.assertEquals(0, a.b2s().length);
}
private void checkA2(A2 a)
{
checkB2(a.b2(), E2.a);
TestCase.assertNull(a.b2null());
TestCase.assertEquals(3, a.b2s().length);
checkB2(a.b2s()[0], E2.a);
checkB2(a.b2s()[1], E2.b);
checkB2(a.b2s()[2], E2.c);
}
private void checkB2(B2 b, E2 e2) {
TestCase.assertEquals(true, b.bool());
TestCase.assertEquals(e2, b.e2());
}
}