org.apache.wicket.request.RequestHandlerStack Maven / Gradle / Ivy
/*
* 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.wicket.request;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages stack of executions of {@link IRequestHandler}s.
*
* @author Matej Knopp
* @author igor.vaynberg
*/
public abstract class RequestHandlerStack
{
private static final Logger log = LoggerFactory.getLogger(RequestHandlerStack.class);
// we need both Queue and List interfaces
private final LinkedList requestHandlers = new LinkedList<>();
private final List inactiveRequestHandlers = new ArrayList<>();
private IRequestHandler scheduledAfterCurrent = null;
/**
* @return active handler
*/
public IRequestHandler getActive()
{
return requestHandlers.peek();
}
/**
* @param handler
*/
public void execute(final IRequestHandler handler)
{
final boolean first = requestHandlers.isEmpty();
requestHandlers.add(handler);
IRequestHandler replacementHandler = null;
try
{
respond(handler);
}
catch (RuntimeException exception)
{
ReplaceHandlerException replacer = Exceptions.findCause(exception,
ReplaceHandlerException.class);
if (replacer == null)
{
throw exception;
}
if (replacer.removeAll && !first)
{
throw exception;
}
replacementHandler = replacer.replacementRequestHandler;
}
finally
{
requestHandlers.poll();
inactiveRequestHandlers.add(handler);
}
IRequestHandler scheduled = scheduledAfterCurrent;
scheduledAfterCurrent = null;
if (replacementHandler != null)
{
execute(replacementHandler);
}
else if (scheduled != null)
{
execute(scheduled);
}
}
/**
* Certain exceptions can carry a request handler they wish to be executed, this method tries to
* resolve such a handler given an exception.
*
* @param exception
* @return request handler or null} if one cannot be resolved
*/
public final IRequestHandler resolveHandler(RuntimeException exception)
{
Args.notNull(exception, "exception");
ReplaceHandlerException replacer = Exceptions.findCause(exception,
ReplaceHandlerException.class);
return replacer != null ? replacer.replacementRequestHandler : null;
}
/**
* Allows the request handler to respond to the request
*
* @param handler
*/
protected abstract void respond(IRequestHandler handler);
/**
* Schedules the handler after the current one
*
* @param handler
*/
public void schedule(final IRequestHandler handler)
{
scheduledAfterCurrent = handler;
}
/**
* @return scheduled request handler after the current one
*/
public IRequestHandler next()
{
return scheduledAfterCurrent;
}
/**
* Replaces all request handlers on the stack with the specified one and executes it. If there
* are any request handlers currently executing (this method is called from inside
* {@link IRequestHandler#respond(IRequestCycle)}) the execution is interrupted via an
* exception.
*
* @param handler
*/
public void replaceAll(final IRequestHandler handler)
{
if (requestHandlers.isEmpty())
{
execute(handler);
}
else
{
throw new ReplaceHandlerException(handler, true);
}
}
/**
* Detaches all request handlers
*/
public void detach()
{
if (!requestHandlers.isEmpty())
{
// All requests handlers should be inactive at this point
log.warn("Some of the request handlers are still active.");
inactiveRequestHandlers.addAll(requestHandlers);
requestHandlers.clear();
}
for (IRequestHandler handler : inactiveRequestHandlers)
{
try
{
detach(handler);
}
catch (RuntimeException exception)
{
throw exception;
}
catch (Exception exception)
{
log.error("Error detaching RequestHandler", exception);
}
}
}
/**
* Allows the request handler to detach
*
* @param handler
*/
protected abstract void detach(IRequestHandler handler);
/**
* Exception to stop current request handler and execute a new one.
*
* @author Matej Knopp
*/
public static class ReplaceHandlerException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private final boolean removeAll;
private final IRequestHandler replacementRequestHandler;
/**
* Construct.
*
* @param replacementRequestHandler
* @param removeAll
*/
public ReplaceHandlerException(final IRequestHandler replacementRequestHandler,
final boolean removeAll)
{
this.replacementRequestHandler = replacementRequestHandler;
this.removeAll = removeAll;
}
/**
* @return the RequestHandler that should be used to continue handling the request
*/
public IRequestHandler getReplacementRequestHandler()
{
return replacementRequestHandler;
}
/**
* @see java.lang.Throwable#fillInStackTrace()
*/
@Override
public Throwable fillInStackTrace()
{
// don't do anything here
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy