FELIX-4888 : ServletHandler's are not sorted by longest matching path. Start new error page registry (WiP)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1679894 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
index 7c12b03..d76e26e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
@@ -158,14 +158,12 @@
private PerContextHandlerRegistry getRegistry(final long key)
{
- synchronized ( this )
+ final List<PerContextHandlerRegistry> list = this.registrations;
+ for(final PerContextHandlerRegistry r : list)
{
- for(final PerContextHandlerRegistry r : this.registrations)
+ if ( key == r.getContextServiceId())
{
- if ( key == r.getContextServiceId())
- {
- return r;
- }
+ return r;
}
}
return null;
@@ -173,32 +171,31 @@
public ServletHolder getErrorHandler(String requestURI, Long serviceId, int code, Throwable exception)
{
- ErrorsMapping errorsMapping = getErrorsMapping(requestURI, serviceId);
- if (errorsMapping == null)
+ final PerContextHandlerRegistry reg;
+ if ( serviceId == null )
{
- return null;
+ // if the context is unknown, we use the first matching one!
+ PerContextHandlerRegistry found = null;
+ final List<PerContextHandlerRegistry> regs = this.registrations;
+ for(final PerContextHandlerRegistry r : regs)
+ {
+ final String path = r.isMatching(requestURI);
+ if ( path != null )
+ {
+ found = r;
+ break;
+ }
+ }
+ reg = found;
}
-
- // TODO
- return null;
- //return errorsMapping.get(exception, code);
- }
-
- private ErrorsMapping getErrorsMapping(final String requestURI, final Long serviceId)
- {
- final List<PerContextHandlerRegistry> regs = this.registrations;
- for(final PerContextHandlerRegistry r : regs)
+ else
{
- if ( serviceId != null && serviceId == r.getContextServiceId() )
- {
- return r.getErrorsMapping();
- }
- else if ( serviceId == null && r.isMatching(requestURI) != null )
- {
- return r.getErrorsMapping();
- }
+ reg = this.getRegistry(serviceId);
}
-
+ if ( reg != null )
+ {
+ return reg.getErrorHandler(code, exception);
+ }
return null;
}
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
new file mode 100644
index 0000000..19564f9
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
@@ -0,0 +1,94 @@
+/*
+ * 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 java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.Nonnull;
+
+import org.apache.felix.http.base.internal.handler.holder.ServletHolder;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+
+public final class ErrorPageRegistry
+{
+ private final Map<Integer, ServletHolder> errorCodesMap = new ConcurrentHashMap<Integer, ServletHolder>();
+ private final Map<String, ServletHolder> exceptionsMap = new ConcurrentHashMap<String, ServletHolder>();
+
+ public void addServlet(@Nonnull final ServletHolder holder)
+ {
+ if ( holder.getServletInfo().getErrorPage() != null )
+ {
+
+ }
+ }
+
+ public void removeServlet(@Nonnull final ServletInfo info, final boolean destroy)
+ {
+ if ( info.getErrorPage() != null )
+ {
+
+ }
+ }
+
+ /**
+ * Get the servlet handling the error
+ * @param exception Optional exception
+ * @param errorCode Error code
+ * @return The servlet handling the error or {@code null}
+ */
+ public ServletHolder get(final Throwable exception, final int errorCode)
+ {
+ ServletHolder errorHandler = this.get(exception);
+ if (errorHandler != null)
+ {
+ return errorHandler;
+ }
+
+ return get(errorCode);
+ }
+
+ private ServletHolder get(final int errorCode)
+ {
+ return this.errorCodesMap.get(errorCode);
+ }
+
+ private ServletHolder get(final Throwable exception)
+ {
+ if (exception == null)
+ {
+ return null;
+ }
+
+ ServletHolder servletHandler = null;
+ Class<?> throwableClass = exception.getClass();
+ while ( servletHandler == null && throwableClass != null )
+ {
+ servletHandler = this.exceptionsMap.get(throwableClass.getName());
+ if ( servletHandler == null )
+ {
+ throwableClass = throwableClass.getSuperclass();
+ if ( !Throwable.class.isAssignableFrom(throwableClass) )
+ {
+ throwableClass = null;
+ }
+ }
+
+ }
+ return servletHandler;
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
index 34c1c71..45d8ba1 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
@@ -19,8 +19,6 @@
import javax.annotation.Nonnull;
import javax.servlet.DispatcherType;
-import org.apache.felix.http.base.internal.handler.ErrorsMapping;
-import org.apache.felix.http.base.internal.handler.ServletHandler;
import org.apache.felix.http.base.internal.handler.holder.FilterHolder;
import org.apache.felix.http.base.internal.handler.holder.ServletHolder;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
@@ -51,6 +49,8 @@
private final FilterRegistry filterRegistry = new FilterRegistry();
+ private final ErrorPageRegistry errorPageRegistry = new ErrorPageRegistry();
+
/**
* Default http service registry
*/
@@ -143,6 +143,7 @@
public void addServlet(@Nonnull final ServletHolder holder)
{
this.servletRegistry.addServlet(holder);
+ this.errorPageRegistry.addServlet(holder);
}
/**
@@ -152,6 +153,7 @@
public void removeServlet(@Nonnull final ServletInfo info, final boolean destroy)
{
this.servletRegistry.removeServlet(info, destroy);
+ this.errorPageRegistry.removeServlet(info, destroy);
}
public void addFilter(@Nonnull final FilterHolder holder)
@@ -165,23 +167,13 @@
}
public FilterHolder[] getFilterHolders(final ServletHolder servletHolder,
- DispatcherType dispatcherType, String requestURI) {
+ DispatcherType dispatcherType, String requestURI)
+ {
return this.filterRegistry.getFilterHolders(servletHolder, dispatcherType, requestURI);
}
- public void removeErrorPage(ServletInfo servletInfo) {
- // TODO Auto-generated method stub
-
- }
-
- public void addErrorPage(ServletHandler handler, String[] errorPages) {
- // TODO Auto-generated method stub
-
- }
-
- public ErrorsMapping getErrorsMapping()
+ public ServletHolder getErrorHandler(int code, Throwable exception)
{
- return new ErrorsMapping();
+ return this.errorPageRegistry.get(exception, code);
}
-
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
index 80a2fd1..1b8032b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
@@ -95,12 +95,12 @@
*/
public void addServlet(@Nonnull final ServletHolder holder)
{
- final ServletRegistrationStatus status = new ServletRegistrationStatus();
-
// we have to check for every pattern in the info
// Can be null in case of error-handling servlets...
if ( holder.getServletInfo().getPatterns() != null )
{
+ final ServletRegistrationStatus status = new ServletRegistrationStatus();
+
for(final String pattern : holder.getServletInfo().getPatterns())
{
final ServletHandler regHandler = this.activeServletMappings.get(pattern);