mirror of
https://github.com/google/nomulus.git
synced 2025-05-04 14:07:51 +02:00
In the previous CL I added filter support for the test server, but even though I could verify that filters were being run when debugging, in practice the side effects of the filters (notably, ObjectifyFilter clearing the session cache) were somehow not present in tests (and therefore causing new as-yet unsubmitted tests that rely on proper session caching to break). Investigating further, the way TestServer works is that it creates a wrapper Servlet for each route, and in that wrapper just pushes a future onto a queue and waits on it. The actual target servlet is run within the queue, not within the wrapper servlet's context. I had added filters to the *wrapper* servlet, which meant that even though they were invoked before adding the task to the queue, they were not invoked in the process of actually running the task. In this CL I pushed the filters into the task itself, just like the target servlet. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=144123637
94 lines
3.6 KiB
Java
94 lines
3.6 KiB
Java
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
|
|
//
|
|
// Licensed 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 google.registry.server;
|
|
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
import static google.registry.util.TypeUtils.instantiate;
|
|
|
|
import com.google.common.base.Throwables;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.util.concurrent.Uninterruptibles;
|
|
import java.io.IOException;
|
|
import java.util.Iterator;
|
|
import java.util.Queue;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.FutureTask;
|
|
import javax.annotation.Nullable;
|
|
import javax.servlet.Filter;
|
|
import javax.servlet.FilterChain;
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.ServletRequest;
|
|
import javax.servlet.ServletResponse;
|
|
import javax.servlet.http.HttpServlet;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
/**
|
|
* Servlet that wraps a servlet and delegates request execution to a queue.
|
|
*
|
|
* <p>The actual invocation of the delegate does not happen within this servlet's lifecycle.
|
|
* Therefore, the task on the queue must manually invoke filters within the queue task.
|
|
*
|
|
* @see TestServer
|
|
*/
|
|
public final class ServletWrapperDelegatorServlet extends HttpServlet {
|
|
|
|
private final Queue<FutureTask<Void>> requestQueue;
|
|
private final Class<? extends HttpServlet> servletClass;
|
|
private final ImmutableList<Class<? extends Filter>> filterClasses;
|
|
|
|
ServletWrapperDelegatorServlet(
|
|
Class<? extends HttpServlet> servletClass,
|
|
ImmutableList<Class<? extends Filter>> filterClasses,
|
|
Queue<FutureTask<Void>> requestQueue) {
|
|
this.servletClass = servletClass;
|
|
this.filterClasses = filterClasses;
|
|
this.requestQueue = checkNotNull(requestQueue, "requestQueue");
|
|
}
|
|
|
|
@Override
|
|
public void service(final HttpServletRequest req, final HttpServletResponse rsp)
|
|
throws ServletException, IOException {
|
|
FutureTask<Void> task = new FutureTask<>(new Callable<Void>() {
|
|
@Nullable
|
|
@Override
|
|
public Void call() throws ServletException, IOException {
|
|
// Simulate the full filter chain with the servlet at the end.
|
|
final Iterator<Class<? extends Filter>> filtersIter = filterClasses.iterator();
|
|
FilterChain filterChain =
|
|
new FilterChain() {
|
|
@Override
|
|
public void doFilter(ServletRequest request, ServletResponse response)
|
|
throws IOException, ServletException {
|
|
if (filtersIter.hasNext()) {
|
|
instantiate(filtersIter.next()).doFilter(request, response, this);
|
|
} else {
|
|
instantiate(servletClass).service(request, response);
|
|
}
|
|
}};
|
|
filterChain.doFilter(req, rsp);
|
|
return null;
|
|
}});
|
|
requestQueue.add(task);
|
|
try {
|
|
Uninterruptibles.getUninterruptibly(task);
|
|
} catch (ExecutionException e) {
|
|
Throwables.propagateIfInstanceOf(e.getCause(), ServletException.class);
|
|
Throwables.propagateIfInstanceOf(e.getCause(), IOException.class);
|
|
throw Throwables.propagate(e.getCause());
|
|
}
|
|
}
|
|
}
|