View Javadoc

1   /*
2    * $Id: PortletActionRedirectResult.java 721838 2008-11-30 16:04:46Z davenewton $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.portlet.result;
23  
24  import java.util.Arrays;
25  import java.util.Iterator;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.portlet.PortletMode;
31  
32  import org.apache.struts2.dispatcher.ServletActionRedirectResult;
33  import org.apache.struts2.dispatcher.mapper.ActionMapper;
34  import org.apache.struts2.dispatcher.mapper.ActionMapping;
35  import org.apache.struts2.portlet.PortletActionConstants;
36  import org.apache.struts2.views.util.UrlHelper;
37  
38  import com.opensymphony.xwork2.ActionInvocation;
39  import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
40  import com.opensymphony.xwork2.util.reflection.ReflectionException;
41  import com.opensymphony.xwork2.util.logging.Logger;
42  import com.opensymphony.xwork2.util.logging.LoggerFactory;
43  import com.opensymphony.xwork2.config.entities.ResultConfig;
44  import com.opensymphony.xwork2.inject.Inject;
45  
46  /***
47   *
48   * Portlet modification of the {@link ServletActionRedirectResult}.
49   *
50   * <!-- START SNIPPET: description -->
51   *
52   * This result uses the {@link ActionMapper} provided by the
53   * {@link ActionMapperFactory} to instruct the render phase to invoke the
54   * specified action and (optional) namespace. This is better than the
55   * {@link PortletResult} because it does not require you to encode the URL
56   * patterns processed by the {@link ActionMapper} in to your struts.xml
57   * configuration files. This means you can change your URL patterns at any point
58   * and your application will still work. It is strongly recommended that if you
59   * are redirecting to another action, you use this result rather than the
60   * standard redirect result.
61   *
62   * See examples below for an example of how request parameters could be passed
63   * in.
64   *
65   * <!-- END SNIPPET: description -->
66   *
67   * <b>This result type takes the following parameters:</b>
68   *
69   * <!-- START SNIPPET: params -->
70   *
71   * <ul>
72   *
73   * <li><b>actionName (default)</b> - the name of the action that will be
74   * redirect to</li>
75   *
76   * <li><b>namespace</b> - used to determine which namespace the action is in
77   * that we're redirecting to . If namespace is null, this defaults to the
78   * current namespace</li>
79   *
80   * </ul>
81   *
82   * <!-- END SNIPPET: params -->
83   *
84   * <b>Example:</b>
85   *
86   * <pre>
87   * &lt;!-- START SNIPPET: example --&gt;
88   *  &lt;package name=&quot;public&quot; extends=&quot;struts-default&quot;&gt;
89   *      &lt;action name=&quot;login&quot; class=&quot;...&quot;&gt;
90   *          &lt;!-- Redirect to another namespace --&gt;
91   *          &lt;result type=&quot;redirectAction&quot;&gt;
92   *              &lt;param name=&quot;actionName&quot;&gt;dashboard&lt;/param&gt;
93   *              &lt;param name=&quot;namespace&quot;&gt;/secure&lt;/param&gt;
94   *          &lt;/result&gt;
95   *      &lt;/action&gt;
96   *  &lt;/package&gt;
97   *
98   *  &lt;package name=&quot;secure&quot; extends=&quot;struts-default&quot; namespace=&quot;/secure&quot;&gt;
99   *      &lt;-- Redirect to an action in the same namespace --&gt;
100  *      &lt;action name=&quot;dashboard&quot; class=&quot;...&quot;&gt;
101  *          &lt;result&gt;dashboard.jsp&lt;/result&gt;
102  *          &lt;result name=&quot;error&quot; type=&quot;redirectAction&quot;&gt;error&lt;/result&gt;
103  *      &lt;/action&gt;
104  *
105  *      &lt;action name=&quot;error&quot; class=&quot;...&quot;&gt;
106  *          &lt;result&gt;error.jsp&lt;/result&gt;
107  *      &lt;/action&gt;
108  *  &lt;/package&gt;
109  *
110  *  &lt;package name=&quot;passingRequestParameters&quot; extends=&quot;struts-default&quot; namespace=&quot;/passingRequestParameters&quot;&gt;
111  *     &lt;-- Pass parameters (reportType, width and height) --&gt;
112  *     &lt;!--
113  *     The redirectAction url generated will be :
114  *     /genReport/generateReport.action?reportType=pie&amp;width=100&amp;height=100
115  *     --&gt;
116  *     &lt;action name=&quot;gatherReportInfo&quot; class=&quot;...&quot;&gt;
117  *        &lt;result name=&quot;showReportResult&quot; type=&quot;redirectAction&quot;&gt;
118  *           &lt;param name=&quot;actionName&quot;&gt;generateReport&lt;/param&gt;
119  *           &lt;param name=&quot;namespace&quot;&gt;/genReport&lt;/param&gt;
120  *           &lt;param name=&quot;reportType&quot;&gt;pie&lt;/param&gt;
121  *           &lt;param name=&quot;width&quot;&gt;100&lt;/param&gt;
122  *           &lt;param name=&quot;height&quot;&gt;100&lt;/param&gt;
123  *        &lt;/result&gt;
124  *     &lt;/action&gt;
125  *  &lt;/package&gt;
126  *
127  *
128  *  &lt;!-- END SNIPPET: example --&gt;
129  * </pre>
130  *
131  * @see ActionMapper
132  */
133 public class PortletActionRedirectResult extends PortletResult implements ReflectionExceptionHandler {
134 
135 	private static final long serialVersionUID = -7627388936683562557L;
136 
137     private static final Logger LOG = LoggerFactory.getLogger(PortletActionRedirectResult.class);
138 
139     /*** The default parameter */
140 	public static final String DEFAULT_PARAM = "actionName";
141 
142 	protected String actionName;
143 
144 	protected String namespace;
145 
146 	protected String method;
147 
148 	private Map<String, String> requestParameters = new LinkedHashMap<String, String>();
149 
150 	private ActionMapper actionMapper;
151 
152 	public PortletActionRedirectResult() {
153 		super();
154 	}
155 
156 	public PortletActionRedirectResult(String actionName) {
157 		this(null, actionName, null);
158 	}
159 
160 	public PortletActionRedirectResult(String actionName, String method) {
161 		this(null, actionName, method);
162 	}
163 
164 	public PortletActionRedirectResult(String namespace, String actionName, String method) {
165 		super(null);
166 		this.namespace = namespace;
167 		this.actionName = actionName;
168 		this.method = method;
169 	}
170 
171 	protected List<String> prohibitedResultParam = Arrays.asList(new String[] { DEFAULT_PARAM, "namespace", "method",
172 			"encode", "parse", "location", "prependServletContext" });
173 
174 	@Inject
175 	public void setActionMapper(ActionMapper actionMapper) {
176 		this.actionMapper = actionMapper;
177 	}
178 
179 	/***
180 	 * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
181 	 */
182 	public void execute(ActionInvocation invocation) throws Exception {
183 		actionName = conditionalParse(actionName, invocation);
184 		if (portletMode != null) {
185 			Map<PortletMode, String> namespaceMap = (Map<PortletMode, String>) invocation.getInvocationContext().get(
186 					PortletActionConstants.MODE_NAMESPACE_MAP);
187 			namespace = namespaceMap.get(portletMode);
188 		}
189 		if (namespace == null) {
190 			namespace = invocation.getProxy().getNamespace();
191 		} else {
192 			namespace = conditionalParse(namespace, invocation);
193 		}
194 		if (method == null) {
195 			method = "";
196 		} else {
197 			method = conditionalParse(method, invocation);
198 		}
199 
200 		String resultCode = invocation.getResultCode();
201 		if (resultCode != null) {
202 			ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(resultCode);
203 			Map resultConfigParams = resultConfig.getParams();
204 			for (Iterator i = resultConfigParams.entrySet().iterator(); i.hasNext();) {
205 				Map.Entry e = (Map.Entry) i.next();
206 				if (!prohibitedResultParam.contains(e.getKey())) {
207 					requestParameters.put(e.getKey().toString(), e.getValue() == null ? "" : conditionalParse(e
208 							.getValue().toString(), invocation));
209 				}
210 			}
211 		}
212 
213 		StringBuilder tmpLocation = new StringBuilder(actionMapper.getUriFromActionMapping(new ActionMapping(actionName,
214                 namespace, method, null)));
215 		UrlHelper.buildParametersString(requestParameters, tmpLocation, "&");
216 
217 		setLocation(tmpLocation.toString());
218 
219 		super.execute(invocation);
220 	}
221 
222 	/***
223 	 * Sets the action name
224 	 *
225 	 * @param actionName
226 	 *            The name
227 	 */
228 	public void setActionName(String actionName) {
229 		this.actionName = actionName;
230 	}
231 
232 	/***
233 	 * Sets the namespace
234 	 *
235 	 * @param namespace
236 	 *            The namespace
237 	 */
238 	public void setNamespace(String namespace) {
239 		this.namespace = namespace;
240 	}
241 
242 	/***
243 	 * Sets the method
244 	 *
245 	 * @param method
246 	 *            The method
247 	 */
248 	public void setMethod(String method) {
249 		this.method = method;
250 	}
251 
252 	/***
253 	 * Adds a request parameter to be added to the redirect url
254 	 *
255 	 * @param key
256 	 *            The parameter name
257 	 * @param value
258 	 *            The parameter value
259 	 */
260 	public PortletActionRedirectResult addParameter(String key, Object value) {
261 		requestParameters.put(key, String.valueOf(value));
262 		return this;
263 	}
264 
265     public void handle(ReflectionException ex) {
266         // Only log as debug as they are probably parameters to be appended to the url
267         LOG.debug(ex.getMessage(), ex);
268     }
269 }