1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.components;
23
24 import com.opensymphony.xwork2.ActionContext;
25 import com.opensymphony.xwork2.ActionInvocation;
26 import com.opensymphony.xwork2.config.entities.ActionConfig;
27 import com.opensymphony.xwork2.inject.Inject;
28 import com.opensymphony.xwork2.util.logging.Logger;
29 import com.opensymphony.xwork2.util.logging.LoggerFactory;
30 import org.apache.struts2.StrutsException;
31 import org.apache.struts2.dispatcher.mapper.ActionMapper;
32 import org.apache.struts2.dispatcher.mapper.ActionMapping;
33 import org.apache.struts2.views.util.UrlHelper;
34 import org.apache.commons.lang.xwork.StringUtils;
35
36 import java.io.IOException;
37 import java.io.Writer;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.LinkedHashMap;
41 import java.util.Map;
42
43 /***
44 * Implementation of the {@link UrlRenderer} interface that creates URLs suitable in a servlet environment.
45 *
46 */
47 public class ServletUrlRenderer implements UrlRenderer {
48 /***
49 * Provide a logging instance.
50 */
51 private static final Logger LOG = LoggerFactory.getLogger(ServletUrlRenderer.class);
52
53 private ActionMapper actionMapper;
54
55 @Inject
56 public void setActionMapper(ActionMapper mapper) {
57 this.actionMapper = mapper;
58 }
59
60
61 /***
62 * {@inheritDoc}
63 */
64 public void renderUrl(Writer writer, UrlProvider urlComponent) {
65 String scheme = urlComponent.getHttpServletRequest().getScheme();
66
67 if (urlComponent.getScheme() != null) {
68 scheme = urlComponent.getScheme();
69 }
70
71 String result;
72 ActionInvocation ai = (ActionInvocation) ActionContext.getContext().get(ActionContext.ACTION_INVOCATION);
73 if (urlComponent.getValue() == null && urlComponent.getAction() != null) {
74 result = urlComponent.determineActionURL(urlComponent.getAction(), urlComponent.getNamespace(), urlComponent.getMethod(), urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
75 } else if (urlComponent.getValue() == null && urlComponent.getAction() == null && ai != null) {
76
77
78 final String action = ai.getProxy().getActionName();
79 final String namespace = ai.getProxy().getNamespace();
80 result = urlComponent.determineActionURL(action, namespace, urlComponent.getMethod(),urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
81 } else {
82 String _value = urlComponent.getValue();
83
84
85
86 if (_value != null && _value.indexOf("?") > 0) {
87 _value = _value.substring(0, _value.indexOf("?"));
88 }
89 result = UrlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
90 }
91 String anchor = urlComponent.getAnchor();
92 if (StringUtils.isNotEmpty(anchor)) {
93 result += '#' + urlComponent.findString(anchor);
94 }
95
96 if (urlComponent.isPutInContext()) {
97 String var = urlComponent.getVar();
98 if (StringUtils.isNotEmpty(var)) {
99 urlComponent.putInContext(result);
100
101
102 urlComponent.getHttpServletRequest().setAttribute(var, result);
103 } else {
104 try {
105 writer.write(result);
106 } catch (IOException e) {
107 throw new StrutsException("IOError: " + e.getMessage(), e);
108 }
109 }
110 } else {
111 try {
112 writer.write(result);
113 } catch (IOException e) {
114 throw new StrutsException("IOError: " + e.getMessage(), e);
115 }
116 }
117 }
118
119 /***
120 * {@inheritDoc}
121 */
122 public void renderFormUrl(Form formComponent) {
123 String namespace = formComponent.determineNamespace(formComponent.namespace, formComponent.getStack(),
124 formComponent.request);
125 String action;
126
127 if(formComponent.action != null) {
128 action = formComponent.findString(formComponent.action);
129 } else {
130
131
132 ActionInvocation ai = (ActionInvocation) formComponent.getStack().getContext().get(
133 ActionContext.ACTION_INVOCATION);
134 if (ai != null) {
135 action = ai.getProxy().getActionName();
136 namespace = ai.getProxy().getNamespace();
137 } else {
138
139 String uri = formComponent.request.getRequestURI();
140 action = uri.substring(uri.lastIndexOf('/'));
141 }
142 }
143
144 ActionMapping nameMapping = actionMapper.getMappingFromActionName(action);
145 String actionName = nameMapping.getName();
146 String actionMethod = nameMapping.getMethod();
147
148 final ActionConfig actionConfig = formComponent.configuration.getRuntimeConfiguration().getActionConfig(
149 namespace, actionName);
150 if (actionConfig != null) {
151
152 ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
153 String result = UrlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
154 formComponent.request, formComponent.response, null);
155 formComponent.addParameter("action", result);
156
157
158
159 formComponent.addParameter("actionName", actionName);
160 try {
161 Class clazz = formComponent.objectFactory.getClassInstance(actionConfig.getClassName());
162 formComponent.addParameter("actionClass", clazz);
163 } catch (ClassNotFoundException e) {
164
165 }
166
167 formComponent.addParameter("namespace", namespace);
168
169
170 if (formComponent.name == null) {
171 formComponent.addParameter("name", actionName);
172 }
173
174
175 if (formComponent.getId() == null && actionName!=null ) {
176 formComponent.addParameter("id", formComponent.escape(actionName));
177 }
178 } else if (action != null) {
179
180
181
182
183
184
185 if (namespace != null) {
186 LOG.warn("No configuration found for the specified action: '" + actionName + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
187 }
188
189 String result = UrlHelper.buildUrl(action, formComponent.request, formComponent.response, null);
190 formComponent.addParameter("action", result);
191
192
193 int slash = result.lastIndexOf('/');
194 if (slash != -1) {
195 formComponent.addParameter("namespace", result.substring(0, slash));
196 } else {
197 formComponent.addParameter("namespace", "");
198 }
199
200
201
202 String id = formComponent.getId();
203 if (id == null) {
204 slash = result.lastIndexOf('/');
205 int dot = result.indexOf('.', slash);
206 if (dot != -1) {
207 id = result.substring(slash + 1, dot);
208 } else {
209 id = result.substring(slash + 1);
210 }
211 formComponent.addParameter("id", formComponent.escape(id));
212 }
213 }
214
215
216
217
218 formComponent.evaluateClientSideJsEnablement(actionName, namespace, actionMethod);
219 }
220
221
222 public void beforeRenderUrl(UrlProvider urlComponent) {
223 if (urlComponent.getValue() != null) {
224 urlComponent.setValue(urlComponent.findString(urlComponent.getValue()));
225 }
226
227
228
229 try {
230
231 String includeParams = (urlComponent.getUrlIncludeParams() != null ? urlComponent.getUrlIncludeParams().toLowerCase() : UrlProvider.GET);
232
233 if (urlComponent.getIncludeParams() != null) {
234 includeParams = urlComponent.findString(urlComponent.getIncludeParams());
235 }
236
237 if (UrlProvider.NONE.equalsIgnoreCase(includeParams)) {
238 mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.EMPTY_MAP);
239 } else if (UrlProvider.ALL.equalsIgnoreCase(includeParams)) {
240 mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getHttpServletRequest().getParameterMap());
241
242
243 includeGetParameters(urlComponent);
244 includeExtraParameters(urlComponent);
245 } else if (UrlProvider.GET.equalsIgnoreCase(includeParams) || (includeParams == null && urlComponent.getValue() == null && urlComponent.getAction() == null)) {
246 includeGetParameters(urlComponent);
247 includeExtraParameters(urlComponent);
248 } else if (includeParams != null) {
249 LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams);
250 }
251 } catch (Exception e) {
252 LOG.warn("Unable to put request parameters (" + urlComponent.getHttpServletRequest().getQueryString() + ") into parameter map.", e);
253 }
254
255
256 }
257
258 private void includeExtraParameters(UrlProvider urlComponent) {
259 if (urlComponent.getExtraParameterProvider() != null) {
260 mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getExtraParameterProvider().getExtraParameters());
261 }
262 }
263 private void includeGetParameters(UrlProvider urlComponent) {
264 String query = extractQueryString(urlComponent);
265 mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), UrlHelper.parseQueryString(query));
266 }
267
268 private String extractQueryString(UrlProvider urlComponent) {
269
270 String query = urlComponent.getHttpServletRequest().getQueryString();
271 if (query == null) {
272 query = (String) urlComponent.getHttpServletRequest().getAttribute("javax.servlet.forward.query_string");
273 }
274
275 if (query != null) {
276
277 int idx = query.lastIndexOf('#');
278
279 if (idx != -1) {
280 query = query.substring(0, idx);
281 }
282 }
283 return query;
284 }
285
286 /***
287 * Merge request parameters into current parameters. If a parameter is
288 * already present, than the request parameter in the current request and value atrribute
289 * will not override its value.
290 *
291 * The priority is as follows:-
292 * <ul>
293 * <li>parameter from the current request (least priority)</li>
294 * <li>parameter form the value attribute (more priority)</li>
295 * <li>parameter from the param tag (most priority)</li>
296 * </ul>
297 *
298 * @param value the value attribute (url to be generated by this component)
299 * @param parameters component parameters
300 * @param contextParameters request parameters
301 */
302 protected void mergeRequestParameters(String value, Map parameters, Map contextParameters){
303
304 Map mergedParams = new LinkedHashMap(contextParameters);
305
306
307
308
309
310 if (value != null && value.trim().length() > 0 && value.indexOf("?") > 0) {
311 String queryString = value.substring(value.indexOf("?")+1);
312
313 mergedParams = UrlHelper.parseQueryString(queryString);
314 for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) {
315 Map.Entry entry = (Map.Entry) iterator.next();
316 Object key = entry.getKey();
317
318 if (!mergedParams.containsKey(key)) {
319 mergedParams.put(key, entry.getValue());
320 }
321 }
322 }
323
324
325
326
327
328
329
330
331 for (Iterator iterator = mergedParams.entrySet().iterator(); iterator.hasNext();) {
332 Map.Entry entry = (Map.Entry) iterator.next();
333 Object key = entry.getKey();
334
335 if (!parameters.containsKey(key)) {
336 parameters.put(key, entry.getValue());
337 }
338 }
339 }
340 }