You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/11/04 00:37:10 UTC

svn commit: r1197348 - in /felix/trunk/configadmin/src: main/java/org/apache/felix/cm/impl/ test/java/org/apache/felix/cm/impl/ test/java/org/apache/felix/cm/integration/ test/java/org/apache/felix/cm/integration/helper/

Author: fmeschbe
Date: Thu Nov  3 23:37:10 2011
New Revision: 1197348

URL: http://svn.apache.org/viewvc?rev=1197348&view=rev
Log:
FELIX-3200 Track ManagedService[Factory] PID changes

Added:
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java
Modified:
    felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java

Modified: felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java?rev=1197348&r1=1197347&r2=1197348&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java Thu Nov  3 23:37:10 2011
@@ -680,9 +680,13 @@ public class ConfigurationManager implem
     }
 
 
-    private void configure( ServiceReference sr, ManagedService service )
+    /**
+     * Configures the ManagedService and returns the service.pid
+     * service property as a String[], which may be <code>null</code> if
+     * the ManagedService does not have such a property.
+     */
+    private void configure( String[] pids, ServiceReference sr, ManagedService service )
     {
-        String[] pids = getServicePid( sr );
         if ( pids != null )
         {
             for ( int i = 0; i < pids.length; i++ )
@@ -696,9 +700,13 @@ public class ConfigurationManager implem
     }
 
 
-    private void configure( ServiceReference sr, ManagedServiceFactory service )
+    /**
+     * Configures the ManagedServiceFactory and returns the service.pid
+     * service property as a String[], which may be <code>null</code> if
+     * the ManagedServiceFactory does not have such a property.
+     */
+    private void configure( String[] pids, ServiceReference sr, ManagedServiceFactory service )
     {
-        String[] pids = getServicePid( sr );
         if ( pids != null )
         {
             for ( int i = 0; i < pids.length; i++ )
@@ -1227,7 +1235,6 @@ public class ConfigurationManager implem
         protected ManagedServiceFactoryHelper( ConfigurationImpl config )
         {
             super( config );
-            // TODO Auto-generated constructor stub
         }
 
 
@@ -1922,20 +1929,43 @@ public class ConfigurationManager implem
 
         public Object addingService( ServiceReference reference )
         {
-            Object serviceObject = super.addingService( reference );
+            Object service = super.addingService( reference );
 
             // configure the managed service
-            if ( serviceObject instanceof ManagedService )
+            final String[] pids;
+            if ( service instanceof ManagedService )
             {
-                cm.configure(reference, ( ManagedService ) serviceObject);
+                pids = getServicePid( reference );
+                cm.configure( pids, reference, ( ManagedService ) service );
             }
             else
             {
                 cm.log( LogService.LOG_WARNING, "Service {0} is not a ManagedService", new Object[]
-                    { serviceObject } );
+                    { service } );
+                pids = null;
             }
 
-            return serviceObject;
+            return new ManagedServiceHolder( service, pids );
+        }
+
+
+        public void modifiedService( ServiceReference reference, Object service )
+        {
+            ManagedServiceHolder holder = ( ManagedServiceHolder ) service;
+            String[] pids = getServicePid( reference );
+
+            if ( holder.isDifferentPids( pids ) )
+            {
+                cm.configure( pids, reference, ( ManagedService ) holder.getManagedService() );
+                holder.setConfiguredPids( pids );
+            }
+        }
+
+
+        public void removedService( ServiceReference reference, Object service )
+        {
+            final Object serviceObject = ( ( ManagedServiceHolder ) service ).getManagedService();
+            super.removedService( reference, serviceObject );
         }
     }
 
@@ -1957,19 +1987,94 @@ public class ConfigurationManager implem
             Object serviceObject = super.addingService( reference );
 
             // configure the managed service factory
+            final String[] pids;
             if ( serviceObject instanceof ManagedServiceFactory )
             {
-                cm.configure( reference, ( ManagedServiceFactory ) serviceObject );
+                pids = getServicePid( reference );
+                cm.configure( pids, reference, ( ManagedServiceFactory ) serviceObject );
             }
             else
             {
                 cm.log( LogService.LOG_WARNING, "Service {0} is not a ManagedServiceFactory", new Object[]
                     { serviceObject } );
+                pids = null;
+            }
+
+            return new ManagedServiceHolder( serviceObject, pids );
+        }
+
+
+        public void modifiedService( ServiceReference reference, Object service )
+        {
+            ManagedServiceHolder holder = ( ManagedServiceHolder ) service;
+            String[] pids = getServicePid( reference );
+
+            if ( holder.isDifferentPids( pids ) )
+            {
+                cm.configure( pids, reference, ( ManagedServiceFactory ) holder.getManagedService() );
+                holder.setConfiguredPids( pids );
             }
 
-            return serviceObject;
+            super.modifiedService( reference, service );
+        }
+
+
+        public void removedService( ServiceReference reference, Object service )
+        {
+            final Object serviceObject = ( ( ManagedServiceHolder ) service ).getManagedService();
+            super.removedService( reference, serviceObject );
         }
     }
 
+    private static class ManagedServiceHolder
+    {
+        private final Object managedService;
+        private String[] configuredPids;
+
+
+        ManagedServiceHolder( final Object managedService, final String[] configuredPids )
+        {
+            this.managedService = managedService;
+            this.configuredPids = configuredPids;
+        }
+
+
+        public Object getManagedService()
+        {
+            return managedService;
+        }
+
+
+        public void setConfiguredPids( String[] configuredPids )
+        {
+            this.configuredPids = configuredPids;
+        }
+
 
+        boolean isDifferentPids( final String[] pids )
+        {
+            if ( this.configuredPids == null && pids == null )
+            {
+                return false;
+            }
+            else if ( this.configuredPids == null )
+            {
+                return true;
+            }
+            else if ( pids == null )
+            {
+                return true;
+            }
+            else if ( this.configuredPids.length != pids.length )
+            {
+                return true;
+            }
+            else
+            {
+                HashSet thisPids = new HashSet( Arrays.asList( this.configuredPids ) );
+                HashSet otherPids = new HashSet( Arrays.asList( pids ) );
+                return !thisPids.equals( otherPids );
+            }
+        }
+    }
 }

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java?rev=1197348&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java Thu Nov  3 23:37:10 2011
@@ -0,0 +1,130 @@
+/*
+ * 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.cm.impl;
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+
+public class ManagedServiceHolderTest extends TestCase
+{
+
+    private static final Constructor mshConstructor;
+    private static final Method msh_isDifferentPids;
+
+    static
+    {
+        try
+        {
+            Class clazz = Class.forName( "org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceHolder" );
+            mshConstructor = clazz.getDeclaredConstructor( new Class[]
+                { Object.class, String[].class } );
+            mshConstructor.setAccessible( true );
+            msh_isDifferentPids = clazz.getDeclaredMethod( "isDifferentPids", new Class[]
+                { String[].class } );
+            msh_isDifferentPids.setAccessible( true );
+        }
+        catch ( Throwable t )
+        {
+            throw new RuntimeException( t );
+        }
+    }
+
+
+    public void test_isDifferentPids_null_null()
+    {
+        Object holder = createHolder( null );
+        assertFalse( "Expect both pids null to be the same", isDifferentPids( holder, null ) );
+    }
+
+
+    public void test_isDifferentPids_null_notNull()
+    {
+        Object holder = createHolder( null );
+        assertTrue( "Expect not same for one pid not null", isDifferentPids( holder, new String[]
+            { "entry" } ) );
+    }
+
+
+    public void test_isDifferentPids_notNull_null()
+    {
+        Object holder = createHolder( new String[]
+            { "entry" } );
+        assertTrue( "Expect not same for one pid not null", isDifferentPids( holder, null ) );
+    }
+
+
+    public void test_isDifferentPids_notNull_notNull()
+    {
+        final String[] pids10 =
+            { "a", "b" };
+        final String[] pids11 =
+            { "b", "a" };
+        final String[] pids20 =
+            { "a", "c" };
+        final String[] pids30 =
+            { "a", "b", "c" };
+
+        final Object holder10 = createHolder( pids10 );
+        assertFalse( isDifferentPids( holder10, pids10 ) );
+        assertFalse( isDifferentPids( holder10, pids11 ) );
+        assertTrue( isDifferentPids( holder10, pids20 ) );
+        assertTrue( isDifferentPids( holder10, pids30 ) );
+
+        final Object holder20 = createHolder( pids20 );
+        assertTrue( isDifferentPids( holder20, pids10 ) );
+        assertTrue( isDifferentPids( holder20, pids11 ) );
+        assertFalse( isDifferentPids( holder20, pids20 ) );
+        assertTrue( isDifferentPids( holder20, pids30 ) );
+    }
+
+
+    private Object createHolder( final String[] pids )
+    {
+        try
+        {
+            return mshConstructor.newInstance( new Object[]
+                { null, pids } );
+        }
+        catch ( Throwable t )
+        {
+            fail( t.getMessage() );
+            return null; // keep compiler quiet
+        }
+    }
+
+
+    private boolean isDifferentPids( final Object holder, final String[] pids )
+    {
+        try
+        {
+            Object result = msh_isDifferentPids.invoke( holder, new Object[]
+                { pids } );
+            return ( result instanceof Boolean ) && ( ( Boolean ) result ).booleanValue();
+        }
+        catch ( Throwable t )
+        {
+            fail( t.getMessage() );
+            return false; // keep compiler quiet
+        }
+    }
+}

Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java?rev=1197348&r1=1197347&r2=1197348&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java Thu Nov  3 23:37:10 2011
@@ -383,4 +383,116 @@ public class ConfigurationBaseTest exten
         final Configuration get2 = getConfigurationAdmin().getConfiguration( pid );
         TestCase.assertEquals( bundle.getLocation(), get2.getBundleLocation() );
 }
+
+    @Test
+    public void test_ManagedService_change_pid() throws BundleException, IOException
+    {
+        final String pid0 = "test_ManagedService_change_pid_0";
+        final String pid1 = "test_ManagedService_change_pid_1";
+
+        final Configuration config0 = configure( pid0, null, true );
+        final Configuration config1 = configure( pid1, null, true );
+        delay();
+
+        // register ManagedService ms1 with pid from said locationA
+        bundle = installBundle( pid0, ManagedServiceTestActivator.class );
+        bundle.start();
+        delay();
+
+        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
+        TestCase.assertNotNull( tester.props );
+        TestCase.assertEquals( pid0, tester.props.get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.props.get( PROP_NAME ) );
+        TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );
+
+        // change ManagedService PID
+        tester.changePid( pid1 );
+        delay();
+
+        TestCase.assertNotNull( tester.props );
+        TestCase.assertEquals( pid1, tester.props.get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.props.get( PROP_NAME ) );
+        TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );
+
+        // delete
+        config0.delete();
+        config1.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.props );
+        TestCase.assertEquals( 3, tester.numManagedServiceUpdatedCalls );
+    }
+
+
+    @Test
+    public void test_ManagedServiceFactory_change_pid() throws BundleException, IOException
+    {
+
+        final String factoryPid0 = "test_ManagedServiceFactory_change_pid_0";
+        final String factoryPid1 = "test_ManagedServiceFactory_change_pid_1";
+
+        final Configuration config0 = createFactoryConfiguration( factoryPid0, null, true );
+        final String pid0 = config0.getPid();
+        final Configuration config1 = createFactoryConfiguration( factoryPid1, null, true );
+        final String pid1 = config1.getPid();
+        delay();
+
+        bundle = installBundle( factoryPid0, ManagedServiceFactoryTestActivator.class );
+        bundle.start();
+        delay();
+
+        // pid0 properties provided on registration
+        final ManagedServiceFactoryTestActivator tester = ManagedServiceFactoryTestActivator.INSTANCE;
+        Dictionary<?, ?> props0 = tester.configs.get( pid0 );
+        TestCase.assertNotNull( props0 );
+        TestCase.assertEquals( pid0, props0.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid0, props0.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props0.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props0.get( PROP_NAME ) );
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // change ManagedService PID
+        tester.changePid( factoryPid1 );
+        delay();
+
+        // pid1 properties must have been added
+        Dictionary<?, ?> props1 = tester.configs.get( pid1 );
+        TestCase.assertNotNull( props1 );
+        TestCase.assertEquals( pid1, props1.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid1, props1.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props1.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props1.get( PROP_NAME ) );
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 2, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // pid0 properties must still exist !
+        Dictionary<?, ?> props01 = tester.configs.get( pid0 );
+        TestCase.assertNotNull( props01 );
+        TestCase.assertEquals( pid0, props01.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid0, props01.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props01.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props01.get( PROP_NAME ) );
+
+
+        // delete
+        config0.delete();
+        config1.delete();
+        delay();
+
+        // only pid1 properties removed because pid0 is not registered any longer
+        TestCase.assertNotNull( tester.configs.get( pid0 ) );
+        TestCase.assertNull( tester.configs.get( pid1 ) );
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 2, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryDeleteCalls );
+    }
+
 }

Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java?rev=1197348&r1=1197347&r2=1197348&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java Thu Nov  3 23:37:10 2011
@@ -19,7 +19,11 @@
 package org.apache.felix.cm.integration.helper;
 
 
+import java.util.Dictionary;
+
+import org.ops4j.pax.swissbox.tinybundles.dp.Constants;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ManagedServiceFactory;
 
 
@@ -28,10 +32,15 @@ public class ManagedServiceFactoryTestAc
 
     public static ManagedServiceFactoryTestActivator INSTANCE;
 
+    private Dictionary registrationProps;
+    private ServiceRegistration registration;
+
 
     public void start( BundleContext context ) throws Exception
     {
-        context.registerService( ManagedServiceFactory.class.getName(), this, getServiceProperties( context ) );
+        this.registrationProps = getServiceProperties( context );
+        this.registration = context.registerService( ManagedServiceFactory.class.getName(), this,
+            this.registrationProps );
         INSTANCE = this;
     }
 
@@ -40,4 +49,11 @@ public class ManagedServiceFactoryTestAc
     {
         INSTANCE = null;
     }
+
+
+    public void changePid( final String newPid )
+    {
+        this.registrationProps.put( Constants.SERVICE_PID, newPid );
+        this.registration.setProperties( this.registrationProps );
+    }
 }

Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java?rev=1197348&r1=1197347&r2=1197348&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java Thu Nov  3 23:37:10 2011
@@ -19,7 +19,11 @@
 package org.apache.felix.cm.integration.helper;
 
 
+import java.util.Dictionary;
+
+import org.ops4j.pax.swissbox.tinybundles.dp.Constants;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ManagedService;
 
 
@@ -28,10 +32,13 @@ public class ManagedServiceTestActivator
 
     public static ManagedServiceTestActivator INSTANCE;
 
+    private Dictionary registrationProps;
+    private ServiceRegistration registration;
 
     public void start( BundleContext context ) throws Exception
     {
-        context.registerService( ManagedService.class.getName(), this, getServiceProperties( context ) );
+        this.registrationProps = getServiceProperties( context );
+        this.registration = context.registerService( ManagedService.class.getName(), this, this.registrationProps );
         INSTANCE = this;
     }
 
@@ -40,4 +47,11 @@ public class ManagedServiceTestActivator
     {
         INSTANCE = null;
     }
+
+
+    public void changePid( final String newPid )
+    {
+        this.registrationProps.put( Constants.SERVICE_PID, newPid );
+        this.registration.setProperties( this.registrationProps );
+    }
 }