| /* |
| * 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); |
| } |
| } |
| |
| } |