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