/* * 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.registry; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import org.apache.felix.http.base.internal.context.ExtServletContext; import org.apache.felix.http.base.internal.handler.HttpServiceServletHandler; import org.apache.felix.http.base.internal.handler.ServletHandler; import org.apache.felix.http.base.internal.runtime.ServletInfo; import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder; import org.junit.Test; import org.mockito.Matchers; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.http.runtime.dto.FailedServletDTO; import org.osgi.service.http.runtime.dto.ServletContextDTO; import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; public class ServletRegistryTest { private final ServletRegistry reg = new ServletRegistry(); private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder) { assertNull(dto.servletDTOs); assertNull(dto.resourceDTOs); assertTrue(holder.failedResourceDTOs.isEmpty()); assertTrue(holder.failedServletDTOs.isEmpty()); } private void clear(final ServletContextDTO dto, final FailedDTOHolder holder) { dto.servletDTOs = null; dto.resourceDTOs = null; holder.failedResourceDTOs.clear(); holder.failedServletDTOs.clear(); } @Test public void testSingleServlet() throws InvalidSyntaxException, ServletException { final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); // empty reg reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertEmpty(dto, holder); // register servlet final ServletHandler h1 = createServletHandler(1L, 0, "/foo"); reg.addServlet(h1); verify(h1.getServlet()).init(Matchers.any(ServletConfig.class)); // one entry in reg // check DTO clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertNull(dto.resourceDTOs); assertTrue(holder.failedResourceDTOs.isEmpty()); assertTrue(holder.failedServletDTOs.isEmpty()); assertNotNull(dto.servletDTOs); assertEquals(1, dto.servletDTOs.length); assertEquals(1, dto.servletDTOs[0].patterns.length); assertEquals("/foo", dto.servletDTOs[0].patterns[0]); // remove servlet final Servlet s = h1.getServlet(); reg.removeServlet(h1.getServletInfo(), true); verify(s).destroy(); // empty again clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertEmpty(dto, holder); } @Test public void testSimpleHiding() throws InvalidSyntaxException, ServletException { final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); // empty reg reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertEmpty(dto, holder); // register servlets final ServletHandler h1 = createServletHandler(1L, 10, "/foo"); reg.addServlet(h1); verify(h1.getServlet()).init(Matchers.any(ServletConfig.class)); final ServletHandler h2 = createServletHandler(2L, 0, "/foo"); reg.addServlet(h2); verify(h2.getServlet(), never()).init(Matchers.any(ServletConfig.class)); verify(h1.getServlet(), never()).destroy(); // two entries in reg // h1 is active // h2 is hidden clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertNull(dto.resourceDTOs); assertTrue(holder.failedResourceDTOs.isEmpty()); assertFalse(holder.failedServletDTOs.isEmpty()); assertNotNull(dto.servletDTOs); assertEquals(1, dto.servletDTOs.length); assertEquals(1, dto.servletDTOs[0].patterns.length); assertEquals("/foo", dto.servletDTOs[0].patterns[0]); assertEquals(1, dto.servletDTOs[0].serviceId); assertEquals(1, holder.failedServletDTOs.size()); final FailedServletDTO failedDTO = holder.failedServletDTOs.iterator().next(); assertEquals(1, failedDTO.patterns.length); assertEquals("/foo", failedDTO.patterns[0]); assertEquals(2, failedDTO.serviceId); // remove servlet 1 final Servlet s1 = h1.getServlet(); reg.removeServlet(h1.getServletInfo(), true); verify(s1).destroy(); verify(h2.getServlet()).init(Matchers.any(ServletConfig.class)); // h2 is active clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertNull(dto.resourceDTOs); assertTrue(holder.failedResourceDTOs.isEmpty()); assertTrue(holder.failedServletDTOs.isEmpty()); assertNotNull(dto.servletDTOs); assertEquals(1, dto.servletDTOs.length); assertEquals(1, dto.servletDTOs[0].patterns.length); assertEquals("/foo", dto.servletDTOs[0].patterns[0]); assertEquals(2, dto.servletDTOs[0].serviceId); // remove servlet 2 final Servlet s2 = h2.getServlet(); reg.removeServlet(h2.getServletInfo(), true); verify(s2).destroy(); // empty again clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedServletDTOs, holder.failedResourceDTOs); assertEmpty(dto, holder); } @Test public void testMatcherOrdering() throws InvalidSyntaxException { final ServletHandler h1 = createServletHandler(1L, 0, "/foo"); final ServletHandler h2 = createServletHandler(2L, 0, "/foo/*"); final List<PathResolver> resolvers = new ArrayList<PathResolver>(); resolvers.add(PathResolverFactory.createPatternMatcher(h1, "/foo")); resolvers.add(PathResolverFactory.createPatternMatcher(h2, "/foo/*")); Collections.sort(resolvers); assertEquals("/foo", resolvers.get(0).getPattern()); assertEquals("/foo/*", resolvers.get(1).getPattern()); } @Test public void testServletOrdering() throws InvalidSyntaxException { final ServletHandler h1 = createServletHandler(1L, 0, "/foo"); reg.addServlet(h1); final ServletHandler h2 = createServletHandler(2L, 0, "/foo/*"); reg.addServlet(h2); final ServletHandler h3 = createServletHandler(3L, 0, "/foo/rsrc"); reg.addServlet(h3); final ServletHandler h4 = createServletHandler(4L, 0, "/foo/rsrc/*"); reg.addServlet(h4); final ServletHandler h5 = createServletHandler(5L, 0, "/other"); reg.addServlet(h5); PathResolution pr = null; pr = reg.resolve("/foo"); assertNotNull(pr); assertEquals("/foo", pr.patterns[0]); assertEquals(h1, pr.handler); pr = reg.resolve("/fool"); assertNull(pr); pr = reg.resolve("/foo/bar"); assertEquals("/foo", pr.patterns[0]); assertEquals(h1, pr.handler); pr = reg.resolve("/foo/rsrc"); assertEquals("/foo/rsrc", pr.patterns[0]); assertEquals(h3, pr.handler); pr = reg.resolve("/foo/rsrc/some"); assertEquals("/foo/rsrc", pr.patterns[0]); assertEquals(h3, pr.handler); pr = reg.resolve("/other"); assertEquals("/other", pr.patterns[0]); assertEquals(h5, pr.handler); pr = reg.resolve("/other/bla"); assertEquals("/other", pr.patterns[0]); assertEquals(h5, pr.handler); // cleanup reg.removeServlet(h1.getServletInfo(), true); reg.removeServlet(h2.getServletInfo(), true); reg.removeServlet(h3.getServletInfo(), true); reg.removeServlet(h4.getServletInfo(), true); reg.removeServlet(h5.getServletInfo(), true); } private static ServletInfo createServletInfo(final long id, final int ranking, final String... paths) throws InvalidSyntaxException { final BundleContext bCtx = mock(BundleContext.class); when(bCtx.createFilter(Matchers.anyString())).thenReturn(null); final Bundle bundle = mock(Bundle.class); when(bundle.getBundleContext()).thenReturn(bCtx); final ServiceReference<Servlet> ref = mock(ServiceReference.class); when(ref.getBundle()).thenReturn(bundle); when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(id); when(ref.getProperty(Constants.SERVICE_RANKING)).thenReturn(ranking); when(ref.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN)).thenReturn(paths); when(ref.getPropertyKeys()).thenReturn(new String[0]); final ServletInfo si = new ServletInfo(ref); return si; } private static ServletHandler createServletHandler(final long id, final int ranking, final String... paths) throws InvalidSyntaxException { final ServletInfo si = createServletInfo(id, ranking, paths); final ExtServletContext ctx = mock(ExtServletContext.class); final Servlet servlet = mock(Servlet.class); return new HttpServiceServletHandler(ctx, si, servlet); } }