felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject svn commit: r1689973 [3/25] - in /felix/sandbox/pderop/dependencymanager.ds: cnf/ext/ cnf/localrepo/ cnf/localrepo/org.apache.felix.framework/ cnf/releaserepo/ org.apache.felix.dependencymanager.ds.itest/ org.apache.felix.dependencymanager.ds.itest/.se...
Date Wed, 08 Jul 2015 22:10:16 GMT
Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentConfigurationTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentConfigurationTest.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentConfigurationTest.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentConfigurationTest.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,588 @@
+/*
+ * 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.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.apache.felix.scr.integration.components.SimpleServiceImpl;
+import org.junit.Test;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+
+import junit.framework.TestCase;
+
+
+public class ComponentConfigurationTest extends ComponentTestBase
+{
+    @Test
+    public void test_SimpleComponent_configuration_ignore() throws Exception
+    {
+        final String pid = "SimpleComponent.configuration.ignore";
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        deleteConfig( pid );
+        delay();
+
+        ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
+        
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        configure( pid );
+        delay();
+
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        deleteConfig( pid );
+        delay();
+
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        disableAndCheck( cc );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+
+    @Test
+    public void test_SimpleComponent_configuration_optional() throws Exception
+    {
+        final String pid = "SimpleComponent.configuration.optional";
+        ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
+
+        final SimpleComponent firstInstance = SimpleComponent.INSTANCE;
+        TestCase.assertNotNull( firstInstance );
+        TestCase.assertNull( firstInstance.getProperty( PROP_NAME ) );
+
+        configure( pid );
+        delay();
+
+        final SimpleComponent secondInstance = SimpleComponent.INSTANCE;
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNotNull( secondInstance );
+        TestCase.assertEquals( PROP_NAME, secondInstance.getProperty( PROP_NAME ) );
+
+        deleteConfig( pid );
+        delay();
+
+        final SimpleComponent thirdInstance = SimpleComponent.INSTANCE;
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNotNull( thirdInstance );
+        TestCase.assertNull( thirdInstance.getProperty( PROP_NAME ) );
+
+        TestCase.assertNotSame( "Expect new instance object after reconfiguration", firstInstance, secondInstance );
+        TestCase.assertNotSame( "Expect new instance object after configuration deletion (1)", firstInstance,
+            thirdInstance );
+        TestCase.assertNotSame( "Expect new instance object after configuration deletion (2)", secondInstance,
+            thirdInstance );
+
+        disableAndCheck( cc );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+
+    @Test
+    public void test_SimpleComponent_configuration_require() throws Exception
+    {
+        final String pid = "SimpleComponent.configuration.require";
+
+        deleteConfig( pid );
+        delay();
+        
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        getConfigurationsDisabledThenEnable(pid, 0, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        configure( pid );
+        delay();
+
+        ComponentConfigurationDTO cc = findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        deleteConfig( pid );
+        delay();
+
+        checkConfigurationCount(pid, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        disableAndCheck( cc );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+    /**
+     * same as test_SimpleComponent_configuration_require except configuration is present when component is enabled.
+     */
+    @Test
+    public void test_SimpleComponent_configuration_require_initialize() throws Exception
+    {
+        final String pid = "SimpleComponent.configuration.require";
+
+        deleteConfig( pid );
+        configure( pid );
+        delay();
+        
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        ComponentConfigurationDTO cc = getConfigurationsDisabledThenEnable(pid, 1, ComponentConfigurationDTO.ACTIVE).iterator().next();
+
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        deleteConfig( pid );
+        delay();
+
+        checkConfigurationCount(pid, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        disableAndCheck( cc );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+
+    @Test
+    public void test_SimpleComponent_dynamic_configuration() throws Exception
+    {
+        final String pid = "DynamicConfigurationComponent";
+        boolean pre13 = true;
+        boolean recreateOnDelete = true;
+        dynamicConfigTest(pid, pre13, recreateOnDelete);
+    }
+
+    @Test
+    public void test_SimpleComponent_dynamic_configuration_13() throws Exception
+    {
+        final String pid = "DynamicConfigurationComponent13";
+        boolean pre13 = false;
+        boolean recreateOnDelete = false;
+        dynamicConfigTest(pid, pre13, recreateOnDelete);
+    }
+    
+    @Test
+    public void test_SimpleComponent_dynamic_configuration_flag() throws Exception
+    {
+        final String pid = "DynamicConfigurationComponentFlag";
+        boolean pre13 = true;
+        boolean recreateOnDelete = false;
+        dynamicConfigTest(pid, pre13, recreateOnDelete);
+    }
+
+
+	private void dynamicConfigTest(final String pid, boolean pre13, boolean recreateOnDelete)  throws Exception
+	{
+	    Object pidWithout;
+	    Object pidWith;
+	    if (pre13)
+	    {
+	        pidWithout = pid + ".description";
+	        pidWith = pid;
+	    }
+	    else 
+	    {
+	        pidWithout = pid + ".description";
+	        pidWith = Arrays.asList(new String[] {pid + ".description", pid});
+	    }
+        deleteConfig( pid );
+        delay();
+
+        ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
+
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+        TestCase.assertEquals(pidWithout, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
+
+        final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+        configure( pid );
+        delay();
+
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+        TestCase.assertEquals(pidWith, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
+
+        deleteConfig( pid );
+        delay();
+
+        findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+        if (recreateOnDelete)
+        {
+            TestCase.assertNotSame( instance, SimpleComponent.INSTANCE );
+        }
+        else
+        {
+            TestCase.assertSame( instance, SimpleComponent.INSTANCE );
+        }
+        TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+        TestCase.assertEquals(pidWithout, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
+
+        disableAndCheck( cc );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+	}
+
+
+    @Test
+    public void test_SimpleComponent_dynamic_optional_configuration_with_required_service() throws Exception
+    {
+        final String targetProp = "ref.target";
+        final String filterProp = "required";
+        final SimpleServiceImpl service = SimpleServiceImpl.create( bundleContext, "sample" ).setFilterProperty( filterProp );
+        try
+        {
+            final String pid = "DynamicConfigurationComponentWithRequiredReference";
+            deleteConfig( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            // dynamically configure without the correct target
+            configure( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            // dynamically configure with correct target
+            theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
+            configure( pid );
+            delay();
+
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertNotNull( SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+
+            final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+            configure( pid );
+            delay();
+
+            // same instance after reconfiguration
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // reconfigure without target --> unsatisifed
+            theConfig.remove( targetProp );
+            configure( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            deleteConfig( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            disableAndCheck(cc);
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+        }
+        finally
+        {
+            theConfig.remove( targetProp );
+            if ( service != null )
+            {
+                service.drop();
+            }
+        }
+    }
+
+    /**
+     * FELIX-3902.  Start with filter matching two services, remove one, then change the filter
+     * to (still) match the other one.  2nd service should remain bound.
+     */
+    @Test
+    public void test_SimpleComponent_dynamic_optional_configuration_with_required_service2() throws Exception
+    {
+        final String targetProp = "ref.target";
+        final String filterProp1 = "one";
+        final String filterProp2 = "two";
+        final SimpleServiceImpl service1 = SimpleServiceImpl.create( bundleContext, "one", 1 ).setFilterProperty( filterProp1 );
+        final SimpleServiceImpl service2 = SimpleServiceImpl.create( bundleContext, "two", 2 ).setFilterProperty( filterProp2 );
+        try
+        {
+            final String pid = "DynamicConfigurationComponentWithRequiredReference";
+            deleteConfig( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            // dynamically configure without the correct target
+            configure( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            // dynamically configure with correct target
+            theConfig.put( targetProp, "(|(filterprop=" + filterProp1 + ")(filterprop=" + filterProp2 + "))" );
+            configure( pid );
+            delay();
+
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertNotNull( SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+
+            final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+            configure( pid );
+            delay();
+
+            //remove higher ranked service
+            if (service2 != null)
+            {
+                service2.drop();
+            }
+             // same instance after reconfiguration
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // reconfigure with new filter --> active
+            theConfig.put( targetProp, "(filterprop=" + filterProp1 + ")" );
+            configure( pid );
+            delay();
+
+            // same instance after reconfiguration
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            deleteConfig( pid );
+            delay();
+
+            // mandatory ref missing --> component unsatisfied
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+            disableAndCheck(cc);
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+        }
+        finally
+        {
+            theConfig.remove( targetProp );
+            if ( service1 != null )
+            {
+                service1.drop();
+            }
+        }
+    }
+
+    @Test
+    public void test_SimpleComponent_dynamic_optional_configuration_with_optional_service() throws Exception
+    {
+        final String targetProp = "ref.target";
+        final String filterProp = "required";
+        final SimpleServiceImpl service = SimpleServiceImpl.create( bundleContext, "sample" ).setFilterProperty( filterProp );
+        try
+        {
+            final String pid = "DynamicConfigurationComponentWithOptionalReference";
+            deleteConfig( pid );
+            delay();
+
+            // optional ref missing --> component active
+            ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
+
+            TestCase.assertNotNull( SimpleComponent.INSTANCE );
+            final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+            // dynamically configure without the correct target
+            configure( pid );
+            delay();
+
+            // optional ref missing --> component active
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // dynamically configure with correct target
+            theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
+            configure( pid );
+            delay();
+
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            configure( pid );
+            delay();
+
+            // same instance after reconfiguration
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // reconfigure without target --> active
+            theConfig.remove( targetProp );
+            configure( pid );
+            delay();
+
+            // optional ref missing --> component active
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            deleteConfig( pid );
+            delay();
+
+            // optional ref missing --> component active
+            findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
+            TestCase.assertNotSame( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            disableAndCheck(cc);
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+        }
+        finally
+        {
+//            Thread.sleep( 60000 );
+            theConfig.remove( targetProp );
+            if ( service != null )
+            {
+                service.drop();
+            }
+        }
+    }
+
+
+    @Test
+    public void test_SimpleComponent_factory_configuration() throws Exception
+    {
+        final String factoryPid = "FactoryConfigurationComponent";
+
+        deleteFactoryConfigurations( factoryPid );
+        delay();
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(factoryPid, 0, -1);
+        TestCase.assertTrue( SimpleComponent.INSTANCES.isEmpty() );
+
+        // create two factory configurations expecting two components
+        final String pid0 = createFactoryConfiguration( factoryPid );
+        final String pid1 = createFactoryConfiguration( factoryPid );
+        delay();
+
+        // expect two active components, //TODO WTF?? only first is active, second is disabled
+        checkConfigurationCount(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
+        // delete a configuration
+        deleteConfig( pid0 );
+        delay();
+
+        // expect one component
+        checkConfigurationCount(factoryPid, 1, ComponentConfigurationDTO.ACTIVE);
+
+        // delete second configuration
+        deleteConfig( pid1 );
+        delay();
+
+        checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
+        disableAndCheck(confs);
+    }
+
+    /**
+     * same as test_SimpleComponent_factory_configuration except configurations are present before 
+     * component is enabled to test initialization.
+     */
+    @Test
+    public void test_SimpleComponent_factory_configuration_initialize() throws Exception
+    {
+        final String factoryPid = "FactoryConfigurationComponent";
+
+        deleteFactoryConfigurations( factoryPid );
+
+        // create two factory configurations expecting two components
+        final String pid0 = createFactoryConfiguration( factoryPid );
+        final String pid1 = createFactoryConfiguration( factoryPid );
+        delay();
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
+
+        // delete a configuration
+        deleteConfig( pid0 );
+        delay();
+
+        // expect one component
+        checkConfigurationCount(factoryPid, 1, ComponentConfigurationDTO.ACTIVE);
+
+        // delete second configuration
+        deleteConfig( pid1 );
+        delay();
+
+        checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
+        disableAndCheck(confs);
+    }
+
+    @Test
+    public void test_SimpleComponent_factory_configuration_enabled() throws Exception
+    {
+        final String factoryPid = "FactoryConfigurationComponent_enabled";
+
+        deleteFactoryConfigurations( factoryPid );
+        delay();
+
+        checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
+        // no component config exists without configuration
+
+        // create two factory configurations expecting two components
+        final String pid0 = createFactoryConfiguration( factoryPid );
+        final String pid1 = createFactoryConfiguration( factoryPid );
+        delay();
+
+        // expect two components, all active
+        checkConfigurationCount(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
+
+        // disable the name component
+        disableAndCheck( factoryPid );
+        delay();
+
+
+        // create a configuration
+        final String pid3 = createFactoryConfiguration( factoryPid );
+        delay();
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(factoryPid, 3, ComponentConfigurationDTO.ACTIVE);
+        deleteFactoryConfigurations( factoryPid );
+        for (ComponentConfigurationDTO conf : confs) {
+            disableAndCheck(conf);
+        }
+    }
+
+
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentDisposeTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentDisposeTest.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentDisposeTest.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentDisposeTest.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,77 @@
+/*
+ * 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.util.Collection;
+
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.junit.Test;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+
+public class ComponentDisposeTest extends ComponentTestBase
+{
+    @Test
+    public void test_SimpleComponent_factory_configuration() throws Exception
+    {
+        final String factoryPid = "FactoryConfigurationComponent";
+
+        deleteFactoryConfigurations( factoryPid );
+        delay();
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);//there should be none
+
+        // create two factory configurations expecting two components
+        final String pid0 = createFactoryConfiguration( factoryPid );
+        final String pid1 = createFactoryConfiguration( factoryPid );
+        delay();
+
+        Collection<ComponentConfigurationDTO> ccs = findComponentConfigurationsByName(factoryPid, ComponentConfigurationDTO.ACTIVE);
+		Assert.assertEquals(2, ccs.size());
+        // expect two components, only first is active, second is disabled
+        TestCase.assertEquals( 2, SimpleComponent.INSTANCES.size() );
+        for (ComponentConfigurationDTO cc: ccs)
+        {
+        	TestCase.assertTrue(SimpleComponent.INSTANCES.containsKey(cc.id));
+        }
+
+        // dispose an instance
+        final SimpleComponent anInstance = SimpleComponent.INSTANCE;
+        TestCase.assertNotNull( anInstance );
+        TestCase.assertNotNull( anInstance.m_activateContext );
+        anInstance.m_activateContext.getComponentInstance().dispose();
+        delay();
+
+        // expect one component
+        ComponentConfigurationDTO cc = findComponentConfigurationByName(factoryPid, ComponentConfigurationDTO.ACTIVE);
+
+        TestCase.assertEquals( 1, SimpleComponent.INSTANCES.size() );
+    	TestCase.assertTrue(SimpleComponent.INSTANCES.containsKey(cc.id));
+
+        final SimpleComponent instance = SimpleComponent.INSTANCES.values().iterator().next();
+        disableAndCheck(confs);
+        deleteFactoryConfigurations(factoryPid);
+    }
+
+
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentEnableTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentEnableTest.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentEnableTest.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentEnableTest.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,59 @@
+/*
+ * 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 org.apache.felix.scr.integration.components.EnableComponent;
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.junit.Test;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+
+import junit.framework.TestCase;
+
+
+public class ComponentEnableTest extends ComponentTestBase
+{
+    public ComponentEnableTest()
+    {
+        super("/resource/integration_test_enable.xml");
+    }
+
+    @Test
+    public void test_Component_Enable() throws Exception
+    {
+        final String enable = "org.apache.felix.scr.integration.components.enable";
+        final String name = "org.apache.felix.scr.integration.components.SimpleComponent";
+        
+        ComponentConfigurationDTO dto = findComponentConfigurationByName(enable, ComponentConfigurationDTO.SATISFIED);
+        
+        EnableComponent ec = getServiceFromConfiguration(dto, EnableComponent.class);
+        
+        TestCase.assertEquals(0, SimpleComponent.INSTANCES.size());
+
+        ec.enable(name);
+        delay();
+        TestCase.assertEquals(1, SimpleComponent.INSTANCES.size());
+        ec.enable(name);
+        delay();
+        TestCase.assertEquals(1, SimpleComponent.INSTANCES.size());
+
+    }
+
+
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentFactoryTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentFactoryTest.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentFactoryTest.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentFactoryTest.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,434 @@
+/*
+ * 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.InvocationTargetException;
+import java.util.Collection;
+import java.util.Hashtable;
+
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.apache.felix.scr.integration.components.SimpleService;
+import org.apache.felix.scr.integration.components.SimpleServiceImpl;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentException;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.log.LogService;
+
+import junit.framework.TestCase;
+
+
+public class ComponentFactoryTest extends ComponentTestBase
+{
+    public ComponentFactoryTest() 
+    {
+        super("/resource/integration_test_simple_factory_components.xml");
+        ignoredWarnings = new String[] {
+          "ComponentFactoryTest: Bound Services=\\[SimpleServiceImpl: value=service2, filterprop=match\\]",
+          "\\[factory.component.*\\] The activate method has thrown an exception\\njava.lang.RuntimeException: Requested Failure",
+          "\\[factory.component.*\\] Failed creating the component instance; see log for reason"
+        };
+    }
+
+    @Test
+    public void test_component_factory() throws Exception
+    {
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 0, -1);
+
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ComponentInstance instance = createFactoryComponentInstance(componentfactory);
+
+        // check registered components
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+        
+        checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);
+        disableAndCheck(confs);        
+    }
+
+
+    @Test
+    public void test_component_factory_disable_factory() throws Exception
+    {
+        // tests components remain alive after factory has been disabled
+
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 0, -1);
+
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ComponentInstance instance = createFactoryComponentInstance(componentfactory);
+
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        // disable the factory
+        disableAndCheck(componentname);
+        delay();
+
+        // factory is disabled but the instance is still alive
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+        disableAndCheck(confs);        
+    }
+
+
+    @Test
+    public void test_component_factory_newInstance_failure() throws Exception
+    {
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        try
+        {
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+            props.put( SimpleComponent.PROP_ACTIVATE_FAILURE, "Requested Failure" );
+            createFactoryComponentInstance(componentfactory, props);
+            TestCase.fail( "Expected newInstance method to fail with ComponentException" );
+        }
+        catch ( ComponentException ce )
+        {
+            // this is expected !
+        }
+
+        checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);
+        disableAndCheck(confs);
+    }
+
+
+    @Test
+    public void test_component_factory_require_configuration() throws Exception
+    {
+        final String componentname = "factory.component.configuration";
+        final String componentfactory = "factory.component.factory.configuration";
+
+        testConfiguredFactory(componentname, componentfactory, false, false);        
+    }
+
+    @Test
+    public void test_component_factory_require_configuration_obsolete() throws Exception
+    {
+        final String componentname = "factory.component.configuration.obsolete";
+
+        TestCase.assertNull(SimpleComponent.INSTANCE);
+
+        createFactoryConfiguration(componentname);
+        delay();
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertEquals(PROP_NAME, SimpleComponent.INSTANCE.getProperty(PROP_NAME));
+        disableAndCheck(confs);
+        deleteFactoryConfigurations(componentname);
+    }
+
+    @Test
+    public void test_component_factory_optional_configuration() throws Exception
+    {
+        final String componentname = "factory.component.configuration.optional";
+        final String componentfactory = "factory.component.factory.configuration.optional";
+
+        testConfiguredFactory(componentname, componentfactory, true, false);
+    }
+
+    @Test
+    public void test_component_factory_optional_configuration_13() throws Exception
+    {
+        final String componentname = "factory.component.configuration.optional.13";
+        final String componentfactory = "factory.component.factory.configuration.optional.13";
+
+        testConfiguredFactory(componentname, componentfactory, true, true);
+    }
+
+    @Test
+    public void test_component_factory_optional_configuration_nomodify() throws Exception
+    {
+        final String componentname = "factory.component.configuration.optional.nomodify";
+        final String componentfactory = "factory.component.factory.configuration.optional.nomodify";
+
+        testConfiguredFactory(componentname, componentfactory, true, false);
+    }
+
+
+    private void testConfiguredFactory(final String componentname,
+        final String componentfactory, boolean optional, boolean expectComponent) throws InvocationTargetException,
+        InterruptedException, InvalidSyntaxException
+    {
+        // ensure there is no configuration for the component
+        deleteConfig( componentname );
+        delay();
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // At this point, since we don't have created the configuration, then the ComponentFactory
+        // should not be available.
+        
+        checkFactory(componentfactory, optional);
+        
+        // supply configuration now and ensure active
+        configure( componentname );
+        delay();        
+
+        checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // get the component factory service
+        final ComponentInstance instance = createFactoryComponentInstance(componentfactory);
+
+        final Object instanceObject = instance.getInstance();
+        TestCase.assertNotNull( instanceObject );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instanceObject );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );                        
+
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        // delete config, ensure factory is not active anymore and component instance gone 
+        //(configuration required >> dispose of instance.  Also for pre-1.3 components, removing config unconditionally
+        //deactivates component.
+        deleteConfig( componentname );
+        delay();
+
+        checkFactory(componentfactory, optional);
+
+        if (expectComponent) 
+        {
+            TestCase.assertNotNull( instance.getInstance() );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE );
+
+            // with removal of the factory, the created instance should also be removed
+            checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);            
+        }
+        else
+        {
+            TestCase.assertNull( instance.getInstance() );
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+
+            // with removal of the factory, the created instance should also be removed
+            checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);            
+        }
+        disableAndCheck(confs);
+        instance.dispose();
+    }
+
+
+    @Test
+    public void test_component_factory_reference() throws Exception
+    {
+        final String componentname = "factory.component.reference";
+        final String componentfactory = "factory.component.factory.reference";
+
+        SimpleServiceImpl simpleService = SimpleServiceImpl.create( bundleContext, "ignored" ).setFilterProperty( "ignored" );
+
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentname, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // register a service : filterprop=match
+        SimpleServiceImpl match = SimpleServiceImpl.create( bundleContext, "required" ).setFilterProperty( "required" );
+        delay();
+
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ComponentInstance instance = createFactoryComponentInstance(componentfactory);
+        TestCase.assertEquals( 1, SimpleComponent.INSTANCE.m_multiRef.size() );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( match ) );
+
+        // check registered components
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+        checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);
+
+
+        // overwritten filterprop
+        Hashtable<String, String> propsNonMatch = new Hashtable<String, String>();
+        propsNonMatch.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        propsNonMatch.put( "ref.target", "(filterprop=nomatch)" );
+        ComponentFactory factory = getComponentFactory(componentfactory);
+        try
+        {
+            factory.newInstance( propsNonMatch );
+            TestCase.fail( "Missing reference must fail instance creation" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expected
+        }
+
+        final SimpleServiceImpl noMatch = SimpleServiceImpl.create( bundleContext, "nomatch" ).setFilterProperty(
+            "nomatch" );
+        delay();
+
+        final ComponentInstance instanceNonMatch = factory.newInstance( propsNonMatch );
+
+        TestCase.assertNotNull( instanceNonMatch );
+
+        TestCase.assertNotNull( instanceNonMatch.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instanceNonMatch.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+
+        TestCase.assertEquals( 1, SimpleComponent.INSTANCE.m_multiRef.size() );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( noMatch ) );
+
+        // check registered components
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        match.getRegistration().unregister();
+        delay();
+
+        // check registered components (ComponentFactory aint no longer)
+        checkConfigurationCount(componentname, 1, ComponentConfigurationDTO.ACTIVE);
+
+        //it has already been deactivated.... this should cause an exception?
+        noMatch.getRegistration().unregister();
+        delay();
+
+        // check registered components (ComponentFactory aint no longer)
+        checkConfigurationCount(componentname, 0, ComponentConfigurationDTO.ACTIVE);
+
+        // deactivated due to unsatisfied reference
+        TestCase.assertNull( instanceNonMatch.getInstance() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        //Check that calling dispose on a deactivated instance has no effect
+        instanceNonMatch.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instanceNonMatch.getInstance() ); // SCR 112.12.6.2
+        disableAndCheck(confs);
+        simpleService.drop();
+    }
+
+    @Test
+    public void test_component_factory_referredTo() throws Exception
+    {
+        //set up the component that refers to the service the factory will create.
+        final String referringComponentName = "ComponentReferringToFactoryObject";
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(referringComponentName, 1, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+
+        final String componentname = "factory.component.referred";
+        final String componentfactory = "factory.component.factory.referred";
+
+        getConfigurationsDisabledThenEnable(componentname, 0, -1);
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( "service.pid", "myFactoryInstance" );
+        final ComponentFactory factory = getComponentFactory(componentfactory);
+
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertTrue( instance.getInstance() instanceof SimpleService );
+        //The referring service should now be active
+        checkConfigurationCount(referringComponentName, 1, ComponentConfigurationDTO.ACTIVE);
+
+        instance.dispose();
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        //make sure it's unsatisfied (service is no longer available)
+        checkConfigurationCount(referringComponentName, 1, ComponentConfigurationDTO.UNSATISFIED_REFERENCE);
+        disableAndCheck(confs);
+    }
+
+    @Test
+    public void test_component_factory_with_target_filters() throws Exception
+    {
+        final String componentfactory = "factory.component.reference.targetfilter";
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentfactory, 0, -1);
+
+        SimpleServiceImpl s1 = SimpleServiceImpl.create(bundleContext, "service1");
+        SimpleServiceImpl s2 = SimpleServiceImpl.create(bundleContext, "service2");
+
+        // supply configuration now and ensure active
+        Configuration conf = configure( componentfactory );
+        delay();        
+
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        props.put("ref.target", "(value=service2)");
+        final ComponentInstance instance = createFactoryComponentInstance(componentfactory, props);
+
+        log.log(LogService.LOG_WARNING, "ComponentFactoryTest: Bound Services=" +  SimpleComponent.INSTANCE.m_multiRef);
+        TestCase.assertFalse( SimpleComponent.INSTANCE.m_multiRef.contains( s1 ) );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( s2 ) );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+        
+        s2.drop();
+        s1.drop();
+        conf.delete();
+        disableAndCheck(confs);
+    }
+    
+    @Test
+    public void test_component_factory_set_bundle_location_null() throws Exception
+    {
+        final String componentfactory = "factory.component.reference.targetfilter";
+        Collection<ComponentConfigurationDTO> confs = getConfigurationsDisabledThenEnable(componentfactory, 0, -1);
+        SimpleServiceImpl s1 = SimpleServiceImpl.create(bundleContext, "service1");
+
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        org.osgi.service.cm.Configuration config = ca.getConfiguration( componentfactory, null );
+        config.setBundleLocation( null );
+        delay();
+        if ( isAtLeastR5() )
+        {
+            //check that ConfigurationSupport got a Location changed event and set the bundle location
+            TestCase.assertNotNull( config.getBundleLocation() );
+        } 
+        // supply configuration now and ensure active
+        configure( componentfactory );
+        delay();        
+
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        
+        final ComponentFactory factory = getComponentFactory(componentfactory);
+        
+        disableAndCheck(confs);
+        s1.drop();
+        config.delete();
+    }
+    
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentTestBase.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentTestBase.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentTestBase.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds.itest/src/org/apache/felix/scr/integration/ComponentTestBase.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,1098 @@
+/*
+ * 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 static java.lang.System.err;
+import static java.lang.System.out;
+
+import java.io.BufferedOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.felix.scr.integration.components.Felix4350Component;
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.junit.After;
+import org.junit.Before;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.namespace.extender.ExtenderNamespace;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public abstract class ComponentTestBase extends TestCase
+{
+    // Injected
+    protected BundleContext bundleContext;
+    
+    // Our integration test bundle
+    protected Bundle bundle;
+    
+    protected ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime> scrTracker;
+
+    protected ServiceTracker<ConfigurationAdmin, ConfigurationAdmin> configAdminTracker;
+
+    // the name of the system property providing the bundle file to be installed and tested
+    protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";
+
+    // the default bundle jar file name
+    protected static final String BUNDLE_JAR_DEFAULT = "target/scr.jar";
+
+    protected static final String PROP_NAME = "theValue";
+    protected static final Hashtable<String, Object> theConfig = new Hashtable<>();
+
+    // the JVM option to set to enable remote debugging
+    protected static final String DEBUG_VM_OPTION = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=30303";
+
+    // the actual JVM option set, extensions may implement a static
+    // initializer overwriting this value to have the configuration()
+    // method include it when starting the OSGi framework JVM
+    protected static String paxRunnerVmOption = null;
+
+    protected String DS_LOGLEVEL = "warn";
+
+    protected static String bsnVersionUniqueness = "single";
+
+    // the descriptor file to use for the installed test bundle
+    protected String descriptorFile = "/resource/integration_test_simple_components.xml";
+    protected String COMPONENT_PACKAGE = "org.apache.felix.scr.integration.components";
+
+
+    protected static boolean NONSTANDARD_COMPONENT_FACTORY_BEHAVIOR = false;
+    protected volatile Log log;
+
+    private ServiceRegistration<?> logService;
+
+    private final Set<ServiceReference> existingServices = new HashSet<>();
+    private final Set<Configuration> existingConfigurations = new HashSet<>();
+
+	protected String[] ignoredWarnings; //null unless you need it.
+
+    //set to true to only get last 1000 lines of log.
+    protected boolean restrictedLogging;
+
+    protected static String felixCaVersion = System.getProperty( "felix.ca.version" );
+
+    protected static final String PROP_NAME_FACTORY = ComponentTestBase.PROP_NAME + ".factory";
+
+
+    public ComponentTestBase()
+    {
+        // Will use by default this.descriptorFile and this.COMPONENT_PACKAGE
+    }
+
+    public ComponentTestBase(String descriptorFile) 
+    {
+        this.descriptorFile = descriptorFile;
+        // Will use by default this.COMPONENT_PACKAGE
+    }
+
+    public ComponentTestBase(String descriptorFile, String componentPackage)
+    {
+        this.descriptorFile = descriptorFile;
+        this.COMPONENT_PACKAGE = COMPONENT_PACKAGE + "." + componentPackage;
+    }
+
+    @Before
+    public void setUp() throws BundleException, IOException
+    {
+        bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        init();
+
+        log = new Log(restrictedLogging, ignoredWarnings);
+        log.start();
+        bundleContext.addFrameworkListener( log );
+        logService = bundleContext.registerService( LogService.class.getName(), log, null );
+
+        scrTracker = new ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime>( bundleContext, ServiceComponentRuntime.class, null );
+        scrTracker.open();
+        configAdminTracker = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>( bundleContext, ConfigurationAdmin.class, null );
+        configAdminTracker.open();
+        
+        out.println("Running " + getClass().getName() + "." + super.getName());
+        bundle = installBundle( descriptorFile, COMPONENT_PACKAGE );
+        bundle.start();
+
+        recordExistingConfigurations();
+    }
+
+
+    @After
+    public void tearDown() throws BundleException, InterruptedException
+    {
+        boolean foundWarnings = false;
+        try
+        {
+            // Check if the bundle has cleaned of configuration it may have created.
+            checkConfigurationCleaned();
+
+            if ( bundle != null && bundle.getState() != Bundle.UNINSTALLED )
+            {
+                bundle.stop();
+                bundle.uninstall();
+                bundle = null;
+            }
+            
+            Bundle scrBundle = scrTracker.getServiceReference().getBundle();
+            scrBundle.stop();
+            scrBundle.start();
+
+            configAdminTracker.close();
+            configAdminTracker = null;
+            scrTracker.close();
+            scrTracker = null;
+            logService.unregister();
+            bundleContext.removeFrameworkListener( log );
+        }
+        finally
+        {
+            foundWarnings = log.stop();
+        }
+        
+        if (foundWarnings)
+        {
+            TestCase.fail("Test failed (see previous warnings).");
+        }        
+
+    }
+
+    protected Collection<ComponentDescriptionDTO> getComponentDescriptions()
+    {
+        ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr == null )
+        {
+        	TestCase.fail("no ServiceComponentRuntime");
+        }
+            return scr.getComponentDescriptionDTOs();
+    }
+
+
+    protected ComponentDescriptionDTO findComponentDescriptorByName( String name )
+    {
+        ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr == null )
+        {
+        	TestCase.fail("no ServiceComponentRuntime");
+        }
+            return scr.getComponentDescriptionDTO(bundle, name);
+    }
+
+
+    protected Collection<ComponentConfigurationDTO> findComponentConfigurationsByName( Bundle b, String name, int expected )
+    {
+        ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr == null )
+        {
+        	TestCase.fail("no ServiceComponentRuntime");
+        }
+        ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO(b, name);
+        Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs(cd);
+        if (expected != -1)
+        {
+        	for (ComponentConfigurationDTO cc: ccs)
+        	{
+        		Assert.assertEquals( "for ComponentConfiguration name: " + cc.description.name + " properties" + cc.properties + "Expected state " + STATES.get(expected) + " but was " + STATES.get(cc.state), expected, cc.state);
+        	}
+        }
+        return ccs;
+    }
+
+    protected Collection<ComponentConfigurationDTO> findComponentConfigurationsByName( String name, int expected )
+    {
+    	return findComponentConfigurationsByName(bundle, name, expected);
+    }
+
+    protected ComponentConfigurationDTO findComponentConfigurationByName( Bundle b, String name, int expected )
+    {
+    	Collection<ComponentConfigurationDTO> ccs = findComponentConfigurationsByName( b, name, expected);
+    	Assert.assertEquals(1, ccs.size());
+    	return ccs.iterator().next();
+    }
+
+    protected ComponentConfigurationDTO findComponentConfigurationByName( String name, int expected )
+    {
+    	return findComponentConfigurationByName( bundle, name, expected );
+    }
+
+    static final Map<Integer, String> STATES = new HashMap<Integer, String>();
+
+    static {
+    	STATES.put(ComponentConfigurationDTO.UNSATISFIED_REFERENCE, "Unsatisfied (" + ComponentConfigurationDTO.UNSATISFIED_REFERENCE + ")" );
+    	STATES.put(ComponentConfigurationDTO.SATISFIED, "Satisified (" + ComponentConfigurationDTO.SATISFIED + ")" );
+    	STATES.put(ComponentConfigurationDTO.ACTIVE, "Active (" + ComponentConfigurationDTO.ACTIVE + ")" );
+    }
+
+    protected ComponentConfigurationDTO getDisabledConfigurationAndEnable( Bundle b, String name, int initialState ) throws InvocationTargetException, InterruptedException
+    {
+    	int count = 1;
+        Collection<ComponentConfigurationDTO> ccs = getConfigurationsDisabledThenEnable(
+				b, name, count, initialState);
+		ComponentConfigurationDTO cc = ccs.iterator().next();
+    	return cc;
+    }
+
+    protected ComponentConfigurationDTO getDisabledConfigurationAndEnable( String name, int initialState ) throws InvocationTargetException, InterruptedException
+    {
+    	return getDisabledConfigurationAndEnable( bundle, name, initialState );
+    }
+
+    protected Collection<ComponentConfigurationDTO> getConfigurationsDisabledThenEnable( Bundle b, String name, int count, int initialState) throws InvocationTargetException, InterruptedException
+    {
+		ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr == null )
+        {
+        	TestCase.fail("no ServiceComponentRuntime");
+        }
+    	ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO(b, name);
+    	Assert.assertFalse("Expected component disabled", scr.isComponentEnabled(cd));
+    	scr.enableComponent(cd).getValue();
+    	Assert.assertTrue("Expected component enabled", scr.isComponentEnabled(cd));
+
+    	Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs(cd);
+    	Assert.assertEquals(count, ccs.size());
+    	for (ComponentConfigurationDTO cc: ccs) {
+			Assert.assertEquals("Expected state " + STATES.get(initialState)
+					+ " but was " + STATES.get(cc.state), initialState,
+					cc.state);
+		}
+		return ccs;
+	}
+
+    protected Collection<ComponentConfigurationDTO> getConfigurationsDisabledThenEnable( String name, int count, int initialState) throws InvocationTargetException, InterruptedException
+    {
+    	return getConfigurationsDisabledThenEnable(bundle, name, count, initialState);
+    }
+
+    protected ComponentDescriptionDTO checkConfigurationCount( Bundle b, String name, int count, int expectedState )
+    {
+    	ServiceComponentRuntime scr = scrTracker.getService();
+    	if ( scr == null )
+    	{
+    		TestCase.fail("no ServiceComponentRuntime");
+    	}
+    	ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO(b, name);
+    	Assert.assertTrue("Expected component enabled", scr.isComponentEnabled(cd));
+
+    	Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs(cd);
+    	Assert.assertEquals(count, ccs.size());
+    	if (expectedState != -1)
+    	{
+    		for (ComponentConfigurationDTO cc: ccs)
+    		{
+    			Assert.assertEquals("Expected state " + STATES.get(expectedState)
+    					+ " but was " + STATES.get(cc.state), expectedState,
+    					cc.state);
+    		}
+    	}
+    	return cd;
+    }
+
+    protected ComponentDescriptionDTO checkConfigurationCount( String name, int count, int expectedState )
+    {
+    	return checkConfigurationCount(bundle, name, count, expectedState);
+    }
+
+    protected <S> S getServiceFromConfiguration( ComponentConfigurationDTO dto, Class<S> clazz )
+    {
+        long id = dto.id;
+        String filter = "(component.id=" + id + ")";
+        Collection<ServiceReference<S>> srs;
+        try {
+            srs = bundleContext.getServiceReferences(clazz, filter);
+            Assert.assertEquals(1, srs.size());
+            ServiceReference<S> sr = srs.iterator().next();
+            S s = bundleContext.getService(sr);
+            Assert.assertNotNull(s);
+            return s;
+        } catch (InvalidSyntaxException e) {
+            TestCase.fail(e.getMessage());
+            return null;//unreachable in fact
+        }
+    }
+    
+    protected <S> void ungetServiceFromConfiguration( ComponentConfigurationDTO dto, Class<S> clazz )
+    {
+        long id = dto.id;
+        String filter = "(component.id=" + id + ")";
+        Collection<ServiceReference<S>> srs;
+        try {
+            srs = bundleContext.getServiceReferences(clazz, filter);
+            Assert.assertEquals(1, srs.size());
+            ServiceReference<S> sr = srs.iterator().next();
+            bundleContext.ungetService(sr);
+        } catch (InvalidSyntaxException e) {
+            TestCase.fail(e.getMessage());
+        }
+    }
+
+    
+    @SuppressWarnings({ "unchecked" })
+    protected <S> ServiceReference<S> findServiceByPid(BundleContext ctx, String type, String filter)
+    {
+        try
+        {
+            ServiceReference<S>[] refs = (ServiceReference<S>[]) ctx.getServiceReferences(type, filter);
+            return refs != null ? refs[0] : null;
+        }
+        catch (InvalidSyntaxException e)
+        {
+            throw new IllegalStateException("Could not get service using filter " + filter);
+        }        
+    }
+
+    protected void enableAndCheck( ComponentDescriptionDTO cd ) throws InvocationTargetException, InterruptedException
+    {
+        ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr != null )
+        {
+            scr.enableComponent(cd).getValue();
+        	Assert.assertTrue("Expected component enabled", scr.isComponentEnabled(cd));
+        }
+        else
+        {
+        	throw new NullPointerException("no ServiceComponentRuntime");
+        }
+
+    }
+
+	protected void disableAndCheck(ComponentDescriptionDTO cd) throws InvocationTargetException, InterruptedException {
+		ServiceComponentRuntime scr = scrTracker.getService();
+        if ( scr != null )
+        {
+        	scr.disableComponent(cd).getValue();
+        	Assert.assertFalse("Expected component disabled", scr.isComponentEnabled(cd));
+        }
+        else
+        {
+        	throw new NullPointerException("no ServiceComponentRuntime");
+        }
+	}
+
+	protected void disableAndCheck(Collection<ComponentConfigurationDTO> confs) throws InvocationTargetException, InterruptedException {
+        if (confs != null) {
+            for (ComponentConfigurationDTO conf : confs) {
+                disableAndCheck(conf);
+            }
+        }
+    }
+
+    protected void disableAndCheck( ComponentConfigurationDTO cc ) throws InvocationTargetException, InterruptedException
+    {
+        ComponentDescriptionDTO cd = cc.description;
+        disableAndCheck(cd);
+    }
+
+	protected void disableAndCheck(String name) throws InvocationTargetException, InterruptedException {
+		ComponentDescriptionDTO cd = findComponentDescriptorByName(name);
+		disableAndCheck(cd);
+	}
+
+    protected static void delay()
+    {
+        delay(300);
+    }
+
+    protected static void delay(int millis)
+    {
+        try
+        {
+            Thread.sleep(millis);
+        }
+        catch (InterruptedException ie)
+        {
+        }
+    }
+
+
+    protected ConfigurationAdmin getConfigurationAdmin()
+    {
+        ConfigurationAdmin ca = configAdminTracker.getService();
+        if ( ca == null )
+        {
+            TestCase.fail( "Missing ConfigurationAdmin service" );
+        }
+        return ca;
+    }
+
+    protected org.osgi.service.cm.Configuration configure( String pid )
+    {
+        return configure( pid, null );
+
+    }
+
+    protected org.osgi.service.cm.Configuration configure( String pid, String bundleLocation )
+    {
+        return configure(pid, bundleLocation, theConfig);
+    }
+
+    protected org.osgi.service.cm.Configuration configure(String pid,
+        String bundleLocation, Dictionary<String, Object> props)
+    {
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        try
+        {
+            org.osgi.service.cm.Configuration config = ca.getConfiguration( pid, null );
+            if (bundleLocation != null)
+            {
+                config.setBundleLocation( bundleLocation );
+            }
+            config.update( props );
+            return config;
+        }
+        catch ( IOException ioe )
+        {
+            TestCase.fail( "Failed updating configuration " + pid + ": " + ioe.toString() );
+        }
+        return null;
+    }
+
+
+    protected void deleteConfig( String pid )
+    {
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        try
+        {
+            org.osgi.service.cm.Configuration config = ca.getConfiguration( pid );
+            config.delete();
+        }
+        catch ( IOException ioe )
+        {
+            TestCase.fail( "Failed deleting configuration " + pid + ": " + ioe.toString() );
+        }
+    }
+
+
+    protected String createFactoryConfiguration( String factoryPid )
+    {
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        try
+        {
+            org.osgi.service.cm.Configuration config = ca.createFactoryConfiguration( factoryPid, null );
+            config.update( theConfig );
+            return config.getPid();
+        }
+        catch ( IOException ioe )
+        {
+            TestCase.fail( "Failed updating factory configuration " + factoryPid + ": " + ioe.toString() );
+            return null;
+        }
+    }
+
+
+    protected void deleteFactoryConfigurations( String factoryPid )
+    {
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        try
+        {
+            final String filter = "(service.factoryPid=" + factoryPid + ")";
+            org.osgi.service.cm.Configuration[] configs = ca.listConfigurations( filter );
+            if ( configs != null )
+            {
+                for ( org.osgi.service.cm.Configuration configuration : configs )
+                {
+                    configuration.delete();
+                }
+            }
+        }
+        catch ( InvalidSyntaxException ise )
+        {
+            // unexpected
+        }
+        catch ( IOException ioe )
+        {
+            TestCase.fail( "Failed deleting configurations " + factoryPid + ": " + ioe.toString() );
+        }
+    }
+
+    //component factory test helper methods
+    protected ComponentFactory getComponentFactory(final String componentfactory)
+        throws InvalidSyntaxException
+    {
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+        return factory;
+    }
+
+
+    protected void checkFactory(final String componentfactory, boolean expectFactoryPresent)
+        throws InvalidSyntaxException
+    {
+        ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        if ( expectFactoryPresent )
+        {
+            TestCase.assertNotNull( refs );
+            TestCase.assertEquals(1, refs.length);
+
+        }
+        else
+        {
+            TestCase.assertNull( refs );
+        }
+    }
+
+    protected ComponentInstance createFactoryComponentInstance(final String componentfactory)
+        throws InvalidSyntaxException
+    {
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+
+        return createFactoryComponentInstance(componentfactory, props);
+    }
+
+
+    protected ComponentInstance createFactoryComponentInstance(
+        final String componentfactory, Hashtable<String, String> props)
+        throws InvalidSyntaxException
+    {
+        final ComponentFactory factory = getComponentFactory(componentfactory);
+
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        return instance;
+    }
+
+
+
+
+    protected static Class<?> getType( Object object, String desiredName )
+    {
+        Class<?> ccImpl = object.getClass();
+        while ( ccImpl != null && !desiredName.equals( ccImpl.getSimpleName() ) )
+        {
+            ccImpl = ccImpl.getSuperclass();
+        }
+        if ( ccImpl == null )
+        {
+            TestCase.fail( "ComponentContext " + object + " is not a " + desiredName );
+        }
+
+        return ccImpl;
+    }
+
+
+    protected static Object getFieldValue( Object object, String fieldName )
+    {
+        try
+        {
+            final Field m_componentsField = getField( object.getClass(), fieldName );
+            return m_componentsField.get( object );
+        }
+        catch ( Throwable t )
+        {
+            TestCase.fail( "Cannot get " + fieldName + " from " + object + ": " + t );
+            return null; // keep the compiler happy
+        }
+    }
+
+    protected Object getComponentManagerFromComponentInstance( Object instance )
+    {
+        Object cc = getFieldValue( instance, "m_componentContext");
+        return getFieldValue( cc, "m_componentManager" );
+    }
+
+
+    protected static Field getField( Class<?> type, String fieldName ) throws NoSuchFieldException
+    {
+        Class<?> clazz = type;
+        while (clazz != null)
+        {
+            Field[] fields = clazz.getDeclaredFields();
+            for (int i = 0; i < fields.length; i++)
+            {
+                Field field = fields[i];
+                if (field.getName().equals(fieldName))
+                {
+                    field.setAccessible( true );
+                    return field;
+                }
+            }
+            clazz = clazz.getSuperclass();
+        }
+        throw new NoSuchFieldException(fieldName);
+    }
+
+    protected Bundle installBundle( final String descriptorFile, String componentPackage ) throws BundleException, IOException
+    {
+        return installBundle(descriptorFile, componentPackage, "simplecomponent", "0.0.11", null);
+    }
+
+    protected Bundle installBundle( final String descriptorFile, String componentPackage, String symbolicName, String version, String location ) throws BundleException, IOException
+    {
+        BundleGenerator generator = new BundleGenerator();
+                
+        try(InputStream bundleStream =         
+             generator
+                .add("OSGI-INF/components.xml", bundleContext.getBundle().getEntry(descriptorFile))
+                .set(Constants.BUNDLE_SYMBOLICNAME, symbolicName)
+                .set(Constants.BUNDLE_VERSION, version)
+                .set(Constants.IMPORT_PACKAGE, componentPackage)
+                .set("Service-Component", "OSGI-INF/components.xml")
+                .set(Constants.REQUIRE_CAPABILITY, ExtenderNamespace.EXTENDER_NAMESPACE + ";filter:=\"(&(osgi.extender=osgi.component)(version>=1.3)(!(version>=2.0)))\"")
+                .buildWithBnd()) {
+
+            if ( location == null )
+            {
+                location = "test:SimpleComponent/" + System.currentTimeMillis();
+            }
+            return bundleContext.installBundle( location, bundleStream );
+        }
+    }
+
+    protected boolean isAtLeastR5()
+    {
+        try
+        {
+            Method m = org.osgi.service.cm.Configuration.class.getDeclaredMethod( "getChangeCount");
+            return true;
+        }
+        catch ( SecurityException e )
+        {
+            throw new RuntimeException(e);
+        }
+        catch ( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+    
+    /**
+     * Reset some integration test components and some configurations before running a test.
+     */
+    private void init() {
+        theConfig.clear();
+        theConfig.put( PROP_NAME, PROP_NAME );
+        SimpleComponent.INSTANCES.clear();
+        SimpleComponent.PREVIOUS_INSTANCES.clear();  
+        Felix4350Component.init();
+    }
+    
+    /**
+     * Record all existing services and configuration.
+     */
+    protected void recordExistingConfigurations() {
+        Configuration[] confs = getAllConfigurations();
+        existingConfigurations.addAll(Arrays.asList(confs));        
+    }
+
+    private Configuration[] getAllConfigurations() {
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        try
+        {
+            Configuration[] confs = ca.listConfigurations( null );
+            return confs == null ? new Configuration[0] : confs;
+        }
+        catch ( Throwable ignored )
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Check if the test has removed all its resources (services, configurations).
+     */
+    private void checkConfigurationCleaned() {
+        Configuration[] confs = getAllConfigurations();
+        for (Configuration conf : confs) {
+            if (! existingConfigurations.contains(conf)) {
+                log.log(LogService.LOG_ERROR, "Tested ended but did not unregister " + conf);
+                Assert.fail("Tested ended but did not unregister configuration " + conf);
+            }
+        }
+        
+        existingServices.clear();
+        existingConfigurations.clear();
+    }
+    
+    public static class LogEntry
+    {
+        private final String m_msg;
+        private final int m_level;
+        private final Throwable m_err;
+        private final long m_time;
+        private final Thread m_thread;
+
+
+        LogEntry( int level, String msg, Throwable t )
+        {
+            m_level = level;
+            m_msg = msg;
+            m_err = t;
+            m_time = System.currentTimeMillis();
+            m_thread = Thread.currentThread();
+        }
+
+
+        @Override
+        public String toString()
+        {
+            return m_msg;
+        }
+
+
+        public int getLevel()
+        {
+            return m_level;
+        }
+
+
+        public String getMessage()
+        {
+            return m_msg;
+        }
+
+
+        public Throwable getError()
+        {
+            return m_err;
+        }
+
+
+        public long getTime()
+        {
+            return m_time;
+        }
+
+
+        public Thread getThread()
+        {
+            return m_thread;
+        }
+    }
+
+    public class Log implements LogService, FrameworkListener, Runnable
+    {
+        private static final int RESTRICTED_LOG_SIZE = 1000;
+        private final SimpleDateFormat m_sdf = new SimpleDateFormat( "HH:mm:ss,S" );
+        private final PrintStream m_out = new PrintStream( new BufferedOutputStream( new FileOutputStream(
+            FileDescriptor.err ), 128 ) );
+        private final List<String> m_warnings = Collections.synchronizedList( new ArrayList<String>() );
+        private LinkedBlockingQueue<LogEntry> m_logQueue = new LinkedBlockingQueue<LogEntry>();
+        private volatile Thread m_logThread;
+        private String[] ignoredWarnings; // Format is : log message [:exception message]
+
+        protected Throwable firstFrameworkThrowable;
+
+        private final boolean restrictedLogging;
+        private final String[] log = new String[1000];
+        private int i = 0;
+
+        public Log( boolean restrictedLogging, String[] ignoredWarnings )
+        {
+            this.restrictedLogging = restrictedLogging;
+            this.ignoredWarnings = ignoredWarnings;
+        }
+
+        public void start()
+        {
+            m_logThread = new Thread( this );
+            m_logThread.start();
+        }
+
+
+        public boolean stop()
+        {
+            // Make sure logging threads is done.
+            m_logThread.interrupt();
+            try
+            {
+                m_logThread.join();
+            }
+            catch ( InterruptedException e )
+            {
+            }
+
+            if ( restrictedLogging )
+            {
+                for (int j = 0; j < RESTRICTED_LOG_SIZE; j++)
+                {
+                    if ( log[i] != null )
+                    {
+                        err.println(log[i]);
+                    }
+                    i ++;
+                    if (i == RESTRICTED_LOG_SIZE) 
+                    {
+                        i = 0;
+                    }                   
+                }
+            }
+            else
+            {
+                m_out.flush();
+            }
+            boolean foundWarning = m_warnings.size() > 0;
+            m_warnings.clear();
+            m_logThread.interrupt();
+            return foundWarning;
+        }
+
+
+        List<String> foundWarnings()
+        {
+            return m_warnings;
+        }
+
+        Throwable getFirstFrameworkThrowable()
+        {
+            return firstFrameworkThrowable;
+        }
+
+
+
+        public void run()
+        {
+            try
+            {
+                LogEntry entry = null;
+                while ( true )
+                {
+                    entry = m_logQueue.take();
+                    boolean acceptedWarning = false;
+                    if ( entry.getLevel() <= 2 )
+                    {
+                        if (acceptWarning( entry))
+                        {
+                            acceptedWarning = true;
+                            if ( m_warnings.size() < 1024 )
+                            {
+                                m_warnings.add( entry.getMessage() );
+                            }
+                            else
+                            {
+                                // Avoid out of memory ...
+                                m_warnings.set( 1023, "Unexpected errors logged. Please look at previous logs" );
+                            }
+                        }
+                    }
+
+                    StringWriter sw = new StringWriter();
+                    sw.append( "L=" + entry.getLevel() );
+                    sw.append( " D=" );
+                    sw.append( m_sdf.format( new Date( entry.getTime() ) ) );
+                    sw.append( " T=\"" + entry.getThread().getName() + "\"");
+                    sw.append((entry.getLevel() <= 2 && ! acceptedWarning) ? " (log expected)" : " (log Unexpected)");
+                    sw.append( ": " );
+                    sw.append( entry.getMessage() );
+                    if ( entry.getLevel() <= 2 && entry.getError() != null)
+                    {
+                        PrintWriter pw = new PrintWriter( sw );
+                        sw.append( System.getProperty( "line.separator" ) );
+                        if (acceptWarning(entry)) 
+                        {
+                            entry.getError().printStackTrace( pw );
+                        } 
+                        else 
+                        {
+                            pw.print(entry.getError().toString());
+                        }
+                        pw.flush();
+                    }
+                    // We really want to log to stdout warnings that are ignored by the test.
+                    if ( restrictedLogging && (entry.getLevel() <= 2 && acceptedWarning))
+                    {
+                        log[i++] = sw.toString();
+                        if ( i == RESTRICTED_LOG_SIZE ) i = 0;
+                    }
+                    else
+                    {
+                        m_out.println( sw.toString() );
+                        m_out.flush();
+                    }
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                return;
+            }
+        }
+
+
+        // ------------- FrameworkListener -----------------------------------------------------------
+
+        private boolean acceptWarning(LogEntry entry) {
+        	if ( ignoredWarnings != null )
+        	{
+				for (String ignore : ignoredWarnings) {
+				    if (entry.getError() == null) {
+				        if (entry.getMessage().matches(ignore)) {
+				            return false;
+				        }
+				    } else {
+				        String msg = entry.getMessage() + System.getProperty( "line.separator" ) + entry.getError().toString(); 
+                        if (msg.matches(ignore)) {
+                            return false;
+                        }
+				    }
+				}
+			}
+			return true;
+		}
+
+		public void frameworkEvent( final FrameworkEvent event )
+        {
+            int eventType = event.getType();
+            String msg = getFrameworkEventMessage( eventType );
+            int level = ( eventType == FrameworkEvent.ERROR ) ? LogService.LOG_ERROR : LogService.LOG_INFO;
+            log( level, msg, event.getThrowable() );
+            if (event.getThrowable() != null && firstFrameworkThrowable == null)
+            {
+                firstFrameworkThrowable = event.getThrowable();
+            }
+        }
+
+
+        // ------------ LogService ----------------------------------------------------------------
+
+        public void log( int level, String message )
+        {
+            log( level, message, null );
+        }
+
+
+        public void log( int level, String message, Throwable exception )
+        {
+            if ( level > getEnabledLogLevel() )
+            {
+                return;
+            }
+            m_logQueue.offer( new LogEntry( level, message, exception ) );
+        }
+
+
+        public void log( ServiceReference sr, int osgiLevel, String message )
+        {
+            log( sr, osgiLevel, message, null );
+        }
+
+
+        public void log( ServiceReference sr, int level, String msg, Throwable exception )
+        {
+            if ( sr != null )
+            {
+                StringBuilder sb = new StringBuilder();
+                Object serviceId = sr.getProperty( Constants.SERVICE_ID );
+                if ( serviceId != null )
+                {
+                    sb.append( "[" + serviceId.toString() + "] " );
+                }
+                sb.append( msg );
+                log( level, sb.toString(), exception );
+            }
+            else
+            {
+                log( level, msg, exception );
+            }
+        }
+
+
+        private int getEnabledLogLevel()
+        {
+            if ( DS_LOGLEVEL.regionMatches( true, 0, "err", 0, "err".length() ) )
+            {
+                return LogService.LOG_ERROR;
+            }
+            else if ( DS_LOGLEVEL.regionMatches( true, 0, "warn", 0, "warn".length() ) )
+            {
+                return LogService.LOG_WARNING;
+            }
+            else if ( DS_LOGLEVEL.regionMatches( true, 0, "info", 0, "info".length() ) )
+            {
+                return LogService.LOG_INFO;
+            }
+            else
+            {
+                return LogService.LOG_DEBUG;
+            }
+        }
+
+
+        private String getFrameworkEventMessage( int event )
+        {
+            switch ( event )
+            {
+                case FrameworkEvent.ERROR:
+                    return "FrameworkEvent: ERROR";
+                case FrameworkEvent.INFO:
+                    return "FrameworkEvent INFO";
+                case FrameworkEvent.PACKAGES_REFRESHED:
+                    return "FrameworkEvent: PACKAGE REFRESHED";
+                case FrameworkEvent.STARTED:
+                    return "FrameworkEvent: STARTED";
+                case FrameworkEvent.STARTLEVEL_CHANGED:
+                    return "FrameworkEvent: STARTLEVEL CHANGED";
+                case FrameworkEvent.WARNING:
+                    return "FrameworkEvent: WARNING";
+                default:
+                    return null;
+            }
+        }
+    }
+}



Mime
View raw message