All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.boot.web.view.TemplateView Maven / Gradle / Ivy

package org.springframework.boot.web.view;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.util.HtmlUtils;

public class TemplateView implements View {
  private final NonRecursivePropertyPlaceholderHelper helper;
  private final String template;
  private volatile Map expressions;

  public TemplateView(String template) {
    this.helper = new NonRecursivePropertyPlaceholderHelper("${", "}");
    this.template = template;
  }

  @Override
  public String getContentType() {
    return "text/html";
  }

  @Override
  public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (response.getContentType() == null) {
      response.setContentType(getContentType());
    }
    String result = toString(model);
    response.getWriter().append(result);
  }

  private Map getExpressions() {
    if (this.expressions == null) {
      synchronized (this) {
        ExpressionCollector expressionCollector = new ExpressionCollector();
        this.helper.replacePlaceholders(this.template, expressionCollector);
        this.expressions = expressionCollector.getExpressions();
      }
    }
    return this.expressions;
  }

  public String toString(Map model) {
    Map map = new HashMap(model);
    PlaceholderResolver resolver = new ExpressionResolver(getExpressions(), map);
    return this.helper.replacePlaceholders(this.template, resolver);
  }
}

class NonRecursivePropertyPlaceholderHelper extends PropertyPlaceholderHelper {
  NonRecursivePropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix) {
    super(placeholderPrefix, placeholderSuffix);
  }

  @Override
  protected String parseStringValue(String strVal, PlaceholderResolver placeholderResolver, Set visitedPlaceholders) {
    return super.parseStringValue(strVal, new NonRecursivePlaceholderResolver(placeholderResolver), visitedPlaceholders);
  }

  private static class NonRecursivePlaceholderResolver implements PlaceholderResolver {
    private final PlaceholderResolver resolver;

    NonRecursivePlaceholderResolver(PlaceholderResolver resolver) {
      this.resolver = resolver;
    }

    @Override
    public String resolvePlaceholder(String placeholderName) {
      if (this.resolver instanceof NonRecursivePlaceholderResolver) {
        return null;
      }
      return this.resolver.resolvePlaceholder(placeholderName);
    }
  }
}

class ExpressionResolver implements PlaceholderResolver {
  private final Map expressions;
  private final EvaluationContext context;

  ExpressionResolver(Map expressions, Map map) {
    this.expressions = expressions;
    this.context = getContext(map);
  }

  private EvaluationContext getContext(Map map) {
    StandardEvaluationContext context = new StandardEvaluationContext();
    context.addPropertyAccessor(new MapAccessor());
    context.setRootObject(map);
    return context;
  }

  @Override
  public String resolvePlaceholder(String placeholderName) {
    Expression expression = this.expressions.get(placeholderName);
    return escape(expression == null ? null : expression.getValue(this.context));
  }

  private String escape(Object value) {
    return HtmlUtils.htmlEscape(value == null ? null : value.toString());
  }
}

class ExpressionCollector implements PlaceholderResolver {
  private final SpelExpressionParser parser = new SpelExpressionParser();
  private final Map expressions = new HashMap();

  @Override
  public String resolvePlaceholder(String name) {
    this.expressions.put(name, this.parser.parseExpression(name));
    return null;
  }

  public Map getExpressions() {
    return Collections.unmodifiableMap(this.expressions);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy