blob: b87a2c5dad845af68e044c05cf53562f2db2d2bc [file] [log] [blame]
/*
* 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.itest;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.osgi.framework.Constants.SERVICE_RANKING;
import static org.osgi.service.http.runtime.HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT;
import static org.osgi.service.http.runtime.HttpServiceRuntimeConstants.HTTP_SERVICE_ID;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_VALIDATION_FAILED;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionListener;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.dto.FailedErrorPageDTO;
import org.osgi.service.http.runtime.dto.FailedServletDTO;
import org.osgi.service.http.runtime.dto.RequestInfoDTO;
import org.osgi.service.http.runtime.dto.RuntimeDTO;
import org.osgi.service.http.runtime.dto.ServletContextDTO;
import org.osgi.service.http.runtime.dto.ServletDTO;
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class HttpServiceRuntimeTest extends BaseIntegrationTest
{
private static final String HTTP_CONTEXT_NAME = "org.osgi.service.http";
Collection<ServiceRegistration<?>> registrations = new ArrayList<>();
private static final long DEFAULT_SLEEP = 100;
@After
public void unregisterServices() throws Exception
{
for (ServiceRegistration<?> serviceRegistration : registrations)
{
try
{
serviceRegistration.unregister();
}
catch (Exception e)
{
// already unregistered
}
}
registrations.clear();
Thread.sleep(100);
}
private void registerServlet(String name, String path) throws InterruptedException
{
CountDownLatch initLatch = new CountDownLatch(1);
registerServlet(name, path, null, initLatch);
awaitServiceRegistration(initLatch);
}
private void registerServlet(String name, String path, CountDownLatch initLatch)
{
registerServlet(name, path, null, initLatch);
}
private void registerServlet(String name, String path, String context, CountDownLatch initLatch)
{
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_SERVLET_PATTERN, path,
HTTP_WHITEBOARD_SERVLET_NAME, name,
HTTP_WHITEBOARD_CONTEXT_SELECT, context);
Dictionary<String, ?> properties = createDictionary(context == null ?
propertyEntries.subList(0, 4).toArray() : propertyEntries.toArray());
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(initLatch, null), properties));
}
private void registerFilter(String name, String path) throws InterruptedException
{
CountDownLatch initLatch = new CountDownLatch(1);
registerFilter(name, path, initLatch);
awaitServiceRegistration(initLatch);
}
private void registerFilter(String name, String path, CountDownLatch initLatch)
{
registerFilter(name, path, null, initLatch);
}
private void registerFilter(String name, String path, String context, CountDownLatch initLatch)
{
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_FILTER_PATTERN, path,
HTTP_WHITEBOARD_FILTER_NAME, name,
HTTP_WHITEBOARD_CONTEXT_SELECT, context);
Dictionary<String, ?> properties = createDictionary(context == null ?
propertyEntries.subList(0, 4).toArray() : propertyEntries.toArray());
registrations.add(m_context.registerService(Filter.class.getName(), new TestFilter(initLatch, null), properties));
}
private void registerResource(String prefix, String path) throws InterruptedException
{
registerResource(prefix, path, null);
}
private void registerResource(String prefix, String path, String context) throws InterruptedException
{
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_RESOURCE_PATTERN, path,
HTTP_WHITEBOARD_RESOURCE_PREFIX, prefix,
HTTP_WHITEBOARD_CONTEXT_SELECT, context);
Dictionary<String, ?> properties = createDictionary(context == null ?
propertyEntries.subList(0, 4).toArray() : propertyEntries.toArray());
registrations.add(m_context.registerService(TestResource.class.getName(), new TestResource(), properties));
awaitServiceRegistration();
}
private void registerErrorPage(String name, List<String> errors) throws InterruptedException
{
CountDownLatch initLatch = new CountDownLatch(1);
registerErrorPage(name, errors, initLatch);
awaitServiceRegistration(initLatch);
}
private void registerErrorPage(String name, List<String> errors, CountDownLatch initLatch)
{
registerErrorPage(name, errors, null, initLatch);
}
private void registerErrorPage(String name, List<String> errors, String context, CountDownLatch initLatch)
{
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, errors,
HTTP_WHITEBOARD_SERVLET_NAME, name,
HTTP_WHITEBOARD_CONTEXT_SELECT, context);
Dictionary<String, ?> properties = createDictionary(context == null ?
propertyEntries.subList(0, 4).toArray() : propertyEntries.toArray());
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(initLatch, null), properties));
}
private void registerListener(Class<?> listenerClass, boolean useWithWhiteboard) throws InterruptedException
{
registerListener(listenerClass, useWithWhiteboard, null);
}
private void registerListener(Class<?> listenerClass, boolean useWithWhiteboard, String context) throws InterruptedException
{
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_LISTENER, useWithWhiteboard ? "true" : "false",
HTTP_WHITEBOARD_CONTEXT_SELECT, context);
Dictionary<String, ?> properties = createDictionary(context == null ?
propertyEntries.subList(0, 2).toArray() : propertyEntries.toArray());
registrations.add(m_context.registerService(listenerClass.getName(), mock(listenerClass), properties));
awaitServiceRegistration();
}
private ServiceRegistration<?> registerContext(String name, String path) throws InterruptedException
{
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_CONTEXT_NAME, name,
HTTP_WHITEBOARD_CONTEXT_PATH, path);
ServiceRegistration<?> contextRegistration = m_context.registerService(ServletContextHelper.class.getName(), mock(ServletContextHelper.class), properties);
registrations.add(contextRegistration);
awaitServiceRegistration();
return contextRegistration;
}
@Before
public void awaitServiceRuntime() throws Exception
{
awaitService(HttpServiceRuntime.class.getName());
}
@Test
public void httpRuntimeServiceIsAvailableAfterBundleActivation() throws Exception
{
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
ServiceReferenceDTO serviceDTO = runtimeDTO.serviceDTO;
assertNotNull(serviceDTO);
assertNotNull(serviceDTO.properties);
assertTrue(serviceDTO.properties.containsKey(HTTP_SERVICE_ID));
assertTrue(serviceDTO.properties.containsKey(HTTP_SERVICE_ENDPOINT));
assertTrue(serviceDTO.properties.get(HTTP_SERVICE_ID) instanceof Collection);
final Collection ids = (Collection)serviceDTO.properties.get(HTTP_SERVICE_ID);
assertTrue(ids.size() == 1);
assertTrue(ids.iterator().next() instanceof Long);
assertTrue(0 < (Long)ids.iterator().next());
assertEquals(0, runtimeDTO.failedErrorPageDTOs.length);
assertEquals(0, runtimeDTO.failedFilterDTOs.length);
assertEquals(0, runtimeDTO.failedListenerDTOs.length);
assertEquals(0, runtimeDTO.failedResourceDTOs.length);
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
assertEquals(0, runtimeDTO.failedServletDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(0, defaultContext.attributes.size());
// TODO The default context should have a negative service Id
// assertTrue(0 > runtimeDTO.servletContextDTOs[0].serviceId);
// TODO Should be "/" ?
assertEquals("", defaultContext.contextPath);
assertEquals(0, defaultContext.initParams.size());
assertEquals(0, defaultContext.filterDTOs.length);
assertEquals(0, defaultContext.servletDTOs.length);
assertEquals(0, defaultContext.resourceDTOs.length);
assertEquals(0, defaultContext.errorPageDTOs.length);
assertEquals(0, defaultContext.listenerDTOs.length);
}
@Test
public void dtosForSuccesfullyRegisteredServlets() throws Exception
{
//register first servlet
registerServlet("testServlet 1", "/servlet_1");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstSerlvet = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithFirstSerlvet.failedServletDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithFirstSerlvet);
assertEquals(1, contextDTO.servletDTOs.length);
assertEquals("testServlet 1", contextDTO.servletDTOs[0].name);
//register second servlet
registerServlet("testServlet 2", "/servlet_2");
RuntimeDTO runtimeDTOWithBothSerlvets = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithBothSerlvets.failedServletDTOs.length);
contextDTO = assertDefaultContext(runtimeDTOWithBothSerlvets);
assertEquals(2, contextDTO.servletDTOs.length);
final Set<String> names = new HashSet<>();
names.add(contextDTO.servletDTOs[0].name);
names.add(contextDTO.servletDTOs[1].name);
assertTrue(names.contains("testServlet 1"));
assertTrue(names.contains("testServlet 2"));
}
@Test
public void dtosForSuccesfullyRegisteredFilters() throws Exception
{
//register first filter
registerFilter("testFilter 1", "/servlet_1");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstFilter = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithFirstFilter.failedFilterDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithFirstFilter);
assertEquals(1, contextDTO.filterDTOs.length);
assertEquals("testFilter 1", contextDTO.filterDTOs[0].name);
//register second filter
registerFilter("testFilter 2", "/servlet_1");
RuntimeDTO runtimeDTOWithBothFilters = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithBothFilters.failedFilterDTOs.length);
contextDTO = assertDefaultContext(runtimeDTOWithBothFilters);
assertEquals(2, contextDTO.filterDTOs.length);
assertEquals("testFilter 1", contextDTO.filterDTOs[0].name);
assertEquals("testFilter 2", contextDTO.filterDTOs[1].name);
}
@Test
public void dtosForSuccesfullyRegisteredResources() throws Exception
{
// register first resource service
registerResource("/resources", "/resource_1/*");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstResource = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithFirstResource.failedResourceDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithFirstResource);
assertEquals(1, contextDTO.resourceDTOs.length);
assertEquals("/resources", contextDTO.resourceDTOs[0].prefix);
assertArrayEquals(new String[] { "/resource_1/*" }, contextDTO.resourceDTOs[0].patterns);
// register second resource service
registerResource("/resources", "/resource_2/*");
RuntimeDTO runtimeDTOWithBothResources = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithBothResources.failedResourceDTOs.length);
contextDTO = assertDefaultContext(runtimeDTOWithBothResources);
assertEquals(2, contextDTO.resourceDTOs.length);
assertEquals("/resources", contextDTO.resourceDTOs[0].prefix);
assertEquals(1, contextDTO.resourceDTOs[0].patterns.length);
assertEquals(1, contextDTO.resourceDTOs[1].patterns.length);
final Set<String> patterns = new HashSet<>();
patterns.add(contextDTO.resourceDTOs[0].patterns[0]);
patterns.add(contextDTO.resourceDTOs[1].patterns[0]);
assertTrue(patterns.contains("/resource_1/*"));
assertTrue(patterns.contains("/resource_2/*"));
}
@Test
public void dtosForSuccesfullyRegisteredErrorPages() throws Exception
{
// register first error page
registerErrorPage("error page 1", asList("404", NoSuchElementException.class.getName()));
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstErrorPage = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithFirstErrorPage.failedServletDTOs.length);
assertEquals(0, runtimeDTOWithFirstErrorPage.failedErrorPageDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithFirstErrorPage);
assertEquals(1, contextDTO.errorPageDTOs.length);
assertEquals("error page 1", contextDTO.errorPageDTOs[0].name);
assertArrayEquals(new String[] { NoSuchElementException.class.getName() }, contextDTO.errorPageDTOs[0].exceptions);
assertArrayEquals(new long[] { 404 }, contextDTO.errorPageDTOs[0].errorCodes);
// register second error page
registerErrorPage("error page 2", asList("500", ServletException.class.getName()));
RuntimeDTO runtimeDTOWithBothErrorPages = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithBothErrorPages.failedServletDTOs.length);
assertEquals(0, runtimeDTOWithBothErrorPages.failedErrorPageDTOs.length);
contextDTO = assertDefaultContext(runtimeDTOWithBothErrorPages);
assertEquals(2, contextDTO.errorPageDTOs.length);
assertEquals("error page 1", contextDTO.errorPageDTOs[0].name);
assertEquals("error page 2", contextDTO.errorPageDTOs[1].name);
assertArrayEquals(new String[] { ServletException.class.getName() }, contextDTO.errorPageDTOs[1].exceptions);
assertArrayEquals(new long[] { 500 }, contextDTO.errorPageDTOs[1].errorCodes);
}
@Test
public void dtosForSuccesfullyRegisteredErrorPageForClientErrorCodes() throws Exception
{
dtosForSuccesfullyRegisteredErrorPageWithWildcardErrorCode("4xx", 400);
}
@Test
public void dtosForSuccesfullyRegisteredErrorPageForClientErrorCodesCaseInsensitive() throws Exception
{
dtosForSuccesfullyRegisteredErrorPageWithWildcardErrorCode("4xX", 400);
}
@Test
public void dtosForSuccesfullyRegisteredErrorPageForServerErrorCodes() throws Exception
{
dtosForSuccesfullyRegisteredErrorPageWithWildcardErrorCode("5xx", 500);
}
@Test
public void dtosForSuccesfullyRegisteredErrorPageForServerErrorCodesCaseInsensitive() throws Exception
{
dtosForSuccesfullyRegisteredErrorPageWithWildcardErrorCode("5XX", 500);
}
public void dtosForSuccesfullyRegisteredErrorPageWithWildcardErrorCode(String code, long startCode) throws Exception
{
registerErrorPage("error page 1", asList(code));
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithErrorPage = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithErrorPage.failedServletDTOs.length);
assertEquals(0, runtimeDTOWithErrorPage.failedErrorPageDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithErrorPage);
assertEquals(1, contextDTO.errorPageDTOs.length);
assertEquals("error page 1", contextDTO.errorPageDTOs[0].name);
assertContainsAllHundredFrom(startCode, contextDTO.errorPageDTOs[0].errorCodes);
}
private void assertContainsAllHundredFrom(Long start, long[] errorCodes)
{
assertEquals(100, errorCodes.length);
SortedSet<Long> distinctErrorCodes = new TreeSet<>();
for (Long code : errorCodes)
{
distinctErrorCodes.add(code);
}
assertEquals(100, distinctErrorCodes.size());
assertEquals(start, distinctErrorCodes.first());
assertEquals(Long.valueOf(start + 99), distinctErrorCodes.last());
}
@Test
public void dtosForSuccesfullyRegisteredListeners() throws Exception
{
// register a servlet context listenere as first listener
registerListener(ServletContextListener.class, true);
awaitService(ServletContextListener.class.getName());
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstListener = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithFirstListener.failedListenerDTOs.length);
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTOWithFirstListener);
assertEquals(1, contextDTO.listenerDTOs.length);
assertEquals(ServletContextListener.class.getName(), contextDTO.listenerDTOs[0].types[0]);
// register all other listener types
registerListener(ServletContextAttributeListener.class, true);
registerListener(ServletRequestListener.class, true);
registerListener(ServletRequestAttributeListener.class, true);
registerListener(HttpSessionListener.class, true);
registerListener(HttpSessionAttributeListener.class, true);
awaitService(ServletContextAttributeListener.class.getName());
awaitService(ServletRequestListener.class.getName());
awaitService(ServletRequestAttributeListener.class.getName());
awaitService(HttpSessionListener.class.getName());
awaitService(HttpSessionAttributeListener.class.getName());
RuntimeDTO runtimeDTOWithAllListeners = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithAllListeners.failedListenerDTOs.length);
contextDTO = assertDefaultContext(runtimeDTOWithAllListeners);
assertEquals(6, contextDTO.listenerDTOs.length);
assertEquals(ServletContextListener.class.getName(), contextDTO.listenerDTOs[0].types[0]);
assertEquals(ServletContextAttributeListener.class.getName(), contextDTO.listenerDTOs[1].types[0]);
assertEquals(ServletRequestListener.class.getName(), contextDTO.listenerDTOs[2].types[0]);
assertEquals(ServletRequestAttributeListener.class.getName(), contextDTO.listenerDTOs[3].types[0]);
assertEquals(HttpSessionListener.class.getName(), contextDTO.listenerDTOs[4].types[0]);
assertEquals(HttpSessionAttributeListener.class.getName(), contextDTO.listenerDTOs[5].types[0]);
}
@Test
public void dtosForSuccesfullyRegisteredContexts() throws Exception
{
// register first additional context
registerContext("contextA", "/contextA");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithAdditionalContext = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithAdditionalContext.failedServletContextDTOs.length);
assertEquals(3, runtimeDTOWithAdditionalContext.servletContextDTOs.length);
// default context is last, as it has the lowest service ranking
assertEquals(HTTP_CONTEXT_NAME, runtimeDTOWithAdditionalContext.servletContextDTOs[0].name);
assertEquals("", runtimeDTOWithAdditionalContext.servletContextDTOs[0].contextPath);
assertEquals("contextA", runtimeDTOWithAdditionalContext.servletContextDTOs[1].name);
assertEquals("/contextA", runtimeDTOWithAdditionalContext.servletContextDTOs[1].contextPath);
assertEquals("default", runtimeDTOWithAdditionalContext.servletContextDTOs[2].name);
// TODO should this be "/" ?
assertEquals("", runtimeDTOWithAdditionalContext.servletContextDTOs[2].contextPath);
// register second additional context
registerContext("contextB", "/contextB");
RuntimeDTO runtimeDTOWithAllContexts = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTOWithAllContexts.failedServletContextDTOs.length);
assertEquals(4, runtimeDTOWithAllContexts.servletContextDTOs.length);
// default context is last, as it has the lowest service ranking
assertEquals(HTTP_CONTEXT_NAME, runtimeDTOWithAdditionalContext.servletContextDTOs[0].name);
assertEquals("", runtimeDTOWithAdditionalContext.servletContextDTOs[0].contextPath);
assertEquals("contextA", runtimeDTOWithAllContexts.servletContextDTOs[1].name);
assertEquals("/contextA", runtimeDTOWithAllContexts.servletContextDTOs[1].contextPath);
assertEquals("contextB", runtimeDTOWithAllContexts.servletContextDTOs[2].name);
assertEquals("/contextB", runtimeDTOWithAllContexts.servletContextDTOs[2].contextPath);
assertEquals("default", runtimeDTOWithAllContexts.servletContextDTOs[3].name);
assertEquals("", runtimeDTOWithAllContexts.servletContextDTOs[3].contextPath);
}
@Test
public void successfulSetup() throws InterruptedException
{
CountDownLatch initLatch = new CountDownLatch(6);
registerContext("test-context", "/test-context");
registerServlet("default servlet", "/default", initLatch);
registerFilter("default filter", "/default", initLatch);
registerErrorPage("default error page", asList(Exception.class.getName()), initLatch);
registerResource("/", "/default/resource");
registerListener(ServletRequestListener.class, true);
registerServlet("context servlet", "/default", "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)", initLatch);
registerFilter("context filter", "/default", "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)", initLatch);
registerErrorPage("context error page", asList("500"), "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)", initLatch);
registerResource("/", "/test-contextd/resource", "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)");
registerListener(ServletRequestListener.class, true, "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)");
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedErrorPageDTOs.length);
assertEquals(0, runtimeDTO.failedFilterDTOs.length);
assertEquals(0, runtimeDTO.failedListenerDTOs.length);
assertEquals(0, runtimeDTO.failedResourceDTOs.length);
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
assertEquals(0, runtimeDTO.failedServletDTOs.length);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals("test-context", runtimeDTO.servletContextDTOs[1].name);
assertEquals("default", runtimeDTO.servletContextDTOs[2].name);
ServletContextDTO defaultContextDTO = runtimeDTO.servletContextDTOs[2];
long contextServiceId = defaultContextDTO.serviceId;
assertEquals(Arrays.toString(defaultContextDTO.servletDTOs), 2, defaultContextDTO.servletDTOs.length);
assertServlet(defaultContextDTO.servletDTOs, "default servlet", contextServiceId);
assertServlet(defaultContextDTO.servletDTOs, "default error page", contextServiceId);
assertEquals(1, defaultContextDTO.filterDTOs.length);
assertEquals("default filter", defaultContextDTO.filterDTOs[0].name);
assertEquals(contextServiceId, defaultContextDTO.filterDTOs[0].servletContextId);
assertEquals(1, defaultContextDTO.errorPageDTOs.length);
assertEquals(Exception.class.getName(), defaultContextDTO.errorPageDTOs[0].exceptions[0]);
assertEquals(contextServiceId, defaultContextDTO.errorPageDTOs[0].servletContextId);
assertEquals(1, defaultContextDTO.listenerDTOs.length);
assertEquals(ServletRequestListener.class.getName(), defaultContextDTO.listenerDTOs[0].types[0]);
assertEquals(contextServiceId, defaultContextDTO.listenerDTOs[0].servletContextId);
ServletContextDTO testContextDTO = runtimeDTO.servletContextDTOs[1];
contextServiceId = testContextDTO.serviceId;
assertEquals(2, testContextDTO.servletDTOs.length);
assertServlet(testContextDTO.servletDTOs, "context servlet", contextServiceId);
assertServlet(testContextDTO.servletDTOs, "context error page", contextServiceId);
assertEquals(1, testContextDTO.filterDTOs.length);
assertEquals("context filter", testContextDTO.filterDTOs[0].name);
assertEquals(contextServiceId, testContextDTO.filterDTOs[0].servletContextId);
assertEquals(1, testContextDTO.errorPageDTOs.length);
assertEquals(500L, testContextDTO.errorPageDTOs[0].errorCodes[0]);
assertEquals(contextServiceId, testContextDTO.errorPageDTOs[0].servletContextId);
assertEquals(1, testContextDTO.listenerDTOs.length);
assertEquals(ServletRequestListener.class.getName(), testContextDTO.listenerDTOs[0].types[0]);
assertEquals(contextServiceId, testContextDTO.listenerDTOs[0].servletContextId);
}
private void assertServlet(final ServletDTO[] servletDTOs,
final String name,
final long contextServiceId)
{
assertNotNull(servletDTOs);
for(final ServletDTO dto : servletDTOs)
{
if ( name.equals(dto.name) && contextServiceId == dto.servletContextId )
{
return;
}
}
fail("Servlet with name " + name + " and context id " + contextServiceId + " not found in " + Arrays.toString(servletDTOs));
}
@Test
public void exceptionInServletInitAppearsAsFailure() throws ServletException, InterruptedException
{
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet");
CountDownLatch initLatch = new CountDownLatch(1);
@SuppressWarnings("serial")
Servlet failingServlet = new TestServlet(initLatch, null) {
@Override
public void init() throws ServletException
{
super.init();
throw new ServletException();
}
};
registrations.add(m_context.registerService(Servlet.class.getName(), failingServlet, properties));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletDTOs.length);
assertEquals("servlet", runtimeDTO.failedServletDTOs[0].name);
assertEquals(FAILURE_REASON_EXCEPTION_ON_INIT, runtimeDTO.failedServletDTOs[0].failureReason);
}
@Test
public void exceptionInServletInitDuringServletRemovalAppearsAsFailure() throws ServletException, InterruptedException
{
Dictionary<String, ?> properties1 = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet1",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet1");
final CountDownLatch initLatch1 = new CountDownLatch(1);
@SuppressWarnings("serial")
Servlet failingServlet1 = new TestServlet(initLatch1, null) {
@Override
public void init() throws ServletException
{
//fail when initialized the second time
if (initLatch1.getCount() == 0)
{
throw new ServletException();
}
super.init();
}
};
Dictionary<String, ?> properties2 = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet2",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet2");
final CountDownLatch initLatch2 = new CountDownLatch(1);
@SuppressWarnings("serial")
Servlet failingServlet2 = new TestServlet(initLatch2, null) {
@Override
public void init() throws ServletException
{
//fail when initialized the second time
if (initLatch2.getCount() == 0)
{
throw new ServletException();
}
super.init();
}
};
Dictionary<String, ?> propertiesShadowing = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, asList("/servlet1", "/servlet2"),
HTTP_WHITEBOARD_SERVLET_NAME, "servletShadowing",
SERVICE_RANKING, Integer.MAX_VALUE);
CountDownLatch initLatchShadowing = new CountDownLatch(1);
Servlet servletShadowing = new TestServlet(initLatchShadowing, null);
registrations.add(m_context.registerService(Servlet.class.getName(), failingServlet1, properties1));
registrations.add(m_context.registerService(Servlet.class.getName(), failingServlet2, properties2));
awaitServiceRegistration(initLatch1);
awaitServiceRegistration(initLatch2);
ServiceRegistration<?> shadowingRegistration = m_context.registerService(Servlet.class.getName(), servletShadowing, propertiesShadowing);
registrations.add(shadowingRegistration);
awaitServiceRegistration(initLatchShadowing);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(2, runtimeDTO.failedServletDTOs.length);
assertEquals(FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, runtimeDTO.failedServletDTOs[0].failureReason);
assertEquals(FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, runtimeDTO.failedServletDTOs[1].failureReason);
shadowingRegistration.unregister();
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(2, runtimeDTO.failedServletDTOs.length);
assertEquals(FAILURE_REASON_EXCEPTION_ON_INIT, runtimeDTO.failedServletDTOs[0].failureReason);
assertEquals(FAILURE_REASON_EXCEPTION_ON_INIT, runtimeDTO.failedServletDTOs[1].failureReason);
}
@Test
public void exceptionInFilterInitAppearsAsFailure() throws ServletException, InterruptedException
{
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_FILTER_PATTERN, "/filter",
HTTP_WHITEBOARD_FILTER_NAME, "filter");
CountDownLatch initLatch = new CountDownLatch(1);
Filter failingFilter = new TestFilter(initLatch, null) {
@Override
public void init(FilterConfig config) throws ServletException
{
super.init(config);
throw new ServletException();
}
};
registrations.add(m_context.registerService(Filter.class.getName(), failingFilter, properties));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedFilterDTOs.length);
assertEquals("filter", runtimeDTO.failedFilterDTOs[0].name);
assertEquals(FAILURE_REASON_EXCEPTION_ON_INIT, runtimeDTO.failedFilterDTOs[0].failureReason);
}
// As specified in OSGi Compendium Release 6, Chapter 140.1 (TODO : exact version)
@Test
public void hiddenDefaultContextAppearsAsFailure() throws InterruptedException
{
registerContext("default", "");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals("default", runtimeDTO.failedServletContextDTOs[0].name);
assertDefaultContext(runtimeDTO);
}
// As specified in OSGi Compendium Release 6, Chapter 140.1
@Test
public void contextHelperWithDuplicateNameAppearsAsFailure() throws InterruptedException
{
ServiceRegistration<?> firstContextReg = registerContext("contextA", "/first");
registerContext("contextA", "/second");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals("contextA", runtimeDTO.failedServletContextDTOs[0].name);
assertEquals("/second", runtimeDTO.failedServletContextDTOs[0].contextPath);
assertEquals(FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, runtimeDTO.failedServletContextDTOs[0].failureReason);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals("default", runtimeDTO.servletContextDTOs[2].name);
assertEquals("contextA", runtimeDTO.servletContextDTOs[1].name);
assertEquals("/first", runtimeDTO.servletContextDTOs[1].contextPath);
firstContextReg.unregister();
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals("default", runtimeDTO.servletContextDTOs[2].name);
assertEquals("contextA", runtimeDTO.servletContextDTOs[1].name);
assertEquals("/second", runtimeDTO.servletContextDTOs[1].contextPath);
}
// As specified in OSGi Compendium Release 6, Chapter 140.1
@Test
public void missingContextHelperNameAppearsAsFailure()
{
Dictionary<String, ?> properties = createDictionary(HTTP_WHITEBOARD_CONTEXT_PATH, "");
registrations.add(m_context.registerService(ServletContextHelper.class.getName(), mock(ServletContextHelper.class), properties));
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals(null, runtimeDTO.failedServletContextDTOs[0].name);
assertEquals(FAILURE_REASON_VALIDATION_FAILED, runtimeDTO.failedServletContextDTOs[0].failureReason);
}
// As specified in OSGi Compendium Release 6, Chapter 140.1
@Test
public void invalidContextHelperNameAppearsAsFailure() throws InterruptedException
{
registerContext("context A", "");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals("context A", runtimeDTO.failedServletContextDTOs[0].name);
assertEquals(FAILURE_REASON_VALIDATION_FAILED, runtimeDTO.failedServletContextDTOs[0].failureReason);
}
// As specified in OSGi Compendium Release 6, Chapter 140.1
@Test
public void invalidContextHelperPathAppearsAsFailure() throws InterruptedException
{
registerContext("contextA", "#");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals("#", runtimeDTO.failedServletContextDTOs[0].contextPath);
assertEquals(FAILURE_REASON_VALIDATION_FAILED, runtimeDTO.failedServletContextDTOs[0].failureReason);
}
// As specified in OSGi Compendium Release 6, Chapter 140.3
@Test
public void selectionOfNonExistingContextHelperAppearsAsFailure() throws InterruptedException
{
registerServlet("servlet 1", "/", "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=contextA)", null);
awaitServiceRegistration();
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletDTOs.length);
assertEquals("servlet 1", runtimeDTO.failedServletDTOs[0].name);
assertEquals(FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING, runtimeDTO.failedServletDTOs[0].failureReason);
registerContext("contextA", "/contextA");
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals("contextA", runtimeDTO.servletContextDTOs[1].name);
assertEquals(1, runtimeDTO.servletContextDTOs[1].servletDTOs.length);
assertEquals("servlet 1", runtimeDTO.servletContextDTOs[1].servletDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.3
@Test
public void differentTargetIsIgnored() throws InterruptedException
{
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet",
HTTP_WHITEBOARD_TARGET, "(org.osgi.service.http.port=8282)");
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(), properties));
awaitServiceRegistration();
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(0, defaultContext.servletDTOs.length);
}
// As specified in OSGi Compendium Release 6, Chapter 140.4
@Test
public void servletWithoutNameGetsFullyQualifiedName() throws InterruptedException
{
Dictionary<String, ?> properties = createDictionary(HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet");
CountDownLatch initLatch = new CountDownLatch(1);
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(initLatch, null), properties));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(serviceRuntime.getRuntimeDTO());
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals(TestServlet.class.getName(), defaultContext.servletDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.4.1
@Test
public void patternAndErrorPageSpecified() throws InterruptedException
{
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/servlet",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet",
HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, asList("400"));
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(), properties));
awaitServiceRegistration();
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(0, runtimeDTO.failedErrorPageDTOs.length);
assertEquals(0, runtimeDTO.failedServletDTOs.length);
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals(1, defaultContext.errorPageDTOs.length);
assertEquals("servlet", defaultContext.servletDTOs[0].name);
assertEquals("servlet", defaultContext.errorPageDTOs[0].name);
assertArrayEquals(new String[] { "/servlet" }, defaultContext.servletDTOs[0].patterns);
assertArrayEquals(new long[] { 400 }, defaultContext.errorPageDTOs[0].errorCodes);
}
// As specified in OSGi Compendium Release 6, Chapter 140.4.1
@Test
public void multipleServletsForSamePatternChoosenByServiceRankingRules() throws InterruptedException
{
registerServlet("servlet 1", "/pathcollision");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(1, defaultContext.servletDTOs.length);
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/pathcollision",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet 2",
SERVICE_RANKING, Integer.MAX_VALUE);
CountDownLatch initLatch = new CountDownLatch(1);
CountDownLatch destroyLatch = new CountDownLatch(1);
TestServlet testServlet = new TestServlet(initLatch, destroyLatch);
ServiceRegistration<?> higherRankingServlet = m_context.registerService(Servlet.class.getName(), testServlet, properties);
registrations.add(higherRankingServlet);
RuntimeDTO runtimeWithShadowedServlet = serviceRuntime.getRuntimeDTO();
awaitServiceRegistration(initLatch);
defaultContext = assertDefaultContext(runtimeWithShadowedServlet);
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals(1, runtimeWithShadowedServlet.failedServletDTOs.length);
FailedServletDTO failedServletDTO = runtimeWithShadowedServlet.failedServletDTOs[0];
assertEquals("servlet 1", failedServletDTO.name);
assertEquals(FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, failedServletDTO.failureReason);
higherRankingServlet.unregister();
awaitServiceRegistration(destroyLatch);
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals("servlet 1", defaultContext.servletDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.4.1
@Test
public void multipleErrorPagesForSameErrorCodeChoosenByServiceRankingRules() throws InterruptedException
{
registerErrorPage("error page 1", asList(NullPointerException.class.getName(), "500"));
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(0, runtimeDTO.failedErrorPageDTOs.length);
assertEquals(1, defaultContext.errorPageDTOs.length);
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, asList("500", IllegalArgumentException.class.getName()),
HTTP_WHITEBOARD_SERVLET_NAME, "error page 2",
SERVICE_RANKING, Integer.MAX_VALUE);
CountDownLatch initLatch = new CountDownLatch(1);
CountDownLatch destroyLatch = new CountDownLatch(1);
TestServlet testServlet = new TestServlet(initLatch, destroyLatch);
ServiceRegistration<?> higherRankingServlet = m_context.registerService(Servlet.class.getName(), testServlet, properties);
registrations.add(higherRankingServlet);
awaitServiceRegistration(initLatch);
RuntimeDTO runtimeWithShadowedErrorPage = serviceRuntime.getRuntimeDTO();
defaultContext = assertDefaultContext(runtimeWithShadowedErrorPage);
assertEquals(2, defaultContext.errorPageDTOs.length);
assertEquals("error page 2", defaultContext.errorPageDTOs[0].name);
assertArrayEquals(new long[] { 500 }, defaultContext.errorPageDTOs[0].errorCodes);
assertArrayEquals(new String[] { IllegalArgumentException.class.getName() }, defaultContext.errorPageDTOs[0].exceptions);
assertEquals("error page 1", defaultContext.errorPageDTOs[1].name);
assertEquals(0, defaultContext.errorPageDTOs[1].errorCodes.length);
assertArrayEquals(new String[] { NullPointerException.class.getName() }, defaultContext.errorPageDTOs[1].exceptions);
assertEquals(1, runtimeWithShadowedErrorPage.failedErrorPageDTOs.length);
FailedErrorPageDTO failedErrorPageDTO = runtimeWithShadowedErrorPage.failedErrorPageDTOs[0];
assertEquals("error page 1", failedErrorPageDTO.name);
assertArrayEquals(new long[] { 500 }, failedErrorPageDTO.errorCodes);
assertEquals(0, failedErrorPageDTO.exceptions.length);
assertEquals(FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, failedErrorPageDTO.failureReason);
higherRankingServlet.unregister();
awaitServiceRegistration(destroyLatch);
runtimeDTO = serviceRuntime.getRuntimeDTO();
defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(0, runtimeDTO.failedErrorPageDTOs.length);
assertEquals(1, defaultContext.errorPageDTOs.length);
assertEquals("error page 1", defaultContext.errorPageDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.4
@Test
public void mulitpleServletsWithSamePatternHttpServiceRegistrationWins() throws Exception
{
registerServlet("servlet 1", "/pathcollision");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(1, defaultContext.servletDTOs.length);
CountDownLatch initLatch = new CountDownLatch(1);
CountDownLatch destroyLatch = new CountDownLatch(1);
TestServlet testServlet = new TestServlet(initLatch, destroyLatch);
register("/pathcollision", testServlet);
RuntimeDTO runtimeWithShadowedServlet = serviceRuntime.getRuntimeDTO();
awaitServiceRegistration(initLatch);
defaultContext = assertDefaultContext(runtimeWithShadowedServlet);
ServletContextDTO httpServiceContext = runtimeWithShadowedServlet.servletContextDTOs[0];
assertEquals(HTTP_CONTEXT_NAME, httpServiceContext.name);
assertEquals(1, httpServiceContext.servletDTOs.length);
assertArrayEquals(new String[] {"/pathcollision"}, httpServiceContext.servletDTOs[0].patterns);
assertEquals(1, defaultContext.servletDTOs.length);
ServletDTO servletDTO = defaultContext.servletDTOs[0];
assertEquals("servlet 1", servletDTO.name);
// check request info DTO to see which servlet responds
final RequestInfoDTO infoDTO = serviceRuntime.calculateRequestInfoDTO("/pathcollision");
assertEquals(httpServiceContext.serviceId, infoDTO.servletDTO.servletContextId);
unregister("/pathcollision");
awaitServiceRegistration(destroyLatch);
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals("servlet 1", defaultContext.servletDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.7
@Test
public void invalidListenerPopertyValueAppearsAsFailure() throws Exception
{
Dictionary<String, ?> properties = createDictionary(HTTP_WHITEBOARD_LISTENER, "invalid");
registrations.add(m_context.registerService(ServletRequestListener.class.getName(), mock(ServletRequestListener.class), properties));
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedListenerDTOs.length);
assertEquals(FAILURE_REASON_VALIDATION_FAILED, runtimeDTO.failedListenerDTOs[0].failureReason);
}
// As specified in OSGi Compendium Release 6, Chapter 140.8
@Test
public void contextReplacedWithHigherRankingContext() throws Exception
{
ServiceRegistration<?> firstContext = registerContext("test-context", "/first");
Long firstContextId = (Long) firstContext.getReference().getProperty(Constants.SERVICE_ID);
CountDownLatch initLatch = new CountDownLatch(1);
registerServlet("servlet", "/servlet", "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=test-context)", initLatch);
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals(firstContextId.longValue(), runtimeDTO.servletContextDTOs[1].serviceId);
assertEquals("test-context", runtimeDTO.servletContextDTOs[1].name);
assertEquals("/first", runtimeDTO.servletContextDTOs[1].contextPath);
assertEquals("default", runtimeDTO.servletContextDTOs[2].name);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals(1, runtimeDTO.servletContextDTOs[1].servletDTOs.length);
assertEquals("servlet", runtimeDTO.servletContextDTOs[1].servletDTOs[0].name);
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_CONTEXT_NAME, "test-context",
HTTP_WHITEBOARD_CONTEXT_PATH, "/second",
SERVICE_RANKING, Integer.MAX_VALUE);
ServiceRegistration<?> secondContext = m_context.registerService(ServletContextHelper.class.getName(), mock(ServletContextHelper.class), properties);
registrations.add(secondContext);
Long secondContextId = (Long) secondContext.getReference().getProperty(Constants.SERVICE_ID);
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(1, runtimeDTO.failedServletContextDTOs.length);
assertEquals(firstContextId.longValue(), runtimeDTO.failedServletContextDTOs[0].serviceId);
assertEquals("test-context", runtimeDTO.failedServletContextDTOs[0].name);
assertEquals("/first", runtimeDTO.failedServletContextDTOs[0].contextPath);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
final List<String> names = new ArrayList<>();
for(final ServletContextDTO dto : runtimeDTO.servletContextDTOs)
{
names.add(dto.name);
}
final int httpContextIndex = names.indexOf(HTTP_CONTEXT_NAME);
final int secondContextIndex = names.indexOf("test-context");
final int defaultContextIndex = names.indexOf("default");
assertEquals(secondContextId.longValue(), runtimeDTO.servletContextDTOs[secondContextIndex].serviceId);
assertEquals("test-context", runtimeDTO.servletContextDTOs[secondContextIndex].name);
assertEquals("/second", runtimeDTO.servletContextDTOs[secondContextIndex].contextPath);
assertEquals("default", runtimeDTO.servletContextDTOs[defaultContextIndex].name);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[httpContextIndex].name);
assertEquals(1, runtimeDTO.servletContextDTOs[secondContextIndex].servletDTOs.length);
assertEquals("servlet", runtimeDTO.servletContextDTOs[secondContextIndex].servletDTOs[0].name);
secondContext.unregister();
runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
assertEquals(3, runtimeDTO.servletContextDTOs.length);
assertEquals(firstContextId.longValue(), runtimeDTO.servletContextDTOs[1].serviceId);
assertEquals("test-context", runtimeDTO.servletContextDTOs[1].name);
assertEquals("/first", runtimeDTO.servletContextDTOs[1].contextPath);
assertEquals("default", runtimeDTO.servletContextDTOs[2].name);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals(1, runtimeDTO.servletContextDTOs[1].servletDTOs.length);
assertEquals("servlet", runtimeDTO.servletContextDTOs[1].servletDTOs[0].name);
}
// As specified in OSGi Compendium Release 6, Chapter 140.9
@Test
public void httpServiceIdIsSet()
{
ServiceReference<?> httpServiceRef = m_context.getServiceReference(HttpService.class.getName());
ServiceReference<?> httpServiceRuntimeRef = m_context.getServiceReference(HttpServiceRuntime.class.getName());
Long expectedId = (Long) httpServiceRef.getProperty(Constants.SERVICE_ID);
Collection col = (Collection)httpServiceRuntimeRef.getProperty(HTTP_SERVICE_ID);
Long actualId = (Long) col.iterator().next();
assertEquals(expectedId, actualId);
}
// As specified in OSGi Compendium Release 6, Chapter 140.9
@Test
public void serviceRegisteredWithHttpServiceHasNegativeServiceId() throws Exception
{
CountDownLatch initLatch = new CountDownLatch(1);
register("/test", new TestServlet(initLatch, null));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(2, runtimeDTO.servletContextDTOs.length);
assertEquals(1, runtimeDTO.servletContextDTOs[0].servletDTOs.length);
assertTrue(0 > runtimeDTO.servletContextDTOs[0].servletDTOs[0].serviceId);
}
@Test
public void namedServletIsNotIgnored() throws InterruptedException
{
// Neither pattern nor error page specified
Dictionary<String, ?> properties = createDictionary(HTTP_WHITEBOARD_SERVLET_NAME, "servlet");
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(), properties));
awaitServiceRegistration();
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletContextDTOs.length);
ServletContextDTO defaultContext = assertDefaultContext(runtimeDTO);
assertEquals(1, defaultContext.servletDTOs.length);
assertEquals(0, defaultContext.servletDTOs[0].patterns.length);
assertEquals("servlet", defaultContext.servletDTOs[0].name);
}
@Test
public void dtosAreIndependentCopies() throws Exception
{
//register first servlet
Dictionary<String, ?> properties = createDictionary(
HTTP_WHITEBOARD_SERVLET_PATTERN, "/test",
HTTP_WHITEBOARD_SERVLET_NAME, "servlet 1",
HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + "test", "testValue");
CountDownLatch initLatch = new CountDownLatch(1);
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(initLatch, null), properties));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTOWithFirstSerlvet = serviceRuntime.getRuntimeDTO();
//register second servlet
registerServlet("testServlet 2", "/servlet_2");
RuntimeDTO runtimeDTOWithTwoSerlvets = serviceRuntime.getRuntimeDTO();
assertNotSame(runtimeDTOWithFirstSerlvet, runtimeDTOWithTwoSerlvets);
ServletContextDTO defaultContextFirstServlet = assertDefaultContext(runtimeDTOWithFirstSerlvet);
ServletContextDTO defaultContextTwoServlets = assertDefaultContext(runtimeDTOWithTwoSerlvets);
assertNotSame(defaultContextFirstServlet.servletDTOs[0].patterns,
defaultContextTwoServlets.servletDTOs[0].patterns);
boolean mapsModifiable = true;
try
{
defaultContextTwoServlets.servletDTOs[0].initParams.clear();
} catch (UnsupportedOperationException e)
{
mapsModifiable = false;
}
if (mapsModifiable)
{
assertNotSame(defaultContextFirstServlet.servletDTOs[0].initParams,
defaultContextTwoServlets.servletDTOs[0].initParams);
}
}
@Test
public void requestInfoDTO() throws Exception
{
registerServlet("servlet", "/default");
registerFilter("filter1", "/default");
registerFilter("filter2", "/default");
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
ServletContextDTO defaultContext = assertDefaultContext(serviceRuntime.getRuntimeDTO());
long defaultContextId = defaultContext.serviceId;
RequestInfoDTO requestInfoDTO = serviceRuntime.calculateRequestInfoDTO("/default");
assertEquals("/default", requestInfoDTO.path);
assertEquals(defaultContextId, requestInfoDTO.servletContextId);
assertEquals("servlet", requestInfoDTO.servletDTO.name);
assertEquals(2, requestInfoDTO.filterDTOs.length);
assertEquals("filter1", requestInfoDTO.filterDTOs[0].name);
assertEquals("filter2", requestInfoDTO.filterDTOs[1].name);
}
@Test
public void serviceEndpointPropertyIsSet()
{
// if there is more than one network interface, there might be more than one endpoint!
final String[] endpoint = (String[]) m_context.getServiceReference(HttpServiceRuntime.class).getProperty(HTTP_SERVICE_ENDPOINT);
assertNotNull(endpoint);
assertTrue(Arrays.toString(endpoint), endpoint.length > 0);
assertTrue(endpoint[0].startsWith("http://"));
assertTrue(endpoint[0].endsWith(":8080/"));
}
/**
* Test for FELIX-5319
* @throws Exception
*/
@Test
public void testCombinedServletAndResourceRegistration() throws Exception
{
// register single component as Servlet and Resource
final String servletPath = "/hello/sayHello";
final String servletName = "Hello World";
final String rsrcPattern = "/hello/static/*";
final String rsrcPrefix = "/static";
CountDownLatch initLatch = new CountDownLatch(1);
List<Object> propertyEntries = Arrays.<Object>asList(
HTTP_WHITEBOARD_SERVLET_PATTERN, servletPath,
HTTP_WHITEBOARD_SERVLET_NAME, servletName,
HTTP_WHITEBOARD_RESOURCE_PATTERN, rsrcPattern,
HTTP_WHITEBOARD_RESOURCE_PREFIX, rsrcPrefix);
Dictionary<String, ?> properties = createDictionary(propertyEntries.toArray());
registrations.add(m_context.registerService(Servlet.class.getName(), new TestServlet(initLatch, null), properties));
awaitServiceRegistration(initLatch);
HttpServiceRuntime serviceRuntime = (HttpServiceRuntime) getService(HttpServiceRuntime.class.getName());
assertNotNull("HttpServiceRuntime unavailable", serviceRuntime);
RuntimeDTO runtimeDTO = serviceRuntime.getRuntimeDTO();
assertEquals(0, runtimeDTO.failedServletDTOs.length);
assertEquals(0, runtimeDTO.failedResourceDTOs.length);
// check servlet registration
ServletContextDTO contextDTO = assertDefaultContext(runtimeDTO);
assertEquals(1, contextDTO.servletDTOs.length);
assertEquals(servletName, contextDTO.servletDTOs[0].name);
assertEquals(1, contextDTO.servletDTOs[0].patterns.length);
assertEquals(servletPath, contextDTO.servletDTOs[0].patterns[0]);
// check resource registration
assertEquals(1, contextDTO.resourceDTOs.length);
assertEquals(1, contextDTO.resourceDTOs[0].patterns.length);
assertEquals(rsrcPattern, contextDTO.resourceDTOs[0].patterns[0]);
assertEquals(rsrcPrefix, contextDTO.resourceDTOs[0].prefix);
}
private ServletContextDTO assertDefaultContext(RuntimeDTO runtimeDTO)
{
assertTrue(1 < runtimeDTO.servletContextDTOs.length);
assertEquals(HTTP_CONTEXT_NAME, runtimeDTO.servletContextDTOs[0].name);
assertEquals("default", runtimeDTO.servletContextDTOs[1].name);
return runtimeDTO.servletContextDTOs[1];
}
private void awaitServiceRegistration() throws InterruptedException
{
// Wait some time until the whiteboard (hopefully) picked up the service
Thread.sleep(DEFAULT_SLEEP);
}
private void awaitServiceRegistration(CountDownLatch initLatch) throws InterruptedException
{
if (!initLatch.await(5, TimeUnit.SECONDS))
{
fail("Service was not initialized in time!");
};
awaitServiceRegistration();
}
public static class TestResource
{
// Tagging class
}
}