blob: e1e7b697fe312f14a9add8952ca3ce8a08f7053d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera.protocol.server.impl;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.abdera.i18n.templates.Context;
import org.apache.abdera.i18n.templates.DelegatingContext;
import org.apache.abdera.i18n.templates.HashMapContext;
import org.apache.abdera.i18n.templates.ObjectContext;
import org.apache.abdera.i18n.templates.Template;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.Target;
import org.apache.abdera.protocol.server.TargetBuilder;
import org.apache.abdera.protocol.server.RequestContext.Scope;
/**
* A TargetBuilder implementation that uses URI/IRI Templates to construct
* URIs/IRIs. The input parameter can be a java.util.Map<String,Object>,
* an instance of the org.apache.abdera.i18n.templates.Context interface,
* or any Java object with public getter methods.
*/
@SuppressWarnings("unchecked")
public class TemplateTargetBuilder
implements TargetBuilder {
protected final Map<Object,Template> templates
= new HashMap<Object,Template>();
public TemplateTargetBuilder() {}
public TemplateTargetBuilder(Map<Object,Template> templates) {
for (Map.Entry<Object, Template> entry : templates.entrySet()) {
setTemplate(entry.getKey(),entry.getValue());
}
}
public TemplateTargetBuilder setTemplate(Object key, String template) {
return setTemplate(key, new Template(template));
}
public TemplateTargetBuilder setTemplate(Object key, Template template) {
template = new Template(doReplacements(template.getPattern()));
templates.put(key,template);
return this;
}
private String doReplacements(String template) {
for (Variable var : Variable.values()) {
String rep = var.getReplacement();
if (rep != null) {
template = template.replaceAll("\\Q{" + var.name().toLowerCase() + "}\\E",rep);
}
}
return template;
}
public static Context getContext(RequestContext request, Object param) {
Context context = null;
if (param != null) {
if (param instanceof Map) {
context = new HashMapContext((Map<String,Object>)param, true);
} else if (param instanceof Context) {
context = (Context)param;
} else {
context = new ObjectContext(param,true);
}
}
return new TemplateContext(request, context);
}
public static <T>List<T> asList(Iterator<T> i) {
List<T> list = new ArrayList<T>();
while(i.hasNext())
list.add(i.next());
return list;
}
public String urlFor(
RequestContext request,
Object key,
Object param) {
Template template = templates.get(key);
return template != null ? template.expand(getContext(request,param)) : null;
}
public static class TemplateContext
extends DelegatingContext {
private static final long serialVersionUID = 4332356546022014897L;
private final RequestContext request;
public TemplateContext(
RequestContext request,
Context subcontext) {
super(subcontext);
this.request = request;
}
private String[] split(String val) {
if (val.equals("")) return null;
String[] segments = val.split("/");
return segments.length > 0 ? segments : null;
}
protected <T> T resolveActual(
String var) {
Variable variable = Variable.get(var);
if (variable == null)
return subcontext != null ? (T)subcontext.resolve(var) : null;
switch(variable) {
case REQUEST_URI:
return (T) request.getUri().toString();
case REQUEST_RESOLVED_URI:
return (T) request.getResolvedUri().toString();
case REQUEST_CONTENT_TYPE:
return (T) request.getContentType().toString();
case REQUEST_CONTEXT_PATH:
return (T) split(request.getContextPath());
case REQUEST_PARAMETER:
String name = Variable.REQUEST_PARAMETER.label(var);
return (T) request.getParameter(name);
case REQUEST_LANGUAGE:
return (T) request.getAcceptLanguage();
case REQUEST_CHARSET:
return (T) request.getAcceptCharset();
case REQUEST_USER:
Principal p = request.getPrincipal();
return p != null ? (T)p.getName() : null;
case SESSION_ATTRIBUTE:
name = Variable.SESSION_ATTRIBUTE.label(var);
return (T) request.getAttribute(Scope.SESSION, name);
case REQUEST_ATTRIBUTE:
name = Variable.REQUEST_ATTRIBUTE.label(var);
return (T) request.getAttribute(Scope.REQUEST, name);
case REQUEST_HEADER:
name = Variable.REQUEST_HEADER.label(var);
return (T) request.getHeader(name);
case TARGET_PARAMETER:
name = Variable.TARGET_PARAMETER.label(var);
return (T) request.getTarget().getParameter(name);
case TARGET_IDENTITY:
return (T) request.getTarget().getIdentity();
case TARGET_PATH:
return (T) split(request.getTargetPath());
case TARGET_BASE:
return (T) split(request.getTargetBasePath());
default:
return subcontext != null ? (T)subcontext.resolve(var) : null;
}
}
public Iterator<String> iterator() {
List<String> vars = new ArrayList<String>();
for (String var : subcontext)
vars.add(var);
for (String var : request.getParameterNames())
vars.add(toVar(Variable.REQUEST_PARAMETER,var));
for (String var : request.getAttributeNames(Scope.SESSION))
vars.add(toVar(Variable.SESSION_ATTRIBUTE,var));
for (String var : request.getAttributeNames(Scope.REQUEST))
vars.add(toVar(Variable.REQUEST_ATTRIBUTE,var));
for (String var : request.getHeaderNames())
vars.add(toVar(Variable.REQUEST_HEADER, var));
Target target = request.getTarget();
for (String var : target.getParameterNames())
vars.add(toVar(Variable.TARGET_PARAMETER, var));
vars.add(Variable.REQUEST_CONTEXT_PATH.name().toLowerCase());
vars.add(Variable.REQUEST_CONTENT_TYPE.name().toLowerCase());
vars.add(Variable.REQUEST_URI.name().toLowerCase());
vars.add(Variable.REQUEST_RESOLVED_URI.name().toLowerCase());
vars.add(Variable.REQUEST_LANGUAGE.name().toLowerCase());
vars.add(Variable.REQUEST_CHARSET.name().toLowerCase());
vars.add(Variable.REQUEST_USER.name().toLowerCase());
vars.add(Variable.TARGET_IDENTITY.name().toLowerCase());
vars.add(Variable.TARGET_PATH.name().toLowerCase());
vars.add(Variable.TARGET_BASE.name().toLowerCase());
return vars.iterator();
}
}
private static String toVar(Variable variable, String label) {
return variable.name().toLowerCase() + "_" + label;
}
public static enum Variable {
REQUEST_CONTEXT_PATH("{-opt|/|request_context_path}{-listjoin|/|request_context_path}"),
REQUEST_CONTENT_TYPE,
REQUEST_URI,
REQUEST_RESOLVED_URI,
REQUEST_PARAMETER,
REQUEST_LANGUAGE,
REQUEST_CHARSET,
REQUEST_USER,
SESSION_ATTRIBUTE,
REQUEST_ATTRIBUTE,
REQUEST_HEADER,
TARGET_PARAMETER,
TARGET_IDENTITY,
TARGET_PATH("{-opt|/|target_path}{-listjoin|/|target_path}"),
TARGET_BASE("{-opt|/|target_base}{-listjoin|/|target_base}"),
;
static Variable get(String var) {
if (REQUEST_PARAMETER.match(var)) {
return REQUEST_PARAMETER;
} else if (SESSION_ATTRIBUTE.match(var)) {
return SESSION_ATTRIBUTE;
} else if (REQUEST_ATTRIBUTE.match(var)) {
return REQUEST_ATTRIBUTE;
} else if (REQUEST_HEADER.match(var)) {
return REQUEST_HEADER;
} else if (TARGET_PARAMETER.match(var)) {
return TARGET_PARAMETER;
} else {
try {
return Variable.valueOf(var.toUpperCase());
} catch (Exception e) {
return null;
}
}
}
private final Pattern p;
private final String replacement;
Variable() {
this(null);
}
Variable(String replacement) {
this.p = Pattern.compile("\\Q" + name() + "_\\E.*", Pattern.CASE_INSENSITIVE);
this.replacement = replacement;
}
String getReplacement() {
return replacement;
}
boolean match(String var) {
return p.matcher(var).matches();
}
String label(String var) {
return var.substring(name().length() + 1);
}
}
}