/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-07 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id: URLRewrite.java 13765 2011-02-12 13:51:55Z wolfgang_m $
*/
package org.exist.http.urlrewrite;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.exist.Namespaces;
import org.exist.http.servlets.HttpResponseWrapper;
import org.exist.http.urlrewrite.XQueryURLRewrite;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Base class for all rewritten URLs.
*/
public abstract class URLRewrite {
private final static String UNSET = "";
protected String uri;
protected String target;
protected String prefix = null;
protected Map<String, String> attributes = null;
protected Map<String, List<String>> parameters = null;
protected Map<String, String> headers = null;
protected boolean absolute = false;
protected URLRewrite(Element config, String uri) {
this.uri = uri;
if (config != null && config.hasAttribute("absolute"))
absolute = config.getAttribute("absolute").equals("yes");
// Check for add-parameter elements etc.
if (config != null && config.hasChildNodes()) {
Node node = config.getFirstChild();
while (node != null) {
if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) {
Element elem = (Element) node;
if ("add-parameter".equals(elem.getLocalName())) {
addParameter(elem.getAttribute("name"), elem.getAttribute("value"));
} else if ("set-attribute".equals(elem.getLocalName())) {
setAttribute(elem.getAttribute("name"), elem.getAttribute("value"));
} else if ("clear-attribute".equals(elem.getLocalName())) {
unsetAttribute(elem.getAttribute("name"));
} else if ("set-header".equals(elem.getLocalName())) {
setHeader(elem.getAttribute("name"), elem.getAttribute("value"));
}
}
node = node.getNextSibling();
}
}
}
protected void updateRequest(XQueryURLRewrite.RequestWrapper request) {
if (prefix != null)
request.removePathPrefix(prefix);
}
protected void rewriteRequest(XQueryURLRewrite.RequestWrapper request) {
// do nothing by default
}
protected void setAbsolutePath(XQueryURLRewrite.RequestWrapper request) {
request.setPaths(target, null);
}
protected boolean doResolve() {
return !absolute;
}
/**
* Resolve the target of this rewrite rule against the current request context.
*
* @return the new target path excluding context path
*/
protected String resolve(XQueryURLRewrite.RequestWrapper request) throws ServletException {
String path = request.getInContextPath();
if (target == null)
return path;
String fixedTarget;
if (request.getBasePath() != null && target.startsWith("/")) {
fixedTarget = request.getBasePath() + target;
} else
fixedTarget = target;
try {
URI reqURI = new URI(path);
return reqURI.resolve(fixedTarget).toASCIIString();
} catch (URISyntaxException e) {
throw new ServletException(e.getMessage(), e);
}
}
protected void copyFrom(URLRewrite other) {
this.headers = other.headers;
this.parameters = other.parameters;
this.attributes = other.attributes;
}
private void setHeader(String key, String value) {
if(headers == null) {
headers = new HashMap<String, String>();
}
headers.put(key, value);
}
private void addNameValue(String name, String value, Map<String, List<String>> map) {
List<String> values = map.get(name);
if(values == null) {
values = new ArrayList<String>();
}
values.add(value);
map.put(name, values);
}
private void addParameter(String name, String value) {
if(parameters == null){
parameters = new HashMap<String, List<String>>();
}
addNameValue(name, value, parameters);
}
private void setAttribute(String name, String value) {
if(attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.put(name, value);
}
private void unsetAttribute(String name) {
if(attributes == null){
attributes = new HashMap<String, String>();
}
attributes.put(name, UNSET);
}
public void setTarget(String target) {
this.target = target;
}
public String getTarget() {
return target;
}
public void setURI(String uri) {
this.uri = uri;
}
public String getURI() {
return uri;
}
public void setPrefix(String prefix) {
if (prefix.endsWith("/"))
prefix = prefix.replaceFirst("/+$", "");
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
public abstract void doRewrite(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException;
public void prepareRequest(XQueryURLRewrite.RequestWrapper request) {
if (parameters != null) {
for(Map.Entry<String, List<String>> param : parameters.entrySet()) {
for(String paramValue : param.getValue()) {
request.addParameter(param.getKey().toString(), paramValue);
}
}
}
if (attributes != null) {
for (Map.Entry<String, String> entry : attributes.entrySet()) {
String value = entry.getValue();
if(value.equals(UNSET)) {
request.removeAttribute(entry.getKey().toString());
} else {
request.setAttribute(entry.getKey().toString(), entry.getValue());
}
}
}
}
protected void setHeaders(HttpResponseWrapper response) {
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
response.setHeader(entry.getKey().toString(), entry.getValue().toString());
}
}
}
public boolean isControllerForward() {
return false;
}
protected static String normalizePath(String path) {
StringBuilder sb = new StringBuilder(path.length());
for (int i = 0; i < path.length(); i++) {
char c = path.charAt(i);
if (c == '/') {
if (i == 0 || path.charAt(i - 1) != '/')
sb.append(c);
} else
sb.append(c);
}
return sb.toString();
}
}