Author: davidb Date: Fri Feb 26 10:11:59 2016 New Revision: 1732445 URL: http://svn.apache.org/viewvc?rev=1732445&view=rev Log: FELIX-5199 Race condition in HttpServiceFactory.getService() causing exception
Fixed using 'active' flag. Unit test included. Added: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/HttpServiceFactoryTest.java Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java?rev=1732445&r1=1732444&r2=1732445&view=diff ============================================================================== --- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java (original) +++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java Fri Feb 26 10:11:59 2016 @@ -68,6 +68,7 @@ public final class HttpServiceFactory /** Compatibility property with previous versions. */ private static final String OBSOLETE_REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints"; + private volatile boolean active = false; private final BundleContext bundleContext; private final boolean sharedContextAttributes; @@ -111,10 +112,14 @@ public final class HttpServiceFactory final String[] ifaces = new String[] { HttpService.class.getName(), ExtHttpService.class.getName() }; this.httpServiceReg = bundleContext.registerService(ifaces, this, this.httpServiceProps); + + this.active = true; } public void stop() { + this.active = false; + if ( this.httpServiceReg != null ) { this.httpServiceReg.unregister(); @@ -134,8 +139,7 @@ public final class HttpServiceFactory @Override public HttpService getService(final Bundle bundle, final ServiceRegistration<HttpService> reg) { - final ServletContext servletContext = this.context; - if ( servletContext != null ) { + if ( active ) { return new PerBundleHttpServiceImpl(bundle, this.sharedHttpService, this.context, Added: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/HttpServiceFactoryTest.java URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/HttpServiceFactoryTest.java?rev=1732445&view=auto ============================================================================== --- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/HttpServiceFactoryTest.java (added) +++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/service/HttpServiceFactoryTest.java Fri Feb 26 10:11:59 2016 @@ -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.http.base.internal.service; + +import javax.servlet.ServletContext; + +import org.apache.felix.http.base.internal.registry.HandlerRegistry; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.service.http.HttpService; + +public class HttpServiceFactoryTest { + @Test + public void testGetServiceActiveInActive() throws Exception { + BundleContext bc = Mockito.mock(BundleContext.class); + Mockito.when(bc.createFilter(Mockito.anyString())).then(new Answer<Filter>() { + @Override + public Filter answer(InvocationOnMock invocation) throws Throwable { + return FrameworkUtil.createFilter((String) invocation.getArguments()[0]); + } + }); + HttpServiceFactory hsf = new HttpServiceFactory(bc, new HandlerRegistry()); + + Assert.assertNull("Not yet active", + hsf.getService(Mockito.mock(Bundle.class), null)); + + ServletContext sctx = Mockito.mock(ServletContext.class); + hsf.start(sctx); + HttpService svc = hsf.getService(Mockito.mock(Bundle.class), null); + Assert.assertNotNull(svc); + + hsf.stop(); + Assert.assertNull("Not active any more", + hsf.getService(Mockito.mock(Bundle.class), null)); + } +}