1/*2 * Licensed to the Apache Software Foundation (ASF) under one or more3 * contributor license agreements. See the NOTICE file distributed with4 * this work for additional information regarding copyright ownership.5 * The ASF licenses this file to You under the Apache License, Version 2.06 * (the "License"); you may not use this file except in compliance with7 * the License. You may obtain a copy of the License at8 * 9 * http://www.apache.org/licenses/LICENSE-2.010 * 11 * Unless required by applicable law or agreed to in writing, software12 * distributed under the License is distributed on an "AS IS" BASIS,13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14 * See the License for the specific language governing permissions and15 * limitations under the License.16 */17packageorg.apache.jetspeed.layout.impl;
1819import java.io.InputStream;
20import java.io.InputStreamReader;
21import java.io.Reader;
22import java.io.StringWriter;
23import java.util.ArrayList;
24import java.util.HashMap;
25import java.util.List;
26import java.util.Map;
27import java.util.StringTokenizer;
2829import org.apache.jetspeed.ajax.AJAXException;
30import org.apache.jetspeed.ajax.AjaxAction;
31import org.apache.jetspeed.ajax.AjaxBuilder;
32import org.apache.jetspeed.ajax.AjaxRequestService;
33import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
34import org.apache.jetspeed.page.PageManager;
35import org.apache.jetspeed.request.JetspeedRequestContext;
36import org.apache.jetspeed.request.RequestContext;
37import org.apache.velocity.VelocityContext;
38import org.apache.velocity.app.VelocityEngine;
39import org.apache.velocity.context.Context;
40import org.springframework.beans.BeansException;
41import org.springframework.beans.factory.BeanFactory;
42import org.springframework.beans.factory.BeanFactoryAware;
4344/***45 * 46 * @author David Gurney47 * 48 * The purpose of this object is to run several AJAX actions and aggregate the49 * results into a single response. This is useful when the client needs to make50 * more than one call as the result of a single user action.51 * 52 * The sample request URL is shown below:53 * 54 * http://host:port/ajaxapi?action=multiple&commands=(action;name,value;name,value)(action;name,value)55 * 56 * The constructor accepts a map of the actions that are available to be run.57 * The name,value pairs are parameter values needed by the action. The actions58 * are run in the order that they are found on the URL string59 * 60 */61publicclassMultipleActionextendsBasePortletAction implements AjaxAction,
62 AjaxBuilder, BeanFactoryAware
63 {
6465protectedstaticfinal String ALL_RESULTS = "results";
6667protectedstaticfinal String BUILD_RESULTS = "buildresults";
6869protectedstaticfinal String MULTIPLE_ACTION_PROCESSOR = "Multiple Action Processor";
7071protectedstaticfinal String COMMANDS = "commands";
7273protectedstaticfinal String COMMAND_TOKEN = ")";
7475protectedstaticfinal String PARAM_TOKEN = ";";
7677protectedstaticfinal String VALUE_TOKEN = ",";
7879protected Map actionMap = null;
8081protected VelocityEngine m_oVelocityEngine = null;
8283publicMultipleAction(AjaxRequestService requestService, String p_sTemplate,
84 String p_sErrorTemplate, PageManager p_oPageManager,
85 PortletActionSecurityBehavior p_oSecurityBehavior,
86 VelocityEngine p_oVelocityEngine)
87 {
88super(p_sTemplate, p_sErrorTemplate, p_oPageManager,
89 p_oSecurityBehavior);
90 actionMap = requestService.getActionMap();
91 m_oVelocityEngine = p_oVelocityEngine;
92 }
9394publicvoid setBeanFactory(BeanFactory beanFactory) throws BeansException
95 {
96// get the proxied object for this, and put it in the map to avoid circular dep97 Object proxy = beanFactory.getBean("AjaxMultipleAction");
98 actionMap.put("multiple", proxy);
99 }
100101publicboolean run(RequestContext p_oRequestContext, Map p_oResultMap)
102 throws AJAXException
103 {
104boolean a_bReturnSuccess = true;
105 List a_oResultArray = new ArrayList();
106107 p_oResultMap.put(ACTION, "multiple");
108 p_oResultMap.put(STATUS, "success");
109110// Get the command string111 String a_sCommands = p_oRequestContext.getRequestParameter(COMMANDS);
112if (a_sCommands == null || a_sCommands.length() <= 0)
113 {
114 buildErrorContext(p_oRequestContext, p_oResultMap);
115 p_oResultMap.put(STATUS, "failure");
116 p_oResultMap.put(REASON, "command parameters not found");
117118thrownew AJAXException("command parameters not found");
119 }
120121// Tokenize the commands into single commands122 StringTokenizer a_oCommandTok = new StringTokenizer(a_sCommands,
123 COMMAND_TOKEN);
124125// Process each command126while (a_oCommandTok.hasMoreTokens())
127 {
128// Get the token129 String a_sCommand = a_oCommandTok.nextToken();
130131// Strip off the opening (132 a_sCommand = a_sCommand.substring(1);
133134// Tokenize the single commands into parameters135 StringTokenizer a_oParamTok = new StringTokenizer(a_sCommand,
136 PARAM_TOKEN);
137if (a_oParamTok == null || a_oParamTok.hasMoreTokens() == false)
138 {
139 buildErrorContext(p_oRequestContext, p_oResultMap);
140 p_oResultMap.put(STATUS, "failure");
141 p_oResultMap.put(REASON, "incorrect url request");
142143thrownew AJAXException("incorrect url request");
144 }
145146// Get the action - which is the first item in the list147 String a_sAction = a_oParamTok.nextToken();
148149// Lookup the action from the action map150 Object a_oActionObject = actionMap.get(a_sAction);
151if (a_oActionObject == null152 && !(a_oActionObject instanceof AjaxAction))
153 {
154 buildErrorContext(p_oRequestContext, p_oResultMap);
155 p_oResultMap.put(REASON, "unknown action requested==>"156 + a_sAction);
157158thrownew AJAXException("unknown action requested==>"159 + a_sAction);
160 }
161162 AjaxAction a_oAction = (AjaxAction) a_oActionObject;
163164JetspeedRequestContext a_oJetspeedRequestContext = (JetspeedRequestContext) p_oRequestContext;
165166// Process each parameter for this action167while (a_oParamTok.hasMoreTokens())
168 {
169 String a_sName = a_oParamTok.nextToken(VALUE_TOKEN);
170// Strip of the leading ; if present171if (a_sName.indexOf(';') >= 0)
172 {
173 a_sName = a_sName.substring(1);
174 }
175176 String a_sValue = a_oParamTok.nextToken();
177178// Put the parameters on the request context179 a_oJetspeedRequestContext.setAttribute(a_sName, a_sValue);
180 }
181182// Invoke the action183 Map a_oResultMap = new HashMap();
184boolean a_bSuccess;
185186try187 {
188 a_bSuccess = a_oAction.runBatch(a_oJetspeedRequestContext,
189 a_oResultMap);
190 } catch (Exception e)
191 {
192// Move the reason into the return map193 p_oResultMap.put(REASON, a_oResultMap.get(REASON));
194195thrownew AJAXException(e);
196 }
197198// Check for success199if (a_bSuccess)
200 {
201// Invoke the builder for this action if possible202if (a_oAction instanceof AjaxBuilder)
203 {
204 processBuilder((AjaxBuilder) a_oAction, a_oResultMap,
205 p_oRequestContext, a_bSuccess);
206 }
207208// Get the build results209 String a_sBuildResults = (String) a_oResultMap
210 .get(BUILD_RESULTS);
211212// Look for an xml tag and strip it off213int a_iStartIndex = a_sBuildResults.indexOf("<?xml");
214if (a_iStartIndex >= 0)
215 {
216// Look for the end of the tag217int a_iEndIndex = a_sBuildResults.indexOf(">",
218 a_iStartIndex);
219if (a_iEndIndex >= 0)
220 {
221 String a_sStart = a_sBuildResults.substring(0,
222 a_iStartIndex);
223 String a_sEnd = a_sBuildResults.substring(
224 a_iEndIndex + 1, a_sBuildResults.length());
225 a_sBuildResults = a_sStart + a_sEnd;
226 }
227 }
228229if (a_sBuildResults != null)
230 {
231// Save the results232 a_oResultArray.add(a_sBuildResults);
233 }
234 } else235 {
236// Move the reason into the return map237 p_oResultMap.put(REASON, a_oResultMap.get(REASON));
238239// Exit the loop240 a_bReturnSuccess = false;
241break;
242 }
243 }
244245// Save the results for later building into the response246 p_oResultMap.put(ALL_RESULTS, a_oResultArray);
247248return a_bReturnSuccess;
249 }
250251// Process the builder if provided252protectedvoid processBuilder(AjaxBuilder p_oBuilder, Map p_oInputMap,
253 RequestContext p_oRequestContext, boolean p_oActionSuccessFlag)
254 {
255try256 {
257// Ask the builder to construct the context258// Add the input map to the velocity context259boolean result = true;
260261if (p_oActionSuccessFlag == true)
262 {
263 result = p_oBuilder
264 .buildContext(p_oRequestContext, p_oInputMap);
265 } else266 {
267 result = p_oBuilder.buildErrorContext(p_oRequestContext,
268 p_oInputMap);
269 }
270271 Context a_oContext = new VelocityContext(p_oInputMap);
272273// Check to see if we have a valid context274if (result)
275 {
276// Get the name of the template from the builder277 String a_sTemplateName = null;
278279if (p_oActionSuccessFlag == true)
280 {
281 a_sTemplateName = p_oBuilder.getTemplate();
282 } else283 {
284 a_sTemplateName = p_oBuilder.getErrorTemplate();
285 }
286287// Get a reader to the velocity template288final InputStream a_oTemplateStream = this.getClass()
289 .getClassLoader().getResourceAsStream(a_sTemplateName);
290291 Reader a_oTemplate = new InputStreamReader(a_oTemplateStream);
292293// The results of the velocity template will be stored here294 StringWriter a_oStringWriter = new StringWriter();
295296// Run the velocity template297 m_oVelocityEngine.evaluate(a_oContext, a_oStringWriter,
298 MULTIPLE_ACTION_PROCESSOR, a_oTemplate);
299300// Get the results from the velocity processing301 String a_sResults = a_oStringWriter.getBuffer().toString();
302303// Save the results on the input map304 p_oInputMap.put(BUILD_RESULTS, a_sResults);
305 } else306 {
307 log.error("could not create builder context");
308 }
309 } catch (Exception e)
310 {
311 log.error("builder failed", e);
312 p_oInputMap.put(Constants.REASON, e.toString());
313 }
314 }
315316publicboolean buildContext(RequestContext p_oRequestContext,
317 Map p_oInputMap)
318 {
319boolean a_bResults = true;
320321 a_bResults = super.buildContext(p_oRequestContext, p_oInputMap);
322323return a_bResults;
324 }
325326 }