org.ocpsoft.rewrite.faces.config.PhaseAction Maven / Gradle / Ivy
package org.ocpsoft.rewrite.faces.config;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import org.ocpsoft.common.pattern.Weighted;
import org.ocpsoft.common.services.ServiceLoader;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.rewrite.bind.Retrieval;
import org.ocpsoft.rewrite.bind.Submission;
import org.ocpsoft.rewrite.config.Invoke;
import org.ocpsoft.rewrite.config.Operation;
import org.ocpsoft.rewrite.context.EvaluationContext;
import org.ocpsoft.rewrite.exception.RewriteException;
import org.ocpsoft.rewrite.servlet.event.BaseRewrite.ServletRewriteFlow;
import org.ocpsoft.rewrite.servlet.event.ServletRewrite;
import org.ocpsoft.rewrite.servlet.event.SubflowTask;
import org.ocpsoft.rewrite.servlet.http.event.HttpInboundServletRewrite;
import org.ocpsoft.rewrite.servlet.http.event.HttpServletRewrite;
import org.ocpsoft.rewrite.spi.InvocationResultHandler;
/**
* An {@link Operation} that invokes an action before or after a given JavaServer Faces {@link PhaseId}. Has a
* {@link Weighted#priority()} of 0.
*
* @author Lincoln Baxter, III
*/
public abstract class PhaseAction extends PhaseOperation
{
private static final Logger log = Logger.getLogger(Invoke.class);
private final Submission submission;
private final Retrieval retrieval;
/**
* Create an {@link Operation} that invokes the given {@link Retrieval} and processes {@link InvocationResultHandler}
* instances on the result value (if any).
*
* By default, this action is invoked after {@link PhaseId#RESTORE_VIEW}
*/
public static PhaseAction retrieveFrom(final Retrieval retrieval)
{
return new PhaseAction(null, retrieval) {
@Override
public String toString()
{
return "PhaseAction.retrieveFrom(" + retrieval + ")";
}
}.after(PhaseId.RESTORE_VIEW);
}
/**
* Create an {@link Operation} that invokes
* {@link Submission#submit(org.ocpsoft.rewrite.event.Rewrite, EvaluationContext, Object)}, and uses the result of
* the given {@link Retrieval#retrieve(org.ocpsoft.rewrite.event.Rewrite, EvaluationContext)} as the value for this
* submission. Process {@link InvocationResultHandler} instances on the result value (if any).
*
* By default, this action is invoked after {@link PhaseId#RESTORE_VIEW}
*/
public static PhaseAction submitTo(final Submission to, final Retrieval from)
{
return new PhaseAction(to, from) {
@Override
public String toString()
{
return "PhaseAction.submitTo(" + to + ", " + from + ")";
}
}.after(PhaseId.RESTORE_VIEW);
}
@Override
public int priority()
{
return 0;
}
private PhaseAction(final Submission submission, final Retrieval retrieval)
{
this.submission = submission;
this.retrieval = retrieval;
}
@Override
@SuppressWarnings("unchecked")
public void performOperation(final HttpServletRewrite event, final EvaluationContext context)
{
SubflowTask.perform(event, context, ServletRewriteFlow.UN_HANDLED, new SubflowTask() {
@Override
public void performInSubflow(ServletRewrite, ?> event, EvaluationContext context)
{
Object result = null;
if (retrieval != null)
{
result = retrieval.retrieve(event, context);
log.debug("Invoked binding [" + submission + "] returned value [" + result + "]");
}
if (submission != null)
{
result = submission.submit(event, context, result);
log.debug("Invoked binding [" + retrieval + "] returned value [" + result + "]");
}
if (retrieval == null && submission == null)
{
log.warn("No binding specified for Invocation.");
}
if (result instanceof Operation)
{
((Operation) result).perform(event, context);
}
else if (result != null)
{
ServiceLoader providers = ServiceLoader.load(InvocationResultHandler.class);
if (!providers.iterator().hasNext())
{
log.debug("No instances of [" + InvocationResultHandler.class.getName()
+ "] were registered to handing binding invocation result [" + result + "]");
}
for (InvocationResultHandler handler : providers) {
handler.handle(event, context, result);
}
}
if (result != null)
{
try {
if (event.getFlow().is(ServletRewriteFlow.ABORT_REQUEST))
{
FacesContext facesContext = FacesContext.getCurrentInstance();
if (event.getFlow().is(ServletRewriteFlow.FORWARD))
{
String dispatchResource = ((HttpInboundServletRewrite) event).getDispatchResource();
facesContext.getExternalContext().dispatch(dispatchResource);
}
facesContext.responseComplete();
}
else if (event.getFlow().is(ServletRewriteFlow.INCLUDE))
{
throw new IllegalStateException(
"Cannot issue INCLUDE directive within JSF lifecycle. Not supported.");
}
}
catch (Exception e) {
throw new RewriteException("", e);
}
}
}
});
}
}