Author: davidb
Date: Tue Jul 14 13:25:51 2015
New Revision: 1690926

URL: http://svn.apache.org/r1690926
Log:
[SCR] Fix potential NPE in concurrent scenarios

Also included unit tests.

Added:
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java
Modified:
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1690926&r1=1690925&r2=1690926&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
 Tue Jul 14 13:25:51 2015
@@ -450,7 +450,7 @@ public class SingleComponentManager<S> e
                        {
                                servicePids.addAll((List)configPropServicePids);
                        }
-                       else 
+                       else
                        {
                                
servicePids.add(configPropServicePids.toString());
                        }
@@ -458,7 +458,7 @@ public class SingleComponentManager<S> e
                     {
                         
servicePids.add((String)m_factoryProperties.get(Constants.SERVICE_PID));
                     }
-                    
+
                        if ( servicePids.size() == 1 )
                        {
                                props.put(Constants.SERVICE_PID, 
servicePids.get(0));
@@ -761,10 +761,11 @@ public class SingleComponentManager<S> e
     public S getService( Bundle bundle, ServiceRegistration<S> 
serviceRegistration )
     {
         boolean success = getServiceInternal();
-        if ( success )
+        ComponentContextImpl<S> componentContext = m_componentContext;
+        if ( success && componentContext != null)
         {
             m_useCount.incrementAndGet();
-            return m_componentContext.getImplementationObject( true );
+            return componentContext.getImplementationObject( true );
         }
         else
         {

Added: 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java?rev=1690926&view=auto
==============================================================================
--- 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java
 (added)
+++ 
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java
 Tue Jul 14 13:25:51 2015
@@ -0,0 +1,94 @@
+/*
+ * 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.impl.manager;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import java.lang.reflect.Field;
+
+import org.apache.felix.scr.impl.config.ComponentContainer;
+import org.apache.felix.scr.impl.helper.ComponentMethods;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class SingleComponentManagerTest
+{
+    @Test
+    public void testGetService() throws Exception {
+        ComponentMetadata cm = new ComponentMetadata(DSVersion.DS13);
+        cm.setImplementationClassName("foo.bar.SomeClass");
+        cm.validate(null);
+
+        @SuppressWarnings("unchecked")
+        ComponentContainer<Object> cc = Mockito.mock(ComponentContainer.class);
+        Mockito.when(cc.getComponentMetadata()).thenReturn(cm);
+
+        SingleComponentManager<Object> scm = new 
SingleComponentManager<Object>(cc, new ComponentMethods()) {
+            @Override
+            boolean getServiceInternal()
+            {
+                return true;
+            }
+        };
+
+        BundleContext bc = Mockito.mock(BundleContext.class);
+        Bundle b = Mockito.mock(Bundle.class);
+        Mockito.when(b.getBundleContext()).thenReturn(bc);
+
+        ComponentContextImpl<Object> cci = new 
ComponentContextImpl<Object>(scm, b);
+        Object implObj = new Object();
+        cci.setImplementationObject(implObj);
+        cci.setImplementationAccessible(true);
+
+        Field f = 
SingleComponentManager.class.getDeclaredField("m_componentContext");
+        f.setAccessible(true);
+        f.set(scm, cci);
+
+        scm.m_internalEnabled = true;
+        assertSame(implObj, scm.getService(null, null));
+    }
+
+    @Test
+    public void testGetServiceWithNullComponentContext()
+    {
+        ComponentMetadata cm = new ComponentMetadata(DSVersion.DS13);
+        cm.setImplementationClassName("foo.bar.SomeClass");
+        cm.validate(null);
+
+        @SuppressWarnings("unchecked")
+        ComponentContainer<Object> cc = Mockito.mock(ComponentContainer.class);
+        Mockito.when(cc.getComponentMetadata()).thenReturn(cm);
+
+        SingleComponentManager<?> scm = new SingleComponentManager<Object>(cc, 
new ComponentMethods()) {
+            @Override
+            boolean getServiceInternal()
+            {
+                return true;
+            }
+        };
+        scm.m_internalEnabled = true;
+        assertNull("m_componentContext is null, this should not cause an NPE",
+                scm.getService(null, null));
+    }
+}


Reply via email to