1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springbyexample.web.servlet.view.tiles2;
18
19 import javax.servlet.ServletContext;
20 import javax.servlet.ServletRequest;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.tiles.Attribute;
25 import org.apache.tiles.AttributeContext;
26 import org.apache.tiles.TilesContainer;
27 import org.apache.tiles.TilesException;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.springframework.util.StringUtils;
31 import org.springframework.web.servlet.support.JstlUtils;
32 import org.springframework.web.servlet.support.RequestContext;
33 import org.springframework.web.util.WebUtils;
34
35
36
37
38
39
40 public class DynamicTilesViewProcessor {
41
42 final Logger logger = LoggerFactory.getLogger(DynamicTilesViewProcessor.class);
43
44
45
46
47 private String derivedDefinitionName = null;
48
49 private String tilesDefinitionName = "mainTemplate";
50 private String tilesBodyAttributeName = "content";
51 private String tilesDefinitionDelimiter = ".";
52
53
54
55
56
57
58 public void setTilesDefinitionName(String tilesDefinitionName) {
59 this.tilesDefinitionName = tilesDefinitionName;
60 }
61
62
63
64
65
66
67 public void setTilesBodyAttributeName(String tilesBodyAttributeName) {
68 this.tilesBodyAttributeName = tilesBodyAttributeName;
69 }
70
71
72
73
74
75
76
77
78
79 public void setTilesDefinitionDelimiter(String tilesDefinitionDelimiter) {
80 this.tilesDefinitionDelimiter = tilesDefinitionDelimiter;
81 }
82
83
84
85
86 protected void renderMergedOutputModel(String beanName, String url,
87 ServletContext servletContext,
88 HttpServletRequest request, HttpServletResponse response,
89 TilesContainer container)
90 throws Exception {
91 JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext));
92
93 if (!response.isCommitted()) {
94
95
96
97
98
99
100 if (servletContext.getMajorVersion() == 2 && servletContext.getMinorVersion() < 5) {
101 exposeForwardRequestAttributes(request);
102 }
103 }
104
105 String definitionName = startDynamicDefinition(beanName, url, request, response, container);
106
107 container.render(definitionName, request, response);
108
109 endDynamicDefinition(definitionName, beanName, request, response, container);
110 }
111
112
113
114
115 protected String startDynamicDefinition(String beanName, String url,
116 HttpServletRequest request, HttpServletResponse response,
117 TilesContainer container)
118 throws TilesException {
119 String definitionName = processTilesDefinitionName(beanName, container,
120 request, response);
121
122
123
124 if (!definitionName.equals(beanName)) {
125 Attribute attr = new Attribute();
126 attr.setName(tilesBodyAttributeName);
127 attr.setValue(url);
128
129 AttributeContext attributeContext = container.startContext(request, response);
130 attributeContext.putAttribute(tilesBodyAttributeName, attr);
131
132 logger.debug("URL used for Tiles body. url='" + url + "'.");
133 }
134
135 return definitionName;
136 }
137
138
139
140
141 protected void endDynamicDefinition(String definitionName, String beanName,
142 HttpServletRequest request, HttpServletResponse response,
143 TilesContainer container) {
144 if (!definitionName.equals(beanName)) {
145 container.endContext(request, response);
146 }
147 }
148
149
150
151
152
153
154
155
156
157 protected String processTilesDefinitionName(String beanName,
158 TilesContainer container,
159 HttpServletRequest request,
160 HttpServletResponse response)
161 throws TilesException {
162
163
164
165 if (derivedDefinitionName != null) {
166 return derivedDefinitionName;
167 } else if (container.isValidDefinition(beanName, request, response)) {
168 derivedDefinitionName = beanName;
169
170 return beanName;
171 } else {
172 String result = null;
173
174 StringBuilder sb = new StringBuilder();
175 int lastIndex = beanName.lastIndexOf("/");
176 boolean rootDefinition = false;
177
178
179 if (StringUtils.hasLength(tilesDefinitionDelimiter)) {
180 sb.append(tilesDefinitionDelimiter);
181 }
182
183
184 if (lastIndex == -1) {
185 rootDefinition = true;
186 } else {
187 String path = (beanName != null ? beanName.substring(0, lastIndex) : "");
188
189 if (StringUtils.hasLength(tilesDefinitionDelimiter)) {
190 path = StringUtils.replace(path, "/", tilesDefinitionDelimiter);
191
192 }
193
194 sb.append(path);
195
196 if (StringUtils.hasLength(tilesDefinitionDelimiter)) {
197 sb.append(tilesDefinitionDelimiter);
198 }
199 }
200
201 sb.append(tilesDefinitionName);
202
203 if (container.isValidDefinition(sb.toString(), request, response)) {
204 result = sb.toString();
205 } else if (!rootDefinition) {
206 String root = null;
207
208 if (StringUtils.hasLength(tilesDefinitionDelimiter)) {
209 root = tilesDefinitionDelimiter;
210 }
211
212 root += tilesDefinitionName;
213
214 if (container.isValidDefinition(root, request, response)) {
215 result = root;
216 } else {
217 throw new TilesException("No defintion of found for " +
218 "'" + root +"'" +
219 " or '" + sb.toString() +"'");
220 }
221 }
222
223 derivedDefinitionName = result;
224
225 return result;
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 public void exposeForwardRequestAttributes(HttpServletRequest request) {
246 exposeRequestAttributeIfNotPresent(request, WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, request.getRequestURI());
247 exposeRequestAttributeIfNotPresent(request, WebUtils.FORWARD_CONTEXT_PATH_ATTRIBUTE, request.getContextPath());
248 exposeRequestAttributeIfNotPresent(request, WebUtils.FORWARD_SERVLET_PATH_ATTRIBUTE, request.getServletPath());
249 exposeRequestAttributeIfNotPresent(request, WebUtils.FORWARD_PATH_INFO_ATTRIBUTE, request.getPathInfo());
250 exposeRequestAttributeIfNotPresent(request, WebUtils.FORWARD_QUERY_STRING_ATTRIBUTE, request.getQueryString());
251 }
252
253
254
255
256 private void exposeRequestAttributeIfNotPresent(ServletRequest request, String name, Object value) {
257 if (request.getAttribute(name) == null) {
258 request.setAttribute(name, value);
259 }
260 }
261 }