/* * 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.verify; import static org.mockito.Mockito.when; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashSet; import java.util.Set; 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.DTOConstants; import org.osgi.service.http.runtime.dto.FailedErrorPageDTO; import org.osgi.service.http.runtime.dto.ServletContextDTO; import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; public class ErrorPageRegistryTest { private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder) { assertNull(dto.servletDTOs); assertNull(dto.resourceDTOs); assertNull(dto.errorPageDTOs); assertTrue(holder.failedErrorPageDTOs.isEmpty()); } private void clear(final ServletContextDTO dto, final FailedDTOHolder holder) { dto.servletDTOs = null; dto.resourceDTOs = null; dto.errorPageDTOs = null; holder.failedErrorPageDTOs.clear(); } @Test public void testSingleErrorPage() throws InvalidSyntaxException, ServletException { final ErrorPageRegistry reg = new ErrorPageRegistry(); final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); // empty reg reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertEmpty(dto, holder); // register error page final ServletHandler h1 = createServletHandler(1L, 0, "404", "java.io.IOException"); reg.addServlet(h1); verify(h1.getServlet()).init(Matchers.any(ServletConfig.class)); // one entry in reg clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertNull(dto.resourceDTOs); assertNull(dto.servletDTOs); assertNotNull(dto.errorPageDTOs); assertEquals(1, dto.errorPageDTOs.length); assertEquals(1L, dto.errorPageDTOs[0].serviceId); assertEquals(1, dto.errorPageDTOs[0].errorCodes.length); assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]); assertEquals(1, dto.errorPageDTOs[0].exceptions.length); assertEquals("java.io.IOException", dto.errorPageDTOs[0].exceptions[0]); assertTrue(holder.failedErrorPageDTOs.isEmpty()); // test error handling assertNotNull(reg.get(new IOException(), 404)); assertNotNull(reg.get(new RuntimeException(), 404)); assertNotNull(reg.get(new IOException(), 500)); assertNotNull(reg.get(new FileNotFoundException(), 500)); assertNull(reg.get(new RuntimeException(), 500)); // remove servlet final Servlet s = h1.getServlet(); reg.removeServlet(h1.getServletInfo(), true); verify(s).destroy(); // empty again clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertEmpty(dto, holder); } @Test public void testSimpleHiding() throws InvalidSyntaxException, ServletException { final ErrorPageRegistry reg = new ErrorPageRegistry(); final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); // check DTO reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertEmpty(dto, holder); // register error pages final ServletHandler h1 = createServletHandler(1L, 0, "404", "java.io.IOException"); reg.addServlet(h1); final ServletHandler h2 = createServletHandler(2L, 10, "404", "some.other.Exception"); reg.addServlet(h2); verify(h1.getServlet()).init(Matchers.any(ServletConfig.class)); verify(h2.getServlet()).init(Matchers.any(ServletConfig.class)); // two entries in DTO clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertNull(dto.resourceDTOs); assertNull(dto.servletDTOs); assertNotNull(dto.errorPageDTOs); assertEquals(2, dto.errorPageDTOs.length); assertEquals(0, dto.errorPageDTOs[1].errorCodes.length); assertEquals(1, dto.errorPageDTOs[0].errorCodes.length); assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]); assertEquals(1, dto.errorPageDTOs[1].exceptions.length); assertEquals(1, dto.errorPageDTOs[0].exceptions.length); assertEquals("java.io.IOException", dto.errorPageDTOs[1].exceptions[0]); assertEquals("some.other.Exception", dto.errorPageDTOs[0].exceptions[0]); assertEquals(1, holder.failedErrorPageDTOs.size()); assertEquals(1L, holder.failedErrorPageDTOs.get(0).serviceId); assertEquals(1, holder.failedErrorPageDTOs.get(0).errorCodes.length); assertEquals(404, holder.failedErrorPageDTOs.get(0).errorCodes[0]); assertEquals(0, holder.failedErrorPageDTOs.get(0).exceptions.length); assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, holder.failedErrorPageDTOs.get(0).failureReason); // remove second page final Servlet s2 = h2.getServlet(); reg.removeServlet(h2.getServletInfo(), true); verify(s2).destroy(); // one entry in DTO clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertNull(dto.resourceDTOs); assertNull(dto.servletDTOs); assertNotNull(dto.errorPageDTOs); assertEquals(1, dto.errorPageDTOs.length); assertEquals(1, dto.errorPageDTOs[0].errorCodes.length); assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]); assertEquals(1, dto.errorPageDTOs[0].exceptions.length); assertEquals("java.io.IOException", dto.errorPageDTOs[0].exceptions[0]); assertTrue(holder.failedErrorPageDTOs.isEmpty()); // test error handling assertNotNull(reg.get(new IOException(), 404)); assertNotNull(reg.get(new RuntimeException(), 404)); assertNotNull(reg.get(new IOException(), 500)); assertNotNull(reg.get(new FileNotFoundException(), 500)); assertNull(reg.get(new RuntimeException(), 500)); // remove first page final Servlet s1 = h1.getServlet(); reg.removeServlet(h1.getServletInfo(), true); verify(s1).destroy(); // empty again clear(dto, holder); reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertEmpty(dto, holder); } @Test public void testRangeRegistration() throws InvalidSyntaxException { final ErrorPageRegistry reg = new ErrorPageRegistry(); final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); final ServletHandler handler4 = createServletHandler(1L, 0, "4xx"); final ServletHandler handler5 = createServletHandler(2L, 0, "5xx"); reg.addServlet(handler4); reg.addServlet(handler5); // check DTO reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); assertTrue(holder.failedErrorPageDTOs.isEmpty()); assertEquals(2, dto.errorPageDTOs.length); assertEquals(100, dto.errorPageDTOs[0].errorCodes.length); final Set<Long> codes4 = new HashSet<Long>(); for(final long c : dto.errorPageDTOs[0].errorCodes) { assertTrue(c >= 400 && c < 500); codes4.add(c); } assertEquals(100, codes4.size()); assertEquals(100, dto.errorPageDTOs[1].errorCodes.length); final Set<Long> codes5 = new HashSet<Long>(); for(final long c : dto.errorPageDTOs[1].errorCodes) { assertTrue(c >= 500 && c < 600); codes5.add(c); } assertEquals(100, codes5.size()); } @Test public void testRangeRegistrationOverlay() throws InvalidSyntaxException { final ErrorPageRegistry reg = new ErrorPageRegistry(); final FailedDTOHolder holder = new FailedDTOHolder(); final ServletContextDTO dto = new ServletContextDTO(); final ServletHandler handler4 = createServletHandler(1L, 0, "4xx"); final ServletHandler handler = createServletHandler(2L, 10, "404", "403"); reg.addServlet(handler4); reg.addServlet(handler); // check DTO reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs); // a 4xx is only registered as failure DTO if overlayed by a 4xx! // -> no failure in this case assertEquals(0, holder.failedErrorPageDTOs.size()); final Set<Long> codes4 = new HashSet<Long>(); for(final long c : dto.errorPageDTOs[1].errorCodes) { assertTrue(c >= 400 && c < 500); codes4.add(c); } assertEquals(98, codes4.size()); assertFalse(codes4.contains(404L)); assertFalse(codes4.contains(403L)); assertEquals(2, dto.errorPageDTOs[0].errorCodes.length); final Set<Long> codes = new HashSet<Long>(); for(final long c : dto.errorPageDTOs[0].errorCodes) { assertTrue(c >= 403 && c < 405); codes.add(c); } assertEquals(2, codes.size()); } private static ServletInfo createServletInfo(final long id, final int ranking, final String... codes) 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); @SuppressWarnings("unchecked") 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_ERROR_PAGE)).thenReturn(codes); 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... codes) throws InvalidSyntaxException { final ServletInfo si = createServletInfo(id, ranking, codes); final ExtServletContext ctx = mock(ExtServletContext.class); final Servlet servlet = mock(Servlet.class); return new HttpServiceServletHandler(ctx, si, servlet); } }