FELIX-4888 : ServletHandler's are not sorted by longest matching path
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1679603 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
index 8976da9..aaf9ecd 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
@@ -24,7 +24,6 @@
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;
-import org.apache.felix.http.base.internal.console.HttpServicePlugin;
import org.apache.felix.http.base.internal.dispatch.Dispatcher;
import org.apache.felix.http.base.internal.handler.HandlerRegistry;
import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
@@ -38,7 +37,6 @@
private final BundleContext bundleContext;
private final HandlerRegistry registry;
private final Dispatcher dispatcher;
- private final HttpServicePlugin plugin;
private final HttpServiceFactory httpServiceFactory;
private final WhiteboardManager whiteboardManager;
@@ -49,7 +47,6 @@
this.bundleContext = bundleContext;
this.registry = new HandlerRegistry();
this.dispatcher = new Dispatcher(this.registry);
- this.plugin = new HttpServicePlugin(bundleContext, registry);
this.httpServiceFactory = new HttpServiceFactory(this.bundleContext, this.registry);
this.whiteboardManager = new WhiteboardManager(bundleContext, this.httpServiceFactory, this.registry);
}
@@ -113,8 +110,6 @@
{
this.registry.init();
- this.plugin.register();
-
this.httpServiceFactory.start(servletContext);
this.whiteboardManager.start(servletContext);
@@ -123,8 +118,6 @@
public void unregister()
{
- this.plugin.unregister();
-
this.dispatcher.setWhiteboardManager(null);
if ( this.whiteboardManager != null )
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java b/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
index 8665277..2a04d90 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/console/HttpServicePlugin.java
@@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
+import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
@@ -31,26 +32,33 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.http.base.internal.handler.FilterHandler;
-import org.apache.felix.http.base.internal.handler.HandlerRegistry;
import org.apache.felix.http.base.internal.handler.ServletHandler;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
+import org.osgi.service.http.runtime.dto.RuntimeDTO;
+import org.osgi.service.http.runtime.dto.ServletContextDTO;
+import org.osgi.service.http.runtime.dto.ServletDTO;
+/**
+ * This is a web console plugin.
+ */
@SuppressWarnings("serial")
public class HttpServicePlugin extends HttpServlet
{
- private final HandlerRegistry registry;
+ private final HttpServiceRuntime runtime;
private final BundleContext context;
- private ServiceRegistration serviceReg;
+ private volatile ServiceRegistration<Servlet> serviceReg;
- public HttpServicePlugin(BundleContext context, HandlerRegistry registry)
+ public HttpServicePlugin(final BundleContext context, final HttpServiceRuntime runtime)
{
- this.registry = registry;
+ this.runtime = runtime;
this.context = context;
}
@@ -62,7 +70,7 @@
props.put("felix.webconsole.label", "httpservice");
props.put("felix.webconsole.title", "HTTP Service");
props.put("felix.webconsole.configprinter.modes", "always");
- this.serviceReg = context.registerService(Servlet.class.getName(), this, props);
+ this.serviceReg = context.registerService(Servlet.class, this, props);
}
@Override
@@ -71,18 +79,118 @@
getHtml(resp);
}
- private void getHtml(HttpServletResponse resp) throws IOException
+ private void getHtml(final HttpServletResponse resp) throws IOException
{
+ final RuntimeDTO dto = this.runtime.getRuntimeDTO();
+
final PrintWriter pw = resp.getWriter();
- printServletDetails(pw);
- printFilterDetails(pw);
-
+ printRuntimeDetails(pw, dto.serviceDTO);
+ for(final ServletContextDTO ctxDto : dto.servletContextDTOs )
+ {
+ printContextDetails(pw, ctxDto);
+ }
}
- private void printFilterDetails(PrintWriter pw)
+ private String getValueAsString(final Object value)
{
- pw.println("<p class=\"statline ui-state-highlight\">${Registered Filter Services}</p>");
+ if ( value.getClass().isArray() )
+ {
+ if (value instanceof long[])
+ {
+ return Arrays.toString((long[])value);
+ }
+ else if (value instanceof int[])
+ {
+ return Arrays.toString((int[])value);
+ }
+ else if (value instanceof double[])
+ {
+ return Arrays.toString((double[])value);
+ }
+ else if (value instanceof byte[])
+ {
+ return Arrays.toString((byte[])value);
+ }
+ else if (value instanceof float[])
+ {
+ return Arrays.toString((float[])value);
+ }
+ else if (value instanceof short[])
+ {
+ return Arrays.toString((short[])value);
+ }
+ else if (value instanceof boolean[])
+ {
+ return Arrays.toString((boolean[])value);
+ }
+ else if (value instanceof char[])
+ {
+ return Arrays.toString((char[])value);
+ }
+ else
+ {
+ return Arrays.toString((Object[])value);
+ }
+ }
+ return value.toString();
+ }
+
+ private void printRuntimeDetails(final PrintWriter pw, final ServiceReferenceDTO dto)
+ {
+ pw.println("<p class=\"statline ui-state-highlight\">${Runtime Properties}</p>");
+ pw.println("<table class=\"nicetable\">");
+ pw.println("<thead><tr>");
+ pw.println("<th class=\"header\">${Name}</th>");
+ pw.println("<th class=\"header\">${Value}</th>");
+ pw.println("</tr></thead>");
+ boolean odd = true;
+ for(final Map.Entry<String, Object> prop : dto.properties.entrySet())
+ {
+ odd = printRow(pw, odd, prop.getKey(), getValueAsString(prop.getValue()));
+ }
+ pw.println("</table>");
+ }
+
+ private boolean printRow(final PrintWriter pw, final boolean odd, final String...columns)
+ {
+ pw.print("<tr class=\"");
+ if ( odd ) pw.print("odd"); else pw.print("even");
+ pw.println(" ui-state-default\">");
+
+ for(final String val : columns)
+ {
+ pw.print("<td>");
+ pw.print(val);
+ pw.println("</td>");
+ }
+
+ pw.println("</tr>");
+ return !odd;
+ }
+
+ private void printContextDetails(final PrintWriter pw, final ServletContextDTO dto)
+ {
+ pw.print("<p class=\"statline ui-state-highlight\">${Servlet Context} '");
+ pw.print(dto.name);
+ pw.println("'</p>");
+
+ pw.println("<table class=\"nicetable\">");
+
+ boolean odd = true;
+ odd = printRow(pw, odd, "${Path}", dto.contextPath);
+ odd = printRow(pw, odd, "${service.id}", String.valueOf(dto.serviceId));
+ pw.println("</table>");
+
+ printServletDetails(pw, dto);
+ printFilterDetails(pw, dto);
+ }
+
+ private void printFilterDetails(final PrintWriter pw, final ServletContextDTO dto)
+ {
+ pw.print("<p class=\"statline ui-state-highlight\">${Servlet Context} '");
+ pw.print(dto.name);
+ pw.println("' ${Registered Filter Services}</p>");
pw.println("<table class=\"nicetable\">");
pw.println("<thead><tr>");
@@ -114,37 +222,26 @@
pw.println("</table>");
}
- private void printServletDetails(PrintWriter pw)
+ private void printServletDetails(final PrintWriter pw, final ServletContextDTO dto)
{
- pw.println("<p class=\"statline ui-state-highlight\">${Registered Servlet Services}</p>");
+ pw.print("<p class=\"statline ui-state-highlight\">${Servlet Context} '");
+ pw.print(dto.name);
+ pw.println("' ${Registered Servlet Services}</p>");
pw.println("<table class=\"nicetable\">");
pw.println("<thead><tr>");
- pw.println("<th class=\"header\">${Alias}</th>");
- pw.println("<th class=\"header\">${Servlet}</th>");
- pw.println("<th class=\"header\">${Bundle}</th>");
+ pw.println("<th class=\"header\">${Path}</th>");
+ pw.println("<th class=\"header\">${Name}</th>");
+ pw.println("<th class=\"header\">${Info}</th>");
pw.println("</tr></thead>");
- ServletHandler[] servlets = new ServletHandler[0]; // XXX was: registry.getServlets();
- String rowClass = "odd";
- for (ServletHandler servlet : servlets)
+ boolean odd = true;
+ for (ServletDTO servlet : dto.servletDTOs)
{
+ final StringBuilder sb = new StringBuilder();
+ sb.append("${service.id} : ").append(String.valueOf(servlet.serviceId)).append("\n");
- pw.println("<tr class=\"" + rowClass + " ui-state-default\">");
-// pw.println("<td>" + Arrays.toString(servlet.getPatternStrings()) + "</td>"); // XXX
-// pw.println("<td>" + servlet.getServlet().getClass().getName() + "</td>");
-
- printBundleDetails(pw, servlet.getServlet().getClass());
-
- pw.println("</tr>");
- if (rowClass.equals("odd"))
- {
- rowClass = "even";
- }
- else
- {
- rowClass = "odd";
- }
+ odd = printRow(pw, odd, getValueAsString(servlet.patterns), servlet.name, sb.toString());
}
pw.println("</table>");
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
index d3ea3b1..efbf91f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
@@ -541,11 +541,6 @@
}
}
- /**
- * Catch-all filter chain that simple finishes all requests with a "404 Not Found" error.
- */
- private static final FilterChain DEFAULT_CHAIN = new NotFoundFilterChain();
-
private final HandlerRegistry handlerRegistry;
private WhiteboardManager whiteboardManager;
@@ -570,7 +565,7 @@
*/
public void dispatch(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException
{
- // invalid sessions first
+ // check for invalidating session(s) first
final HttpSession session = req.getSession(false);
if ( session != null )
{
@@ -600,7 +595,7 @@
String pathInfo = UriUtils.compactPath(UriUtils.relativePath(servletPath, requestURI));
String queryString = null; // XXX
- ExtServletContext servletContext = (servletHandler != null) ? servletHandler.getContext() : null;
+ final ExtServletContext servletContext = servletHandler.getContext();
final RequestInfo requestInfo = new RequestInfo(servletPath, pathInfo, queryString);
final HttpServletRequest wrappedRequest = new ServletRequestWrapper(req, servletContext, requestInfo, servletHandler.getContextServiceId(),
@@ -707,7 +702,7 @@
private void invokeChain(FilterHandler[] filterHandlers, ServletHandler servletHandler, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
- FilterChain filterChain = new InvocationFilterChain(servletHandler, filterHandlers, DEFAULT_CHAIN);
+ final FilterChain filterChain = new InvocationChain(servletHandler, filterHandlers);
filterChain.doFilter(request, response);
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java
deleted file mode 100644
index 574f572..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.dispatch;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Convenience adapter for {@link FilterChain}s that makes the obtrusive casting unnecessary.
- */
-public abstract class HttpFilterChain implements FilterChain
-{
- @Override
- public final void doFilter(ServletRequest req, ServletResponse res) throws IOException, ServletException
- {
- doFilter((HttpServletRequest) req, (HttpServletResponse) res);
- }
-
- /**
- * @see FilterChain#doFilter(ServletRequest, ServletResponse)
- */
- protected abstract void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException;
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java
new file mode 100644
index 0000000..eda9509
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationChain.java
@@ -0,0 +1,82 @@
+/*
+ * 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.dispatch;
+
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+
+public class InvocationChain implements FilterChain
+{
+ private final ServletHandler servletHandler;
+ private final FilterHandler[] filterHandlers;
+
+ private int index = -1;
+
+ public InvocationChain(@Nonnull final ServletHandler servletHandler, @Nonnull final FilterHandler[] filterHandlers)
+ {
+ this.filterHandlers = filterHandlers;
+ this.servletHandler = servletHandler;
+ }
+
+ @Override
+ public final void doFilter(ServletRequest req, ServletResponse res) throws IOException, ServletException
+ {
+ if ( this.index == -1 )
+ {
+ final HttpServletRequest hReq = (HttpServletRequest) req;
+ final HttpServletResponse hRes = (HttpServletResponse) res;
+
+ // invoke security
+ if ( !servletHandler.getContext().handleSecurity(hReq, hRes))
+ {
+ // FELIX-3988: If the response is not yet committed and still has the default
+ // status, we're going to override this and send an error instead.
+ if (!res.isCommitted() && (hRes.getStatus() == SC_OK || hRes.getStatus() == 0))
+ {
+ hRes.sendError(SC_FORBIDDEN);
+ }
+
+ // we're done
+ return;
+ }
+ }
+ this.index++;
+
+ if (this.index < this.filterHandlers.length)
+ {
+ this.filterHandlers[this.index].handle(req, res, this);
+ }
+ else
+ {
+ // Last entry in the chain...
+ this.servletHandler.handle(req, res);
+ }
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java
deleted file mode 100644
index b806c39..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.dispatch;
-
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.felix.http.base.internal.handler.FilterHandler;
-import org.apache.felix.http.base.internal.handler.ServletHandler;
-
-class InvocationFilterChain extends HttpFilterChain
-{
- private final ServletHandler servletHandler;
- private final FilterHandler[] filterHandlers;
- private final FilterChain defaultChain;
-
- private int index = -1;
-
- public InvocationFilterChain(ServletHandler servletHandler, FilterHandler[] filterHandlers, FilterChain defaultChain)
- {
- this.filterHandlers = filterHandlers;
- this.servletHandler = servletHandler;
- this.defaultChain = defaultChain;
- }
-
- @Override
- protected void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
- {
- this.index++;
-
- if (this.index < this.filterHandlers.length)
- {
- if (this.filterHandlers[this.index].handle(req, res, this))
- {
- // We're done...
- return;
- }
- }
-
- // Last entry in the chain...
- if (this.servletHandler != null && this.servletHandler.handle(req, res))
- {
- // We're done...
- return;
- }
-
- // FELIX-3988: If the response is not yet committed and still has the default
- // status, we're going to override this and send an error instead.
- if (!res.isCommitted() && res.getStatus() == SC_OK)
- {
- this.defaultChain.doFilter(req, res);
- }
- }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java
deleted file mode 100644
index b1398f2..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.dispatch;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public final class NotFoundFilterChain extends HttpFilterChain
-{
- @Override
- protected void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
- {
- res.sendError(HttpServletResponse.SC_NOT_FOUND);
- }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
index 951c2ec..a8eb611 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
@@ -16,9 +16,6 @@
*/
package org.apache.felix.http.base.internal.handler;
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -27,8 +24,8 @@
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
@@ -84,6 +81,7 @@
return this.filter;
}
+ @Override
public FilterInfo getFilterInfo()
{
return this.filterInfo;
@@ -94,23 +92,9 @@
return filterInfo.getRanking();
}
- public boolean handle(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException
+ public void handle(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException
{
- if (getContext().handleSecurity(req, res))
- {
- this.filter.doFilter(req, res, chain);
-
- return true;
- }
-
- // FELIX-3988: If the response is not yet committed and still has the default
- // status, we're going to override this and send an error instead.
- if (!res.isCommitted() && (res.getStatus() == SC_OK || res.getStatus() == 0))
- {
- res.sendError(SC_FORBIDDEN);
- }
-
- return false;
+ this.filter.doFilter(req, res, chain);
}
@Override
@@ -150,6 +134,7 @@
return this.patterns;
}
+ @Override
public long getContextServiceId()
{
return this.contextServiceId;
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 d435bee..f3c020d 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
@@ -37,8 +37,6 @@
import org.apache.felix.http.base.internal.runtime.dto.ContextRuntime;
import org.apache.felix.http.base.internal.runtime.dto.FailureRuntime;
import org.apache.felix.http.base.internal.runtime.dto.HandlerRegistryRuntime;
-import org.apache.felix.http.base.internal.runtime.dto.InfoServletContextHelperRuntime;
-import org.apache.felix.http.base.internal.runtime.dto.ServletContextHelperRuntime;
import org.apache.felix.http.base.internal.runtime.dto.ServletRegistryRuntime;
import org.apache.felix.http.base.internal.whiteboard.RegistrationFailureException;
@@ -50,8 +48,6 @@
*/
public final class HandlerRegistry
{
- private static final String HTTP_SERVICE_CONTEXT_NAME = "Http service context";
-
private static FilterHandler[] EMPTY_FILTER_HANDLER = new FilterHandler[0];
/** Current list of context registrations. */
@@ -252,12 +248,6 @@
return EMPTY_FILTER_HANDLER;
}
- public ServletContextHelperRuntime getHttpServiceContextRuntime()
- {
- ServletContextHelperInfo info = new ServletContextHelperInfo(Integer.MAX_VALUE, 0, HTTP_SERVICE_CONTEXT_NAME, "/", null);
- return new InfoServletContextHelperRuntime(info);
- }
-
public synchronized void addServlet(ServletHandler handler) throws RegistrationFailureException
{
Pattern[] patterns = handler.getPatterns();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index 10398f8..5d10a1a 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -16,16 +16,13 @@
*/
package org.apache.felix.http.base.internal.handler;
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
@@ -69,23 +66,9 @@
return this.servletInfo.compareTo(other.servletInfo);
}
- public boolean handle(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
+ public void handle(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
- if (getContext().handleSecurity(req, res))
- {
- getServlet().service(req, res);
-
- return true;
- }
-
- // FELIX-3988: If the response is not yet committed and still has the default
- // status, we're going to override this and send an error instead.
- if (!res.isCommitted() && (res.getStatus() == SC_OK || res.getStatus() == 0))
- {
- res.sendError(SC_FORBIDDEN);
- }
-
- return false;
+ getServlet().service(req, res);
}
public String determineServletPath(String uri)
@@ -114,6 +97,7 @@
return this.patterns;
}
+ @Override
public ServletInfo getServletInfo()
{
return this.servletInfo;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/InfoServletContextHelperRuntime.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/InfoServletContextHelperRuntime.java
index 8110c41..d938a8a 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/InfoServletContextHelperRuntime.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/InfoServletContextHelperRuntime.java
@@ -26,15 +26,23 @@
{
private final ServletContextHelperInfo info;
- public InfoServletContextHelperRuntime(ServletContextHelperInfo info)
+ private final ServletContext servletContext;
+
+ public InfoServletContextHelperRuntime(final ServletContextHelperInfo info)
+ {
+ this(info, null);
+ }
+
+ public InfoServletContextHelperRuntime(final ServletContextHelperInfo info, final ServletContext ctx)
{
this.info = info;
+ this.servletContext = ctx;
}
@Override
public ServletContext getSharedContext()
{
- return null;
+ return this.servletContext;
}
@Override
@@ -44,7 +52,7 @@
}
@Override
- public int compareTo(InfoServletContextHelperRuntime other)
+ public int compareTo(final InfoServletContextHelperRuntime other)
{
return info.compareTo(other.info);
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
index 34d5bc4..a677c72 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletContextDTOBuilder.java
@@ -86,12 +86,12 @@
ServletContextDTO build()
{
- ServletContext context = contextRuntime.getSharedContext();
- ServletContextHelperInfo contextInfo = contextRuntime.getContextInfo();
- long contextId = contextInfo.getServiceId();
+ final ServletContext context = contextRuntime.getSharedContext();
+ final ServletContextHelperInfo contextInfo = contextRuntime.getContextInfo();
+ final long contextId = contextInfo.getServiceId();
contextDTO.attributes = getAttributes(context);
- contextDTO.contextPath = context == null ? contextInfo.getPath() : context.getContextPath();
+ contextDTO.contextPath = context != null ? context.getContextPath() : contextInfo.getPath();
contextDTO.errorPageDTOs = errorPageDTOs;
contextDTO.filterDTOs = filterDTOs;
contextDTO.initParams = contextInfo.getInitParameters();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
index 8f5032a..6aa33fe 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
@@ -41,6 +41,7 @@
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
+import org.apache.felix.http.base.internal.console.HttpServicePlugin;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.handler.HandlerRegistry;
import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
@@ -60,6 +61,7 @@
import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
import org.apache.felix.http.base.internal.runtime.dto.FailureRuntime;
import org.apache.felix.http.base.internal.runtime.dto.HandlerRegistryRuntime;
+import org.apache.felix.http.base.internal.runtime.dto.InfoServletContextHelperRuntime;
import org.apache.felix.http.base.internal.runtime.dto.RegistryRuntime;
import org.apache.felix.http.base.internal.runtime.dto.ServletContextHelperRuntime;
import org.apache.felix.http.base.internal.service.HttpServiceFactory;
@@ -115,6 +117,8 @@
private volatile ServiceRegistration<HttpServiceRuntime> runtimeServiceReg;
+ private final HttpServicePlugin plugin;
+
/**
* Create a new whiteboard http manager
* @param bundleContext
@@ -129,6 +133,7 @@
this.httpServiceFactory = httpServiceFactory;
this.httpService = new WhiteboardHttpService(this.bundleContext, registry);
this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this);
+ this.plugin = new HttpServicePlugin(bundleContext, this.serviceRuntime);
}
public void start(final ServletContext context)
@@ -191,6 +196,7 @@
addTracker(new ServletRequestListenerTracker(this.bundleContext, this));
addTracker(new ServletRequestAttributeListenerTracker(this.bundleContext, this));
+ this.plugin.register();
}
private void addTracker(ServiceTracker<?, ?> tracker)
@@ -204,6 +210,7 @@
*/
public void stop()
{
+ this.plugin.unregister();
for(final ServiceTracker<?, ?> t : this.trackers)
{
t.close();
@@ -740,6 +747,8 @@
return handlers;
}
+ private static final String HTTP_SERVICE_CONTEXT_NAME = "Http Service context";
+
public RegistryRuntime getRuntime(HandlerRegistry registry)
{
final Collection<ServletContextHelperRuntime> contextRuntimes = new TreeSet<ServletContextHelperRuntime>(ServletContextHelperRuntime.COMPARATOR);
@@ -759,7 +768,10 @@
listenerRuntimes.put(serviceId, handler.getListenerRegistry().getRuntime());
}
}
- contextRuntimes.add(registry.getHttpServiceContextRuntime());
+ // TODO - this is the wrong place, it adds the context for the http service
+ final ServletContextHelperInfo info = new ServletContextHelperInfo(Integer.MAX_VALUE, 0, HTTP_SERVICE_CONTEXT_NAME, "/", null);
+ contextRuntimes.add(new InfoServletContextHelperRuntime(info, this.webContext));
+
handlerRuntimes = registry.getRuntime(failureRuntime);
failureRuntime.add(serviceFailures);
}
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
index 00096af..bc555b7 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
@@ -36,6 +36,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.http.base.internal.dispatch.InvocationChain;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.junit.Before;
import org.junit.Test;
@@ -116,9 +117,11 @@
public void testHandleFoundForbidden() throws Exception
{
FilterHandler h1 = createHandler(0, "/a");
+ final ServletHandler sc = mock(ServletHandler.class);
+ when(sc.getContext()).thenReturn(this.context);
+ final InvocationChain ic = new InvocationChain(sc, new FilterHandler[] {h1});
HttpServletRequest req = createServletRequest();
HttpServletResponse res = createServletResponse();
- FilterChain chain = mock(FilterChain.class);
when(req.getRequestURI()).thenReturn("/a");
// Default behaviour: uncomitted response and default status code...
@@ -127,10 +130,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
- h1.handle(req, res, chain);
+ ic.doFilter(req, res);
- verify(this.filter, never()).doFilter(req, res, chain);
- verify(chain, never()).doFilter(req, res);
+ verify(this.filter, never()).doFilter(req, res, ic);
verify(res).sendError(SC_FORBIDDEN);
}
@@ -141,9 +143,11 @@
public void testHandleFoundForbiddenCommittedOwnResponse() throws Exception
{
FilterHandler h1 = createHandler(0, "/a");
+ final ServletHandler sc = mock(ServletHandler.class);
+ when(sc.getContext()).thenReturn(this.context);
+ final InvocationChain ic = new InvocationChain(sc, new FilterHandler[] {h1});
HttpServletRequest req = createServletRequest();
HttpServletResponse res = createServletResponse();
- FilterChain chain = mock(FilterChain.class);
when(req.getRequestURI()).thenReturn("/a");
// Simulate an already committed response...
@@ -152,10 +156,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
- h1.handle(req, res, chain);
+ ic.doFilter(req, res);
- verify(this.filter, never()).doFilter(req, res, chain);
- verify(chain, never()).doFilter(req, res);
+ verify(this.filter, never()).doFilter(req, res, ic);
// Should not be called from our handler...
verify(res, never()).sendError(SC_FORBIDDEN);
}
@@ -167,9 +170,11 @@
public void testHandleFoundForbiddenCustomStatusCode() throws Exception
{
FilterHandler h1 = createHandler(0, "/a");
+ final ServletHandler sc = mock(ServletHandler.class);
+ when(sc.getContext()).thenReturn(this.context);
+ final InvocationChain ic = new InvocationChain(sc, new FilterHandler[] {h1});
HttpServletRequest req = createServletRequest();
HttpServletResponse res = createServletResponse();
- FilterChain chain = mock(FilterChain.class);
when(req.getRequestURI()).thenReturn("/a");
// Simulate an uncommitted response with a non-default status code...
@@ -178,10 +183,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
- h1.handle(req, res, chain);
+ ic.doFilter(req, res);
- verify(this.filter, never()).doFilter(req, res, chain);
- verify(chain, never()).doFilter(req, res);
+ verify(this.filter, never()).doFilter(req, res, ic);
// Should not be called from our handler...
verify(res, never()).sendError(SC_FORBIDDEN);
}
@@ -190,30 +194,32 @@
public void testHandleNotFound() throws Exception
{
FilterHandler h1 = createHandler(0, "/a");
+ final ServletHandler sc = mock(ServletHandler.class);
+ when(sc.getContext()).thenReturn(this.context);
+ final InvocationChain ic = new InvocationChain(sc, new FilterHandler[] {h1});
HttpServletRequest req = createServletRequest();
HttpServletResponse res = createServletResponse();
- FilterChain chain = mock(FilterChain.class);
when(req.getRequestURI()).thenReturn("/");
- h1.handle(req, res, chain);
+ ic.doFilter(req, res);
- verify(this.filter, never()).doFilter(req, res, chain);
- verify(chain, never()).doFilter(req, res);
+ verify(this.filter, never()).doFilter(req, res, ic);
}
@Test
public void testHandleNotFoundContextRoot() throws Exception
{
FilterHandler h1 = createHandler(0, "/a");
+ final ServletHandler sc = mock(ServletHandler.class);
+ when(sc.getContext()).thenReturn(this.context);
+ final InvocationChain ic = new InvocationChain(sc, new FilterHandler[] {h1});
HttpServletRequest req = createServletRequest();
HttpServletResponse res = createServletResponse();
- FilterChain chain = mock(FilterChain.class);
when(req.getRequestURI()).thenReturn(null);
- h1.handle(req, res, chain);
+ ic.doFilter(req, res);
- verify(this.filter, never()).doFilter(req, res, chain);
- verify(chain, never()).doFilter(req, res);
+ verify(this.filter, never()).doFilter(req, res, ic);
}
@Test
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/SimpleServletHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/SimpleServletHandlerTest.java
index d1eea17..9ba64a1 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/SimpleServletHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/SimpleServletHandlerTest.java
@@ -19,8 +19,7 @@
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.servlet.http.HttpServletResponse.SC_PAYMENT_REQUIRED;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -35,6 +34,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.http.base.internal.dispatch.InvocationChain;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
import org.junit.Before;
import org.junit.Test;
@@ -63,14 +63,15 @@
public void testHandleFound() throws Exception
{
ServletHandler h1 = createHandler("/a");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
when(this.context.handleSecurity(req, res)).thenReturn(true);
when(req.getPathInfo()).thenReturn("/a/b");
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertTrue(result);
+ assertEquals(0, res.getStatus());
verify(this.servlet).service(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@@ -78,14 +79,15 @@
public void testHandleFoundContextRoot() throws Exception
{
ServletHandler h1 = createHandler("/");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
when(this.context.handleSecurity(req, res)).thenReturn(true);
when(req.getPathInfo()).thenReturn(null);
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertTrue(result);
+ assertEquals(0, res.getStatus());
verify(this.servlet).service(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@@ -96,6 +98,7 @@
public void testHandleFoundForbidden() throws Exception
{
ServletHandler h1 = createHandler("/a");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
@@ -107,9 +110,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
when(req.getPathInfo()).thenReturn("/a/b");
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertFalse(result);
+ assertEquals(SC_OK, res.getStatus());
verify(this.servlet, never()).service(req, res);
verify(res).sendError(SC_FORBIDDEN);
}
@@ -121,6 +124,7 @@
public void testHandleFoundForbiddenCommittedOwnResponse() throws Exception
{
ServletHandler h1 = createHandler("/a");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
@@ -132,9 +136,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
when(req.getPathInfo()).thenReturn("/a/b");
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertFalse(result);
+ assertEquals(SC_OK, res.getStatus());
verify(this.servlet, never()).service(req, res);
verify(res, never()).sendError(SC_FORBIDDEN);
}
@@ -146,6 +150,7 @@
public void testHandleFoundForbiddenCustomStatusCode() throws Exception
{
ServletHandler h1 = createHandler("/a");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
@@ -157,9 +162,9 @@
when(this.context.handleSecurity(req, res)).thenReturn(false);
when(req.getPathInfo()).thenReturn("/a/b");
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertFalse(result);
+ assertEquals(SC_PAYMENT_REQUIRED, res.getStatus());
verify(this.servlet, never()).service(req, res);
verify(res, never()).sendError(SC_FORBIDDEN);
}
@@ -168,13 +173,13 @@
public void testHandleNotFound() throws Exception
{
ServletHandler h1 = createHandler("/a");
+ final InvocationChain ic = new InvocationChain(h1, new FilterHandler[0]);
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse res = mock(HttpServletResponse.class);
when(req.getPathInfo()).thenReturn("/");
- boolean result = h1.handle(req, res);
+ ic.doFilter(req, res);
- assertFalse(result);
verify(this.servlet, never()).service(req, res);
}
@@ -187,9 +192,8 @@
when(this.context.handleSecurity(req, res)).thenReturn(true);
when(req.getRequestURI()).thenReturn(null);
- boolean result = h1.handle(req, res);
+ h1.handle(req, res);
- assertTrue(result);
verify(this.servlet).service(req, res);
}