SpringWebThymeleafContextConverter.java

1
package fr.sii.ogham.spring.template.thymeleaf;
2
3
import java.lang.reflect.Field;
4
import java.util.HashMap;
5
import java.util.Map;
6
7
import javax.servlet.ServletContext;
8
import javax.servlet.ServletException;
9
import javax.servlet.http.HttpServletRequest;
10
import javax.servlet.http.HttpServletResponse;
11
12
import org.springframework.context.ApplicationContext;
13
import org.springframework.expression.EvaluationContext;
14
import org.springframework.web.context.request.RequestContextHolder;
15
import org.springframework.web.servlet.View;
16
import org.springframework.web.servlet.support.RequestContext;
17
import org.springframework.web.servlet.view.AbstractTemplateView;
18
import org.thymeleaf.context.IContext;
19
20
import fr.sii.ogham.core.exception.template.ContextException;
21
import fr.sii.ogham.template.thymeleaf.common.ThymeleafContextConverter;
22
23
/**
24
 * Specific context converter for Spring that registers static variables and
25
 * {@link EvaluationContext} for SpEL expressions.
26
 * 
27
 * The aim is to provide the same support as if user was using Spring in web
28
 * context (access to Spring beans from templates, be able to use static
29
 * variables, ...).
30
 * 
31
 * @author Aurélien Baudet
32
 *
33
 */
34
public class SpringWebThymeleafContextConverter implements ThymeleafContextConverter {
35
	private final ThymeleafContextConverter delegate;
36
	private final String springRequestContextVariableName;
37
	private final ApplicationContext applicationContext;
38
	private final WebContextProvider webContextProvider;
39
	private final ThymeleafRequestContextWrapper thymeleafRequestContextWrapper;
40
	private final ThymeleafWebContextProvider thymeleafWebContextProvider;
41
	private final ContextMerger contextMerger;
42
43
	public SpringWebThymeleafContextConverter(ThymeleafContextConverter delegate, String springRequestContextVariableName, ApplicationContext applicationContext, WebContextProvider webContextProvider,
44
			ThymeleafRequestContextWrapper thymeleafRequestContextWrapper, ThymeleafWebContextProvider thymeleafWebContextProvider, ContextMerger contextMerger) {
45
		super();
46
		this.delegate = delegate;
47
		this.springRequestContextVariableName = springRequestContextVariableName;
48
		this.applicationContext = applicationContext;
49
		this.webContextProvider = webContextProvider;
50
		this.thymeleafRequestContextWrapper = thymeleafRequestContextWrapper;
51
		this.thymeleafWebContextProvider = thymeleafWebContextProvider;
52
		this.contextMerger = contextMerger;
53
	}
54
55
	/*
56
	 * If this is not null, we are using Spring 3.1+ and there is the
57
	 * possibility to automatically add @PathVariable's to models. This will be
58
	 * computed at class initialization time.
59
	 */
60
	private static final String pathVariablesSelector;
61
62
	static {
63
64
		/*
65
		 * Compute whether we can obtain @PathVariable's from the request and
66
		 * add them automatically to the model (Spring 3.1+)
67
		 */
68
69
		String pathVariablesSelectorValue = null;
70
		try {
71
			// We are looking for the value of the View.PATH_VARIABLES constant,
72
			// which is a String
73
			final Field pathVariablesField = View.class.getDeclaredField("PATH_VARIABLES");
74
			pathVariablesSelectorValue = (String) pathVariablesField.get(null);
75
		} catch (final NoSuchFieldException | IllegalAccessException ignored) {
76
			pathVariablesSelectorValue = null;
77
		}
78
		pathVariablesSelector = pathVariablesSelectorValue;
79
	}
80
81
	@Override
82
	public IContext convert(fr.sii.ogham.core.template.context.Context context) throws ContextException {
83
		IContext base = delegate.convert(context);
84
		
85
		// the web context may be lost due to @Async method call
86 1 1. convert : negated conditional → TIMED_OUT
		if (isAsyncCall()) {
87 1 1. convert : replaced return value with null for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::convert → TIMED_OUT
			return base;
88
		}
89
90
		// partially borrowed from org.thymeleaf.spring5.view.ThymeleafView
91
		final Map<String, Object> springModel = new HashMap<>(30);
92
93
		HttpServletRequest request = webContextProvider.getRequest(context);
94
		HttpServletResponse response = webContextProvider.getResponse(context);
95
		ServletContext servletContext = webContextProvider.getServletContext(context);
96
97 1 1. convert : negated conditional → TIMED_OUT
		if (pathVariablesSelector != null) {
98
			@SuppressWarnings("unchecked")
99
			final Map<String, Object> pathVars = (Map<String, Object>) request.getAttribute(pathVariablesSelector);
100 1 1. convert : negated conditional → TIMED_OUT
			if (pathVars != null) {
101 1 1. convert : removed call to java/util/Map::putAll → NO_COVERAGE
				springModel.putAll(pathVars);
102
			}
103
		}
104
105
		final RequestContext requestContext = new RequestContext(request, response, servletContext, springModel);
106
107
		// For compatibility with ThymeleafView
108 1 1. convert : removed call to fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::addRequestContextAsVariable → TIMED_OUT
		addRequestContextAsVariable(springModel, springRequestContextVariableName, requestContext);
109
		// For compatibility with AbstractTemplateView
110 1 1. convert : removed call to fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::addRequestContextAsVariable → TIMED_OUT
		addRequestContextAsVariable(springModel, AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE, requestContext);
111
112 1 1. convert : removed call to fr/sii/ogham/spring/template/thymeleaf/ThymeleafRequestContextWrapper::wrapAndRegister → TIMED_OUT
		thymeleafRequestContextWrapper.wrapAndRegister(requestContext, request, response, servletContext, springModel);
113
114 1 1. convert : replaced return value with null for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::convert → TIMED_OUT
		return contextMerger.merge(thymeleafWebContextProvider.getWebContext(context, base, request, response, servletContext, applicationContext, springModel), base);
115
	}
116
117
	private boolean isAsyncCall() {
118
		try {
119
			RequestContextHolder.currentRequestAttributes();
120 1 1. isAsyncCall : replaced boolean return with true for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::isAsyncCall → TIMED_OUT
			return false;
121
		} catch(IllegalStateException e) {
122 1 1. isAsyncCall : replaced boolean return with false for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::isAsyncCall → TIMED_OUT
			return true;
123
		}
124
	}
125
126
	protected static void addRequestContextAsVariable(final Map<String, Object> model, final String variableName, final RequestContext requestContext) throws ContextException {
127
128 1 1. addRequestContextAsVariable : negated conditional → TIMED_OUT
		if (model.containsKey(variableName)) {
129
			throw new ContextException(new ServletException("Cannot expose request context in model attribute '" + variableName + "' because of an existing model object of the same name"));
130
		}
131
		model.put(variableName, requestContext);
132
133
	}
134
135
}

Mutations

86

1.1
Location : convert
Killed by : none
negated conditional → TIMED_OUT

87

1.1
Location : convert
Killed by : none
replaced return value with null for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::convert → TIMED_OUT

97

1.1
Location : convert
Killed by : none
negated conditional → TIMED_OUT

100

1.1
Location : convert
Killed by : none
negated conditional → TIMED_OUT

101

1.1
Location : convert
Killed by : none
removed call to java/util/Map::putAll → NO_COVERAGE

108

1.1
Location : convert
Killed by : none
removed call to fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::addRequestContextAsVariable → TIMED_OUT

110

1.1
Location : convert
Killed by : none
removed call to fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::addRequestContextAsVariable → TIMED_OUT

112

1.1
Location : convert
Killed by : none
removed call to fr/sii/ogham/spring/template/thymeleaf/ThymeleafRequestContextWrapper::wrapAndRegister → TIMED_OUT

114

1.1
Location : convert
Killed by : none
replaced return value with null for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::convert → TIMED_OUT

120

1.1
Location : isAsyncCall
Killed by : none
replaced boolean return with true for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::isAsyncCall → TIMED_OUT

122

1.1
Location : isAsyncCall
Killed by : none
replaced boolean return with false for fr/sii/ogham/spring/template/thymeleaf/SpringWebThymeleafContextConverter::isAsyncCall → TIMED_OUT

128

1.1
Location : addRequestContextAsVariable
Killed by : none
negated conditional → TIMED_OUT

Active mutators

Tests examined


Report generated by PIT OGHAM