/*
* Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
* 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 org.ocpsoft.rewrite.servlet.event;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.ocpsoft.rewrite.AbstractRewrite;
import org.ocpsoft.rewrite.context.Context;
import org.ocpsoft.rewrite.event.Flow;
import org.ocpsoft.rewrite.exception.RewriteException;
import org.ocpsoft.rewrite.servlet.RewriteLifecycleContext;
/**
* Base implementation of {@link InboundServletRewriteEvent}
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public abstract class BaseRewrite<IN extends ServletRequest, OUT extends ServletResponse> extends AbstractRewrite
{
private IN request;
private OUT response;
protected Flow flow;
protected String dispatchResource;
private Context context;
private ServletContext servletContext;
public BaseRewrite(final IN request, final OUT response, final ServletContext servletContext)
{
this.servletContext = servletContext;
flow = ServletRewriteFlow.UN_HANDLED;
this.request = request;
this.response = response;
}
/*
* Mutators
*/
/**
* Abort the current {@link ServletRequest} immediately. No further action will be taken on, and the request will not
* be passed to the application.
*/
public void abort()
{
this.flow = ServletRewriteFlow.ABORT_REQUEST;
}
/**
* Continue processing {@link org.ocpsoft.rewrite.config.Rule} definitions for the current {@link ServletRequest},
* even if a call to {@link #abort()}, {@link #handled()}, {@link #forward(String)}, or any other life-cycle control
* method has previously been made.
*/
public void proceed()
{
this.flow = ServletRewriteFlow.PROCEED;
}
/**
* Stop processing {@link org.ocpsoft.rewrite.config.Rule} definitions and pass control of the the current
* {@link ServletRequest} to the underlying application, even if a call to {@link #abort()}, {@link #proceed()},
* {@link #forward(String)}, or any other life-cycle control method has previously been made.
*/
public void handled()
{
this.flow = ServletRewriteFlow.HANDLED;
}
/**
* Once {@link org.ocpsoft.rewrite.config.Rule} processing has completed, perform a
* {@link RequestDispatcher#include(ServletRequest, ServletResponse)} of the given resource target.
*/
public void include(final String resource)
{
this.dispatchResource = resource;
this.flow = ServletRewriteFlow.INCLUDE;
}
/**
* Once {@link org.ocpsoft.rewrite.config.Rule} processing has completed, perform a
* {@link RequestDispatcher#forward(ServletRequest, ServletResponse)} to the given resource target.
*/
public void forward(final String resource)
{
this.dispatchResource = resource;
this.flow = ServletRewriteFlow.FORWARD;
}
/*
* Getters
*/
/**
* Get the current {@link ServletRewriteFlow} state.
*/
@Override
public Flow getFlow()
{
return flow;
}
/**
* Set the current {@link ServletRewriteFlow} state.
*/
public void setFlow(final ServletRewriteFlow flow)
{
this.flow = flow;
}
/**
* Get the current dispatch resource. This value is used when performing a {@link #forward(String)},
* {@link #include(String)}, or redirect.
*/
public String getDispatchResource()
{
return dispatchResource;
}
/**
* Get the current {@link ServletContext} object.
*/
public ServletContext getServletContext()
{
return servletContext;
}
/**
* Get the current {@link ServletRequest} object.
*/
public IN getRequest()
{
return request;
}
/**
* Get the current {@link ServletResponse} object.
*/
public OUT getResponse()
{
return response;
}
/**
* Set the current {@link ServletRequest} object.
*/
public void setRequest(final IN request)
{
this.request = request;
}
/**
* Set the current {@link ServletResponse} object.
*/
public void setResponse(final OUT response)
{
this.response = response;
}
/**
* Enum to represent the finite state of the Rewrite container.
*/
public enum ServletRewriteFlow implements Flow
{
UN_HANDLED(null),
HANDLED(null),
PROCEED(UN_HANDLED),
CONTINUE(HANDLED),
INCLUDE(HANDLED),
ABORT_REQUEST(HANDLED),
FORWARD(ABORT_REQUEST),
REDIRECT_TEMPORARY(ABORT_REQUEST),
REDIRECT_PERMANENT(ABORT_REQUEST);
private ServletRewriteFlow parent;
private ServletRewriteFlow(final ServletRewriteFlow flow)
{
this.parent = flow;
}
/**
* Return true if this {@link ServletRewriteFlow} is a descendant of the given value.
*/
public boolean is(final ServletRewriteFlow other)
{
if (other == null)
{
return false;
}
ServletRewriteFlow t = this;
while (t != null)
{
if (other == t)
{
return true;
}
t = t.parent;
}
return false;
}
/**
* Return true if the given {@link ServletRewriteFlow} is a descendant of <code>this</code>.
*/
public boolean contains(final ServletRewriteFlow other)
{
if (other == null)
{
return false;
}
ServletRewriteFlow t = other;
while (t != null)
{
if (this == t)
{
return true;
}
t = t.parent;
}
return false;
}
@Override
public boolean isHandled()
{
return is(HANDLED);
}
@Override
public boolean is(Flow flow)
{
if (flow instanceof ServletRewriteFlow)
return is((ServletRewriteFlow) flow);
return false;
}
}
@Override
public String toString()
{
return "Rewrite [flow=" + flow + ", dispatchResource=" + dispatchResource + "]";
}
/**
* Get the {@link org.ocpsoft.rewrite.context.Context} for the current {@link org.ocpsoft.rewrite.event.Rewrite}.
*/
@Override
public Context getRewriteContext()
{
if (this.context == null)
{
Context context = (Context) request.getAttribute(RewriteLifecycleContext.LIFECYCLE_CONTEXT_KEY);
if (context == null)
{
throw new RewriteException("RewriteContext was null. Something is seriously wrong, " +
"or you are attempting to access this event outside of the Rewrite lifecycle.");
}
this.context = context;
}
return this.context;
}
}