001: /*
002: * $Id: ServiceMultiEventHandler.java,v 1.5 2004/02/19 18:52:35 ajzeneski Exp $
003: *
004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.content.webapp.event;
026:
027: import java.util.ArrayList;
028: import java.util.HashMap;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Locale;
032: import java.util.Map;
033:
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpServletResponse;
036: import javax.servlet.http.HttpSession;
037:
038: import org.ofbiz.base.util.Debug;
039: import org.ofbiz.base.util.UtilHttp;
040: import org.ofbiz.base.util.UtilProperties;
041: import org.ofbiz.base.util.UtilValidate;
042: import org.ofbiz.entity.GenericValue;
043: import org.ofbiz.entity.transaction.GenericTransactionException;
044: import org.ofbiz.entity.transaction.TransactionUtil;
045: import org.ofbiz.service.DispatchContext;
046: import org.ofbiz.service.GenericServiceException;
047: import org.ofbiz.service.LocalDispatcher;
048: import org.ofbiz.service.ModelParam;
049: import org.ofbiz.service.ModelService;
050: import org.ofbiz.service.ServiceUtil;
051: import org.ofbiz.service.ServiceValidationException;
052: import org.ofbiz.service.ServiceAuthException;
053:
054: /**
055: * ServiceMultiEventHandler - Event handler for running a service multiple times; for bulk forms
056: *
057: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
058: * @version $Revision: 1.5 $
059: * @since 2.2
060: */
061: public class ServiceMultiEventHandler implements EventHandler {
062:
063: public static final String module = ServiceMultiEventHandler.class
064: .getName();
065:
066: public static final String DELIMITER = "_o_";
067: public static final String SYNC = "sync";
068: public static final String ASYNC = "async";
069:
070: /**
071: * @see org.ofbiz.content.webapp.event.EventHandler#invoke(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
072: */
073: public String invoke(String eventPath, String eventMethod,
074: HttpServletRequest request, HttpServletResponse response)
075: throws EventHandlerException {
076: // make sure we have a valid reference to the Service Engine
077: LocalDispatcher dispatcher = (LocalDispatcher) request
078: .getAttribute("dispatcher");
079: if (dispatcher == null) {
080: throw new EventHandlerException(
081: "The local service dispatcher is null");
082: }
083: DispatchContext dctx = dispatcher.getDispatchContext();
084: if (dctx == null) {
085: throw new EventHandlerException(
086: "Dispatch context cannot be found");
087: }
088:
089: // get the details for the service(s) to call
090: String mode = SYNC;
091: String serviceName = null;
092:
093: if (eventPath == null || eventPath.length() == 0) {
094: mode = SYNC;
095: } else {
096: mode = eventPath;
097: }
098:
099: // we only support SYNC mode in this handler
100: if (mode != SYNC) {
101: throw new EventHandlerException(
102: "Async mode is not supported");
103: }
104:
105: // nake sure we have a defined service to call
106: serviceName = eventMethod;
107: if (serviceName == null) {
108: throw new EventHandlerException(
109: "Service name (eventMethod) cannot be null");
110: }
111: if (Debug.verboseOn())
112: Debug.logVerbose("[Set mode/service]: " + mode + "/"
113: + serviceName, module);
114:
115: // some needed info for when running the service
116: Locale locale = UtilHttp.getLocale(request);
117: HttpSession session = request.getSession();
118: GenericValue userLogin = (GenericValue) session
119: .getAttribute("userLogin");
120:
121: // get the service model to generate context(s)
122: ModelService model = null;
123:
124: try {
125: model = dctx.getModelService(serviceName);
126: } catch (GenericServiceException e) {
127: throw new EventHandlerException(
128: "Problems getting the service model", e);
129: }
130:
131: if (model == null) {
132: throw new EventHandlerException(
133: "Problems getting the service model");
134: }
135:
136: if (Debug.verboseOn())
137: Debug.logVerbose("[Processing]: SERVICE Event", module);
138: if (Debug.verboseOn())
139: Debug.logVerbose("[Using delegator]: "
140: + dispatcher.getDelegator().getDelegatorName(),
141: module);
142:
143: // check if we are using per row submit
144: boolean useRowSubmit = request.getParameter("_useRowSubmit") == null ? false
145: : "Y".equalsIgnoreCase(request
146: .getParameter("_useRowSubmit"));
147:
148: // check if we are to also look in a global scope (no delimiter)
149: boolean checkGlobalScope = request
150: .getParameter("_checkGlobalScope") == null ? false
151: : "Y".equalsIgnoreCase(request
152: .getParameter("_checkGlobalScope"));
153:
154: // get the number of rows
155: String rowCountField = request.getParameter("_rowCount");
156: if (rowCountField == null) {
157: throw new EventHandlerException(
158: "Required field _rowCount is missing");
159: }
160:
161: int rowCount = 0; // parsed int value
162: try {
163: rowCount = Integer.parseInt(rowCountField);
164: } catch (NumberFormatException e) {
165: throw new EventHandlerException(
166: "Invalid value for _rowCount");
167: }
168: if (rowCount < 1) {
169: throw new EventHandlerException("No rows to process");
170: }
171:
172: // some default message settings
173: String errorPrefixStr = UtilProperties.getMessage(
174: "DefaultMessages", "service.error.prefix", locale);
175: String errorSuffixStr = UtilProperties.getMessage(
176: "DefaultMessages", "service.error.suffix", locale);
177: String successPrefixStr = UtilProperties.getMessage(
178: "DefaultMessages", "service.success.prefix", locale);
179: String successSuffixStr = UtilProperties.getMessage(
180: "DefaultMessages", "service.success.suffix", locale);
181: String messagePrefixStr = UtilProperties.getMessage(
182: "DefaultMessages", "service.message.prefix", locale);
183: String messageSuffixStr = UtilProperties.getMessage(
184: "DefaultMessages", "service.message.suffix", locale);
185: String defaultMessageStr = UtilProperties.getMessage(
186: "DefaultMessages", "service.default.message", locale);
187:
188: // prepare the error message list
189: List errorMessages = new ArrayList();
190:
191: // start the transaction
192: boolean beganTrans = false;
193: try {
194: beganTrans = TransactionUtil.begin();
195: } catch (GenericTransactionException e) {
196: throw new EventHandlerException(
197: "Problem starting transaction", e);
198: }
199:
200: // now loop throw the rows and prepare/invoke the service for each
201: for (int i = 0; i < rowCount; i++) {
202: String this Suffix = DELIMITER + i;
203: boolean rowSelected = request.getParameter("_rowSubmit"
204: + this Suffix) == null ? false : "Y"
205: .equalsIgnoreCase(request.getParameter("_rowSubmit"
206: + this Suffix));
207:
208: // make sure we are to process this row
209: if (useRowSubmit && !rowSelected) {
210: continue;
211: }
212:
213: // build the context
214: Map serviceContext = new HashMap();
215: Iterator modelParmInIter = model.getInModelParamList()
216: .iterator();
217: while (modelParmInIter.hasNext()) {
218: ModelParam modelParam = (ModelParam) modelParmInIter
219: .next();
220: String name = (String) modelParam.name;
221:
222: // don't include userLogin, that's taken care of below
223: if ("userLogin".equals(name))
224: continue;
225: // don't include locale, that is also taken care of below
226: if ("locale".equals(name))
227: continue;
228:
229: Object value = null;
230: if (modelParam.stringMapPrefix != null
231: && modelParam.stringMapPrefix.length() > 0) {
232: Map paramMap = UtilHttp.makeParamMapWithPrefix(
233: request, modelParam.stringMapPrefix,
234: this Suffix);
235: value = paramMap;
236: } else if (modelParam.stringListSuffix != null
237: && modelParam.stringListSuffix.length() > 0) {
238: List paramList = UtilHttp.makeParamListWithSuffix(
239: request, modelParam.stringListSuffix, null);
240: value = paramList;
241: } else {
242: value = request.getParameter(name + this Suffix);
243:
244: // if the parameter wasn't passed and no other value found, don't pass on the null
245: if (value == null) {
246: value = request.getAttribute(name + this Suffix);
247: }
248: if (value == null) {
249: value = request.getSession().getAttribute(
250: name + this Suffix);
251: }
252:
253: // now check global scope
254: if (value == null) {
255: if (checkGlobalScope) {
256: value = request.getParameter(name);
257: if (value == null) {
258: value = request.getAttribute(name);
259: }
260: if (value == null) {
261: value = request.getSession()
262: .getAttribute(name);
263: }
264: }
265: }
266:
267: if (value == null) {
268: // still null, give up for this one
269: continue;
270: }
271:
272: if (value instanceof String
273: && ((String) value).length() == 0) {
274: // interpreting empty fields as null values for each in back end handling...
275: value = null;
276: }
277: }
278: // set even if null so that values will get nulled in the db later on
279: serviceContext.put(name, value);
280: }
281:
282: // get only the parameters for this service - converted to proper type
283: serviceContext = model.makeValid(serviceContext,
284: ModelService.IN_PARAM);
285:
286: // include the UserLogin value object
287: if (userLogin != null) {
288: serviceContext.put("userLogin", userLogin);
289: }
290:
291: // include the Locale object
292: if (locale != null) {
293: serviceContext.put("locale", locale);
294: }
295:
296: // invoke the service
297: Map result = null;
298: try {
299: result = dispatcher
300: .runSync(serviceName, serviceContext);
301: } catch (ServiceAuthException e) {
302: // not logging since the service engine already did
303: request.setAttribute("_ERROR_MESSAGE_", e
304: .getNonNestedMessage());
305: return "error";
306: } catch (ServiceValidationException e) {
307: // not logging since the service engine already did
308: request.setAttribute("serviceValidationException", e);
309: request.setAttribute("_ERROR_MESSAGE_", e
310: .getNonNestedMessage());
311: return "error";
312: } catch (GenericServiceException e) {
313: Debug.logError(e, "Service invocation error", module);
314: errorMessages.add(messagePrefixStr
315: + "Service invocation error on row (" + i
316: + "): " + e.getNested() + messageSuffixStr);
317: }
318:
319: // check for an error message
320: String errorMessage = ServiceUtil.makeErrorMessage(result,
321: messagePrefixStr, messageSuffixStr, "", "");
322: if (UtilValidate.isNotEmpty(errorMessage)) {
323: errorMessages.add(errorMessage);
324: }
325:
326: }
327:
328: if (errorMessages.size() > 0) {
329: // rollback the transaction
330: try {
331: TransactionUtil.rollback(beganTrans);
332: } catch (GenericTransactionException e) {
333: Debug.logError(e, "Could not rollback transaction",
334: module);
335: }
336: errorMessages.add(0, errorPrefixStr);
337: errorMessages.add(errorSuffixStr);
338: StringBuffer errorBuf = new StringBuffer();
339: Iterator ei = errorMessages.iterator();
340: while (ei.hasNext()) {
341: String em = (String) ei.next();
342: errorBuf.append(em + "\n");
343: }
344: request
345: .setAttribute("_ERROR_MESSAGE_", errorBuf
346: .toString());
347: return "error";
348: } else {
349: // commit the transaction
350: try {
351: TransactionUtil.commit(beganTrans);
352: } catch (GenericTransactionException e) {
353: Debug.logError(e, "Could not commit transaction",
354: module);
355: throw new EventHandlerException(
356: "Commit transaction failed");
357: }
358: return "success";
359: }
360: }
361: }
|