/*
* 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.config;
import java.net.URL;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.ocpsoft.rewrite.config.ConfigurationRuleParameterBuilder;
import org.ocpsoft.rewrite.config.Operation;
import org.ocpsoft.rewrite.context.EvaluationContext;
import org.ocpsoft.rewrite.param.ParameterStore;
import org.ocpsoft.rewrite.param.Parameterized;
import org.ocpsoft.rewrite.param.ParameterizedPattern;
import org.ocpsoft.rewrite.param.RegexParameterizedPatternBuilder;
import org.ocpsoft.rewrite.servlet.http.event.HttpInboundServletRewrite;
import org.ocpsoft.rewrite.servlet.http.event.HttpServletRewrite;
import org.ocpsoft.rewrite.util.Transpositions;
/**
* An {@link Operation} that performs redirects via {@link HttpInboundServletRewrite#redirectPermanent(String)} and
* {@link HttpInboundServletRewrite#redirectTemporary(String)}
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public abstract class Redirect extends HttpOperation implements Parameterized
{
private final RedirectType type;
private final RegexParameterizedPatternBuilder location;
private Redirect(final String location, final RedirectType type)
{
this.location = new RegexParameterizedPatternBuilder("[^/]+", location);
this.type = type;
}
@Override
public void performHttp(final HttpServletRewrite event, final EvaluationContext context)
{
if (event instanceof HttpInboundServletRewrite)
{
String target = location.build(event, context, Transpositions.encodePath());
switch (type)
{
case PERMANENT:
((HttpInboundServletRewrite) event).redirectPermanent(target);
break;
case TEMPORARY:
((HttpInboundServletRewrite) event).redirectTemporary(target);
break;
default:
break;
}
}
}
/**
* Create an {@link Operation} that issues a permanent {@link Redirect} ( 301
* {@link HttpServletResponse#SC_MOVED_PERMANENTLY} ) to the given location. If the given location is not the same as
* {@link HttpServletRewrite#getAddress()}, this will change the browser {@link URL} and result in a new request.
*
* <p>
* Note that in order to redirect to a resource within the {@link ServletContext}, you must prepend the
* {@link ServletContext#getContextPath()}.
*
* <p>
* For example:<br/>
* <code>
* Redirect.permanent(contextPath + "/example/location.html") <br>
* </code>
*
* <p>
* The given location may be parameterized:
* <p>
* <code>
* /store/global
* /store/{category} <br>
* /store/{category}/item/{itemId} <br>
* ...
* </code>
* <p>
*
* @param location {@link ParameterizedPattern} specifying the target location.
*
* @see ConfigurationRuleParameterBuilder#where(String)
*/
public static Redirect permanent(final String location)
{
return new Redirect(location, RedirectType.PERMANENT) {
@Override
public String toString()
{
return "Redirect.permanent(\"" + location + "\")";
}
};
}
/**
* Create an {@link Operation} that issues a temporary {@link Redirect} ( 302
* {@link HttpServletResponse#SC_MOVED_TEMPORARILY} ) to the given location. If the given location is not the same as
* {@link HttpServletRewrite#getAddress()}, this will change the browser {@link URL} and result in a new request.
* <p>
* Note that in order to redirect within the {@link ServletContext}, you must prepend the
* {@link ServletContext#getContextPath()}.
* <p>
* For example:<br/>
* <code>
* Redirect.temporary(contextPath + "/example/location.html") <br>
* </code>
*
* <p>
* The given location may be parameterized:
* <p>
* <code>
* /store/global
* /store/{category} <br>
* /store/{category}/item/{itemId} <br>
* ...
* </code>
* <p>
*
* @param location {@link ParameterizedPattern} specifying the target location.
*
* @see ConfigurationRuleParameterBuilder#where(String)
*/
public static Redirect temporary(final String location)
{
return new Redirect(location, RedirectType.TEMPORARY) {
@Override
public String toString()
{
return "Redirect.temporary(\"" + location + "\")";
}
};
}
private enum RedirectType
{
PERMANENT(301),
TEMPORARY(302);
private int code;
private RedirectType(int code)
{
this.code = code;
}
@SuppressWarnings("unused")
public int getCode()
{
return code;
}
}
public RegexParameterizedPatternBuilder getTargetExpression()
{
return location;
}
@Override
public Set<String> getRequiredParameterNames()
{
return location.getRequiredParameterNames();
}
@Override
public void setParameterStore(ParameterStore store)
{
location.setParameterStore(store);
}
}