FELIX-4888 : ServletHandler's are not sorted by longest matching path. DTO handling (WiP)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1680349 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
index e719e7a..3ca94be 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
@@ -93,12 +93,17 @@
public final Set<String> exceptions = new TreeSet<String>();
}
- private static final class ErrorRegistrationStatus {
+ static final class ErrorRegistrationStatus {
ServletHandler handler;
final Map<Long, Integer> errorCodeMapping = new ConcurrentHashMap<Long, Integer>();
final Map<String, Integer> exceptionMapping = new ConcurrentHashMap<String, Integer>();
}
+ Map<ServletInfo, ErrorRegistrationStatus> getStatusMapping()
+ {
+ return this.statusMapping;
+ }
+
public static ErrorRegistration getErrorRegistration(@Nonnull final ServletInfo info)
{
if ( info.getErrorPage() != null )
@@ -340,7 +345,7 @@
* @param errorCode Error code
* @return The servlet handling the error or {@code null}
*/
- private ServletHandler get(final int errorCode)
+ private ServletHandler get(final long errorCode)
{
final List<ServletHandler> list = this.errorCodesMap.get(errorCode);
if ( list != null )
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageTest.java
new file mode 100644
index 0000000..f69244c
--- /dev/null
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.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.Map;
+
+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.ServletContextDTO;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public class ErrorPageTest {
+
+ private final ErrorPageRegistry reg = new ErrorPageRegistry();
+
+ 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 testSingleServlet() throws InvalidSyntaxException, ServletException
+ {
+ final FailedDTOHolder holder = new FailedDTOHolder();
+ final ServletContextDTO dto = new ServletContextDTO();
+
+ final Map<ServletInfo, ErrorPageRegistry.ErrorRegistrationStatus> status = reg.getStatusMapping();
+ // empty reg
+ assertEquals(0, status.size());
+ // check DTO
+ 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
+ assertEquals(1, status.size());
+ assertNotNull(status.get(h1.getServletInfo()));
+ assertEquals(1, status.get(h1.getServletInfo()).exceptionMapping.size());
+ assertEquals(-1, (int)status.get(h1.getServletInfo()).exceptionMapping.get("java.io.IOException"));
+ assertEquals(1, status.get(h1.getServletInfo()).errorCodeMapping.size());
+ assertEquals(-1, (int)status.get(h1.getServletInfo()).errorCodeMapping.get(404L));
+
+ // check DTO
+ clear(dto, holder);
+ reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
+ assertNull(dto.resourceDTOs);
+ assertNull(dto.servletDTOs);
+ assertTrue(holder.failedResourceDTOs.isEmpty());
+ assertTrue(holder.failedServletDTOs.isEmpty());
+ assertNotNull(dto.errorPageDTOs);
+ assertEquals(1, dto.errorPageDTOs.length);
+ assertEquals(1, dto.errorPageDTOs[0].errorCodes.length);
+ assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]);
+
+ // 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
+ assertEquals(0, status.size());
+ // check DTO
+ clear(dto, holder);
+ reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
+ assertEmpty(dto, holder);
+ }
+
+ 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);
+
+ 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(7, ctx, si, servlet);
+ }
+}