1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 import javax.faces.application.ViewHandler;
25 import javax.faces.context.ExternalContext;
26 import javax.faces.context.FacesContext;
27 import java.util.Map;
28
29
30
31
32
33
34
35
36 public class DefaultViewHandlerSupport implements ViewHandlerSupport
37 {
38
39
40
41 private static final String CACHED_SERVLET_MAPPING =
42 DefaultViewHandlerSupport.class.getName() + ".CACHED_SERVLET_MAPPING";
43
44 private static final Log log = LogFactory.getLog(DefaultViewHandlerSupport.class);
45
46 public String calculateViewId(FacesContext context, String viewId)
47 {
48 FacesServletMapping mapping = getFacesServletMapping(context);
49 if (mapping == null || mapping.isExtensionMapping())
50 {
51 viewId = applyDefaultSuffix(context, viewId);
52 }
53 else if (mapping != null && viewId != null && mapping.getUrlPattern().startsWith(viewId))
54 {
55 throw new InvalidViewIdException(viewId);
56 }
57 return viewId;
58 }
59
60 public String calculateActionURL(FacesContext context, String viewId)
61 {
62 if (viewId == null || !viewId.startsWith("/"))
63 {
64 throw new IllegalArgumentException("ViewId must start with a '/': " + viewId);
65 }
66
67 FacesServletMapping mapping = getFacesServletMapping(context);
68 ExternalContext externalContext = context.getExternalContext();
69 String contextPath = externalContext.getRequestContextPath();
70 StringBuilder builder = new StringBuilder(contextPath);
71 if (mapping != null)
72 {
73 if (mapping.isExtensionMapping())
74 {
75 String contextSuffix = getContextSuffix(context);
76 if (viewId.endsWith(contextSuffix))
77 {
78 builder.append(viewId.substring(0, viewId.indexOf(contextSuffix)));
79 builder.append(mapping.getExtension());
80 }
81 else
82 {
83 builder.append(viewId);
84 }
85 }
86 else
87 {
88 builder.append(mapping.getPrefix());
89 builder.append(viewId);
90 }
91 }
92 else
93 {
94 builder.append(viewId);
95 }
96 String calculatedActionURL = builder.toString();
97 if (log.isTraceEnabled())
98 {
99 log.trace("Calculated actionURL: '" + calculatedActionURL + "' for viewId: '" + viewId + "'");
100 }
101 return calculatedActionURL;
102 }
103
104
105
106
107
108 protected FacesServletMapping getFacesServletMapping(FacesContext context)
109 {
110 Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
111
112
113 if (!requestMap.containsKey(CACHED_SERVLET_MAPPING))
114 {
115 ExternalContext externalContext = context.getExternalContext();
116 FacesServletMapping mapping =
117 calculateFacesServletMapping(
118 externalContext.getRequestServletPath(),
119 externalContext.getRequestPathInfo());
120
121 requestMap.put(CACHED_SERVLET_MAPPING, mapping);
122 }
123
124 return (FacesServletMapping) requestMap.get(CACHED_SERVLET_MAPPING);
125 }
126
127
128
129
130
131
132
133
134
135
136 protected static FacesServletMapping calculateFacesServletMapping(
137 String servletPath, String pathInfo)
138 {
139 if (pathInfo != null)
140 {
141
142
143
144
145
146
147 return FacesServletMapping.createPrefixMapping(servletPath);
148 }
149 else
150 {
151
152
153
154
155
156 int slashPos = servletPath.lastIndexOf('/');
157 int extensionPos = servletPath.lastIndexOf('.');
158 if (extensionPos > -1 && extensionPos > slashPos)
159 {
160 String extension = servletPath.substring(extensionPos);
161 return FacesServletMapping.createExtensionMapping(extension);
162 }
163 else
164 {
165
166
167 return FacesServletMapping.createPrefixMapping(servletPath);
168 }
169 }
170 }
171
172 protected String getContextSuffix(FacesContext context)
173 {
174 String defaultSuffix = context.getExternalContext().getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
175 if (defaultSuffix == null)
176 {
177 defaultSuffix = ViewHandler.DEFAULT_SUFFIX;
178 }
179 return defaultSuffix;
180 }
181
182
183
184
185
186
187
188 protected String applyDefaultSuffix(FacesContext context, String viewId)
189 {
190 String defaultSuffix = getContextSuffix(context);
191
192 if (viewId == null)
193 {
194 return null;
195 }
196
197 if (!viewId.endsWith(defaultSuffix))
198 {
199 StringBuilder builder = new StringBuilder(viewId);
200 int slashPos = viewId.lastIndexOf('/');
201 int extensionPos = viewId.lastIndexOf('.');
202 if (extensionPos > -1 && extensionPos > slashPos)
203 {
204 builder.replace(extensionPos, viewId.length(), defaultSuffix);
205 }
206 else
207 {
208 builder.append(defaultSuffix);
209 }
210 viewId = builder.toString();
211 if (log.isTraceEnabled())
212 {
213 log.trace("view id after applying the context suffix: " + viewId);
214 }
215 }
216 return viewId;
217 }
218
219
220
221
222
223 protected static class FacesServletMapping
224 {
225
226
227
228
229
230 private String prefix;
231
232
233
234
235
236 private String extension;
237
238
239
240
241
242
243
244
245 public static FacesServletMapping createPrefixMapping(String path)
246 {
247 FacesServletMapping mapping = new FacesServletMapping();
248 mapping.setPrefix(path);
249 return mapping;
250 }
251
252
253
254
255
256
257
258
259 public static FacesServletMapping createExtensionMapping(
260 String extension)
261 {
262 FacesServletMapping mapping = new FacesServletMapping();
263 mapping.setExtension(extension);
264 return mapping;
265 }
266
267
268
269
270
271
272
273
274
275
276 public String getPrefix()
277 {
278 return prefix;
279 }
280
281
282
283
284
285
286
287 public void setPrefix(String path)
288 {
289 this.prefix = path;
290 }
291
292
293
294
295
296
297
298
299 public String getExtension()
300 {
301 return extension;
302 }
303
304
305
306
307
308
309
310 public void setExtension(String extension)
311 {
312 this.extension = extension;
313 }
314
315
316
317
318
319
320
321
322 public boolean isExtensionMapping()
323 {
324 return extension != null;
325 }
326
327
328
329
330
331
332 public String getUrlPattern()
333 {
334 if (isExtensionMapping())
335 {
336 return "*" + extension;
337 }
338 else
339 {
340 return prefix + "/*";
341 }
342 }
343
344 }
345 }