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