| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| package org.apache.ofbiz.minilang; |
| |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.ServiceLoader; |
| import java.util.Set; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.apache.ofbiz.base.location.FlexibleLocation; |
| import org.apache.ofbiz.base.util.Assert; |
| import org.apache.ofbiz.base.util.Debug; |
| import org.apache.ofbiz.base.util.UtilGenerics; |
| import org.apache.ofbiz.base.util.UtilMisc; |
| import org.apache.ofbiz.base.util.UtilProperties; |
| import org.apache.ofbiz.base.util.UtilValidate; |
| import org.apache.ofbiz.base.util.UtilXml; |
| import org.apache.ofbiz.base.util.cache.UtilCache; |
| import org.apache.ofbiz.entity.GenericEntity; |
| import org.apache.ofbiz.entity.GenericValue; |
| import org.apache.ofbiz.entity.transaction.GenericTransactionException; |
| import org.apache.ofbiz.entity.transaction.TransactionUtil; |
| import org.apache.ofbiz.minilang.artifact.ArtifactInfoContext; |
| import org.apache.ofbiz.minilang.method.MethodContext; |
| import org.apache.ofbiz.minilang.method.MethodOperation; |
| import org.apache.ofbiz.minilang.method.MethodOperation.DeprecatedOperation; |
| import org.apache.ofbiz.service.DispatchContext; |
| import org.apache.ofbiz.service.ModelService; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| /** |
| * Implements the <simple-method> element. |
| * <p> |
| * The Mini-language script engine follows the |
| * <a href="http://en.wikipedia.org/wiki/Flyweight_pattern">flyweight</a> |
| * design pattern. Mini-language XML files are parsed twice - first into a W3C DOM |
| * tree, then the DOM tree is parsed into element model objects. Each XML element |
| * has a model class, and each model class has its own factory. |
| * </p> |
| * <p> |
| * Mini-language can be extended by:</p> |
| * <ul> |
| * <li>Creating model classes that extend {@link org.apache.ofbiz.minilang.method.MethodOperation}</li> |
| * <li>Creating factories for the model classes that implement {@link org.apache.ofbiz.minilang.method.MethodOperation.Factory}</li> |
| * <li>Create a service provider information file for the factory classes |
| * (see <a href="http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html" target="_blank">ServiceLoader</a>) |
| * </li> |
| * </ul> |
| * |
| * @see <a href="https://cwiki.apache.org/confluence/display/OFBADMIN/Mini+Language+-+minilang+-+simple-method+-+Reference">Mini-language Reference</a> |
| */ |
| public final class SimpleMethod extends MiniLangElement { |
| |
| public static final String module = SimpleMethod.class.getName(); |
| private static final String err_resource = "MiniLangErrorUiLabels"; |
| private static final String[] DEPRECATED_ATTRIBUTES = {"parameter-map-name", "locale-name", "delegator-name", "security-name", "dispatcher-name", "user-login-name"}; |
| private static final Map<String, MethodOperation.Factory<MethodOperation>> methodOperationFactories; |
| private static final UtilCache<String, Map<String, SimpleMethod>> simpleMethodsDirectCache = UtilCache.createUtilCache("minilang.SimpleMethodsDirect", 0, 0); |
| private static final UtilCache<String, SimpleMethod> simpleMethodsResourceCache = UtilCache.createUtilCache("minilang.SimpleMethodsResource", 0, 0); |
| |
| static { |
| Map<String, MethodOperation.Factory<MethodOperation>> mapFactories = new HashMap<String, MethodOperation.Factory<MethodOperation>>(); |
| Iterator<MethodOperation.Factory<MethodOperation>> it = UtilGenerics.cast(ServiceLoader.load(MethodOperation.Factory.class, SimpleMethod.class.getClassLoader()).iterator()); |
| while (it.hasNext()) { |
| MethodOperation.Factory<MethodOperation> factory = it.next(); |
| mapFactories.put(factory.getName(), factory); |
| } |
| methodOperationFactories = Collections.unmodifiableMap(mapFactories); |
| } |
| |
| // This method is needed only during the v1 to v2 transition |
| private static boolean autoCorrect(Element element) { |
| boolean elementModified = false; |
| for (int i = 0; i < DEPRECATED_ATTRIBUTES.length; i++) { |
| if (!element.getAttribute(DEPRECATED_ATTRIBUTES[i]).isEmpty()) { |
| element.removeAttribute(DEPRECATED_ATTRIBUTES[i]); |
| elementModified = true; |
| } |
| } |
| return elementModified; |
| } |
| |
| private static void compileAllSimpleMethods(Element rootElement, Map<String, SimpleMethod> simpleMethods, String location) throws MiniLangException { |
| for (Element simpleMethodElement : UtilXml.childElementList(rootElement, "simple-method")) { |
| SimpleMethod simpleMethod = new SimpleMethod(simpleMethodElement, location); |
| if (simpleMethods.containsKey(simpleMethod.getMethodName())) { |
| MiniLangValidate.handleError("Duplicate method name found", simpleMethod, simpleMethodElement); |
| } |
| simpleMethods.put(simpleMethod.getMethodName(), simpleMethod); |
| } |
| } |
| |
| private static Map<String, SimpleMethod> getAllDirectSimpleMethods(String name, String content, String fromLocation) throws MiniLangException { |
| if (UtilValidate.isEmpty(fromLocation)) { |
| fromLocation = "<location not known>"; |
| } |
| Map<String, SimpleMethod> simpleMethods = new HashMap<String, SimpleMethod>(); |
| Document document = null; |
| try { |
| document = UtilXml.readXmlDocument(content, true, true); |
| } catch (Exception e) { |
| throw new MiniLangException("Could not read SimpleMethod XML document [" + name + "]: ", e); |
| } |
| compileAllSimpleMethods(document.getDocumentElement(), simpleMethods, fromLocation); |
| return simpleMethods; |
| } |
| |
| private static Map<String, SimpleMethod> getAllSimpleMethods(URL xmlURL) throws MiniLangException { |
| Map<String, SimpleMethod> simpleMethods = new LinkedHashMap<String, SimpleMethod>(); |
| Document document = null; |
| try { |
| document = UtilXml.readXmlDocument(xmlURL, true, true); |
| } catch (Exception e) { |
| throw new MiniLangException("Could not read SimpleMethod XML document [" + xmlURL + "]: ", e); |
| } |
| Element rootElement = document.getDocumentElement(); |
| if (!"simple-methods".equalsIgnoreCase(rootElement.getTagName())) { |
| rootElement = UtilXml.firstChildElement(rootElement, "simple-methods"); |
| } |
| |
| compileAllSimpleMethods(rootElement, simpleMethods, xmlURL.toString()); |
| if (MiniLangUtil.isDocumentAutoCorrected(document)) { |
| MiniLangUtil.writeMiniLangDocument(xmlURL, document); |
| } |
| return simpleMethods; |
| } |
| |
| public static Map<String, SimpleMethod> getDirectSimpleMethods(String name, String content, String fromLocation) throws MiniLangException { |
| Assert.notNull("name", name, "content", content); |
| Map<String, SimpleMethod> simpleMethods = simpleMethodsDirectCache.get(name); |
| if (simpleMethods == null) { |
| simpleMethods = getAllDirectSimpleMethods(name, content, fromLocation); |
| simpleMethods = simpleMethodsDirectCache.putIfAbsentAndGet(name, simpleMethods); |
| } |
| return simpleMethods; |
| } |
| |
| public static SimpleMethod getSimpleMethod(String xmlResource, String methodName, ClassLoader loader) throws MiniLangException { |
| Assert.notNull("methodName", methodName); |
| String key = xmlResource.concat("#").concat(methodName); |
| SimpleMethod method = simpleMethodsResourceCache.get(key); |
| if (method == null) { |
| Map<String, SimpleMethod> simpleMethods = getSimpleMethods(xmlResource, loader); |
| for (Map.Entry<String, SimpleMethod> entry : simpleMethods.entrySet()) { |
| String putKey = xmlResource.concat("#").concat(entry.getKey()); |
| simpleMethodsResourceCache.putIfAbsent(putKey, entry.getValue()); |
| } |
| } |
| return simpleMethodsResourceCache.get(key); |
| } |
| |
| public static SimpleMethod getSimpleMethod(URL xmlUrl, String methodName) throws MiniLangException { |
| Assert.notNull("methodName", methodName); |
| String xmlResource = xmlUrl.toString(); |
| String key = xmlResource.concat("#").concat(methodName); |
| SimpleMethod method = simpleMethodsResourceCache.get(key); |
| if (method == null) { |
| Map<String, SimpleMethod> simpleMethods = getAllSimpleMethods(xmlUrl); |
| for (Map.Entry<String, SimpleMethod> entry : simpleMethods.entrySet()) { |
| String putKey = xmlResource.concat("#").concat(entry.getKey()); |
| simpleMethodsResourceCache.putIfAbsent(putKey, entry.getValue()); |
| } |
| } |
| return simpleMethodsResourceCache.get(key); |
| } |
| |
| private static Map<String, SimpleMethod> getSimpleMethods(String xmlResource, ClassLoader loader) throws MiniLangException { |
| Assert.notNull("xmlResource", xmlResource); |
| URL xmlURL = null; |
| try { |
| xmlURL = FlexibleLocation.resolveLocation(xmlResource, loader); |
| } catch (MalformedURLException e) { |
| throw new MiniLangException("Could not find SimpleMethod XML document in resource: " + xmlResource + "; error was: " + e.toString(), e); |
| } |
| if (xmlURL == null) { |
| throw new MiniLangException("Could not find SimpleMethod XML document in resource: " + xmlResource); |
| } |
| return getAllSimpleMethods(xmlURL); |
| } |
| |
| /** |
| * Returns a List of <code>SimpleMethod</code> objects compiled from <code>xmlResource</code>. |
| * The ordering in the List is the same as the XML file. |
| * <p>This method is used by unit test framework to run tests in the order they appear in the XML file. |
| * Method caching is bypassed since the methods are executed only once.</p> |
| * |
| * @param xmlResource |
| * @param loader |
| * @return |
| * @throws MiniLangException |
| */ |
| public static List<SimpleMethod> getSimpleMethodsList(String xmlResource, ClassLoader loader) throws MiniLangException { |
| Map<String, SimpleMethod> simpleMethodMap = getSimpleMethods(xmlResource, loader); |
| return new ArrayList<SimpleMethod>(simpleMethodMap.values()); |
| } |
| |
| public static List<MethodOperation> readOperations(Element simpleMethodElement, SimpleMethod simpleMethod) throws MiniLangException { |
| Assert.notNull("simpleMethodElement", simpleMethodElement, "simpleMethod", simpleMethod); |
| List<? extends Element> operationElements = UtilXml.childElementList(simpleMethodElement); |
| ArrayList<MethodOperation> methodOperations = new ArrayList<MethodOperation>(operationElements.size()); |
| if (UtilValidate.isNotEmpty(operationElements)) { |
| for (Element curOperElem : operationElements) { |
| String nodeName = UtilXml.getNodeNameIgnorePrefix(curOperElem); |
| MethodOperation methodOp = null; |
| MethodOperation.Factory<MethodOperation> factory = methodOperationFactories.get(nodeName); |
| if (factory != null) { |
| methodOp = factory.createMethodOperation(curOperElem, simpleMethod); |
| } else if ("else".equals(nodeName)) { |
| // don't add anything, but don't complain either, this one is handled in the individual operations |
| } else { |
| MiniLangValidate.handleError("Invalid element found", simpleMethod, curOperElem); |
| } |
| if (methodOp == null) { |
| continue; |
| } |
| methodOperations.add(methodOp); |
| DeprecatedOperation depOp = methodOp.getClass().getAnnotation(DeprecatedOperation.class); |
| if (depOp != null) { |
| MiniLangValidate.handleError("The " + nodeName + " operation has been deprecated in favor of the " + depOp.value() + " operation", simpleMethod, curOperElem); |
| } |
| } |
| } |
| methodOperations.trimToSize(); |
| return methodOperations; |
| } |
| |
| public static String runSimpleEvent(String xmlResource, String methodName, HttpServletRequest request, HttpServletResponse response) throws MiniLangException { |
| return runSimpleMethod(xmlResource, methodName, new MethodContext(request, response, null)); |
| } |
| |
| public static String runSimpleEvent(String xmlResource, String methodName, HttpServletRequest request, HttpServletResponse response, ClassLoader loader) throws MiniLangException { |
| return runSimpleMethod(xmlResource, methodName, new MethodContext(request, response, loader)); |
| } |
| |
| public static String runSimpleEvent(URL xmlURL, String methodName, HttpServletRequest request, HttpServletResponse response, ClassLoader loader) throws MiniLangException { |
| return runSimpleMethod(xmlURL, methodName, new MethodContext(request, response, loader)); |
| } |
| |
| public static String runSimpleMethod(String xmlResource, String methodName, MethodContext methodContext) throws MiniLangException { |
| Assert.notNull("methodContext", methodContext); |
| SimpleMethod simpleMethod = getSimpleMethod(xmlResource, methodName, methodContext.getLoader()); |
| if (simpleMethod == null) { |
| throw new MiniLangException("Could not find SimpleMethod " + methodName + " in XML document in resource: " + xmlResource); |
| } |
| return simpleMethod.exec(methodContext); |
| } |
| |
| public static String runSimpleMethod(URL xmlURL, String methodName, MethodContext methodContext) throws MiniLangException { |
| SimpleMethod simpleMethod = getSimpleMethod(xmlURL, methodName); |
| if (simpleMethod == null) { |
| throw new MiniLangException("Could not find SimpleMethod " + methodName + " in XML document from URL: " + xmlURL.toString()); |
| } |
| return simpleMethod.exec(methodContext); |
| } |
| |
| public static Map<String, Object> runSimpleService(String xmlResource, String methodName, DispatchContext ctx, Map<String, ? extends Object> context) throws MiniLangException { |
| MethodContext methodContext = new MethodContext(ctx, context, null); |
| runSimpleMethod(xmlResource, methodName, methodContext); |
| return methodContext.getResults(); |
| } |
| |
| public static Map<String, Object> runSimpleService(String xmlResource, String methodName, DispatchContext ctx, Map<String, ? extends Object> context, ClassLoader loader) throws MiniLangException { |
| MethodContext methodContext = new MethodContext(ctx, context, loader); |
| runSimpleMethod(xmlResource, methodName, methodContext); |
| return methodContext.getResults(); |
| } |
| |
| public static Map<String, Object> runSimpleService(URL xmlURL, String methodName, DispatchContext ctx, Map<String, ? extends Object> context, ClassLoader loader) throws MiniLangException { |
| MethodContext methodContext = new MethodContext(ctx, context, loader); |
| runSimpleMethod(xmlURL, methodName, methodContext); |
| return methodContext.getResults(); |
| } |
| |
| /** |
| * Execs the given operations returning true if all return true, or returning false and stopping if any return false. |
| * @throws MiniLangException |
| */ |
| public static boolean runSubOps(List<MethodOperation> methodOperations, MethodContext methodContext) throws MiniLangException { |
| Assert.notNull("methodOperations", methodOperations, "methodContext", methodContext); |
| for (MethodOperation methodOperation : methodOperations) { |
| if (!methodOperation.exec(methodContext)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private final String defaultErrorCode; |
| private final String defaultSuccessCode; |
| private final String eventErrorMessageListName; |
| private final String eventErrorMessageName; |
| private final String eventEventMessageListName; |
| private final String eventEventMessageName; |
| private final String eventRequestName; |
| private final String eventResponseCodeName; |
| private final String eventResponseName; |
| private final String eventSessionName; |
| private final String fromLocation; |
| private final boolean loginRequired; |
| private final String methodName; |
| private final List<MethodOperation> methodOperations; |
| private final String serviceErrorMessageListName; |
| private final String serviceErrorMessageMapName; |
| private final String serviceErrorMessageName; |
| private final String serviceResponseMessageName; |
| private final String serviceSuccessMessageListName; |
| private final String serviceSuccessMessageName; |
| private final String shortDescription; |
| private final boolean useTransaction; |
| |
| public SimpleMethod(Element simpleMethodElement, String fromLocation) throws MiniLangException { |
| super(simpleMethodElement, null); |
| if (MiniLangValidate.validationOn()) { |
| String locationMsg = " File = ".concat(fromLocation); |
| if (simpleMethodElement.getAttribute("method-name").isEmpty()) { |
| MiniLangValidate.handleError("Element must include the \"method-name\" attribute.".concat(locationMsg), null, simpleMethodElement); |
| } |
| for (int i = 0; i < DEPRECATED_ATTRIBUTES.length; i++) { |
| if (!simpleMethodElement.getAttribute(DEPRECATED_ATTRIBUTES[i]).isEmpty()) { |
| MiniLangValidate.handleError("Attribute \"" + DEPRECATED_ATTRIBUTES[i] + "\" is deprecated (no replacement)." + locationMsg, null, simpleMethodElement); |
| } |
| } |
| } |
| boolean elementModified = autoCorrect(simpleMethodElement); |
| if (elementModified && MiniLangUtil.autoCorrectOn()) { |
| MiniLangUtil.flagDocumentAsCorrected(simpleMethodElement); |
| } |
| this.fromLocation = fromLocation; |
| methodName = simpleMethodElement.getAttribute("method-name"); |
| shortDescription = simpleMethodElement.getAttribute("short-description"); |
| defaultErrorCode = UtilXml.elementAttribute(simpleMethodElement, "default-error-code", "error"); |
| defaultSuccessCode = UtilXml.elementAttribute(simpleMethodElement, "default-success-code", "success"); |
| eventRequestName = UtilXml.elementAttribute(simpleMethodElement, "event-request-object-name", "request"); |
| eventSessionName = UtilXml.elementAttribute(simpleMethodElement, "event-session-object-name", "session"); |
| eventResponseName = UtilXml.elementAttribute(simpleMethodElement, "event-response-object-name", "response"); |
| eventResponseCodeName = UtilXml.elementAttribute(simpleMethodElement, "event-response-code-name", "_response_code_"); |
| eventErrorMessageName = UtilXml.elementAttribute(simpleMethodElement, "event-error-message-name", "_error_message_"); |
| eventErrorMessageListName = UtilXml.elementAttribute(simpleMethodElement, "event-error-message-list-name", "_error_message_list_"); |
| eventEventMessageName = UtilXml.elementAttribute(simpleMethodElement, "event-event-message-name", "_event_message_"); |
| eventEventMessageListName = UtilXml.elementAttribute(simpleMethodElement, "event-event-message-list-name", "_event_message_list_"); |
| serviceResponseMessageName = UtilXml.elementAttribute(simpleMethodElement, "service-response-message-name", "responseMessage"); |
| serviceErrorMessageName = UtilXml.elementAttribute(simpleMethodElement, "service-error-message-name", "errorMessage"); |
| serviceErrorMessageListName = UtilXml.elementAttribute(simpleMethodElement, "service-error-message-list-name", "errorMessageList"); |
| serviceErrorMessageMapName = UtilXml.elementAttribute(simpleMethodElement, "service-error-message-map-name", "errorMessageMap"); |
| serviceSuccessMessageName = UtilXml.elementAttribute(simpleMethodElement, "service-success-message-name", "successMessage"); |
| serviceSuccessMessageListName = UtilXml.elementAttribute(simpleMethodElement, "service-success-message-list-name", "successMessageList"); |
| loginRequired = !"false".equals(simpleMethodElement.getAttribute("login-required")); |
| useTransaction = !"false".equals(simpleMethodElement.getAttribute("use-transaction")); |
| methodOperations = Collections.unmodifiableList(readOperations(simpleMethodElement, this)); |
| } |
| |
| public void addErrorMessage(MethodContext methodContext, String message) { |
| String messageListName = methodContext.getMethodType() == MethodContext.EVENT ? getEventErrorMessageListName() : getServiceErrorMessageListName(); |
| addMessage(methodContext, messageListName, message); |
| } |
| |
| public void addMessage(MethodContext methodContext, String message) { |
| String messageListName = methodContext.getMethodType() == MethodContext.EVENT ? getEventEventMessageListName() : getServiceSuccessMessageListName(); |
| addMessage(methodContext, messageListName, message); |
| } |
| |
| private void addMessage(MethodContext methodContext, String messageListName, String message) { |
| List<String> messages = methodContext.getEnv(messageListName); |
| if (messages == null) { |
| messages = new LinkedList<String>(); |
| methodContext.putEnv(messageListName, messages); |
| } |
| messages.add(message); |
| } |
| |
| /** Execute the Simple Method operations */ |
| public String exec(MethodContext methodContext) throws MiniLangException { |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "Begin simple-method. Script is running as " + (methodContext.getMethodType() == MethodContext.EVENT ? "an event." : "a service.")); |
| } |
| Locale locale = methodContext.getLocale(); |
| GenericValue userLogin = methodContext.getUserLogin(); |
| if (loginRequired) { |
| if (userLogin == null) { |
| Map<String, Object> messageMap = UtilMisc.<String, Object> toMap("shortDescription", shortDescription); |
| String errMsg = UtilProperties.getMessage(SimpleMethod.err_resource, "simpleMethod.must_logged_process", messageMap, locale) + "."; |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "login-required attribute set to \"true\" but UserLogin GenericValue was not found, returning error message:", errMsg); |
| } |
| return returnError(methodContext, errMsg); |
| } |
| } |
| if (userLogin != null) { |
| methodContext.putEnv(getUserLoginEnvName(), userLogin); |
| } |
| methodContext.putEnv("nullField", GenericEntity.NULL_FIELD); |
| methodContext.putEnv(getDelegatorEnvName(), methodContext.getDelegator()); |
| methodContext.putEnv(getSecurityEnvName(), methodContext.getSecurity()); |
| methodContext.putEnv(getDispatcherEnvName(), methodContext.getDispatcher()); |
| methodContext.putEnv("locale", locale); |
| methodContext.putEnv(getParameterMapName(), methodContext.getParameters()); |
| if (methodContext.getMethodType() == MethodContext.EVENT) { |
| methodContext.putEnv(eventRequestName, methodContext.getRequest()); |
| methodContext.putEnv(eventSessionName, methodContext.getRequest().getSession()); |
| methodContext.putEnv(eventResponseName, methodContext.getResponse()); |
| } |
| methodContext.putEnv("simpleMethod", this); |
| methodContext.putEnv("methodName", this.getMethodName()); |
| methodContext.putEnv("methodShortDescription", this.getShortDescription()); |
| // if using transaction, try to start here |
| boolean beganTransaction = false; |
| if (useTransaction) { |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "use-transaction attribute set to \"true\", beginning transaction."); |
| } |
| try { |
| beganTransaction = TransactionUtil.begin(); |
| } catch (GenericTransactionException e) { |
| String errMsg = UtilProperties.getMessage(SimpleMethod.err_resource, "simpleMethod.error_begin_transaction", locale) + ": " + e.getMessage(); |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "An exception was thrown while beginning a transaction, returning error message:", errMsg); |
| } |
| return returnError(methodContext, errMsg); |
| } |
| } |
| // declare errorMsg here just in case transaction ops fail |
| String errorMsg = ""; |
| boolean finished = false; |
| try { |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "Begin running sub-elements."); |
| } |
| finished = runSubOps(methodOperations, methodContext); |
| } catch (Throwable t) { |
| // make SURE nothing gets thrown through |
| String errMsg = UtilProperties.getMessage(SimpleMethod.err_resource, "simpleMethod.error_running", locale) + ": " + t.getMessage(); |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "An exception was thrown while running sub-elements, error message was:", errMsg); |
| } |
| finished = false; |
| errorMsg += errMsg; |
| } |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "End running sub-elements."); |
| } |
| String returnValue = null; |
| String response = null; |
| StringBuilder summaryErrorStringBuffer = new StringBuilder(); |
| if (methodContext.getMethodType() == MethodContext.EVENT) { |
| boolean forceError = false; |
| String tempErrorMsg = (String) methodContext.getEnv(eventErrorMessageName); |
| if (errorMsg.length() > 0 || UtilValidate.isNotEmpty(tempErrorMsg)) { |
| errorMsg += tempErrorMsg; |
| methodContext.getRequest().setAttribute("_ERROR_MESSAGE_", errorMsg); |
| forceError = true; |
| summaryErrorStringBuffer.append(errorMsg); |
| } |
| List<Object> tempErrorMsgList = UtilGenerics.checkList(methodContext.getEnv(eventErrorMessageListName)); |
| if (UtilValidate.isNotEmpty(tempErrorMsgList)) { |
| methodContext.getRequest().setAttribute("_ERROR_MESSAGE_LIST_", tempErrorMsgList); |
| forceError = true; |
| summaryErrorStringBuffer.append("; "); |
| summaryErrorStringBuffer.append(tempErrorMsgList.toString()); |
| } |
| String eventMsg = (String) methodContext.getEnv(eventEventMessageName); |
| if (UtilValidate.isNotEmpty(eventMsg)) { |
| methodContext.getRequest().setAttribute("_EVENT_MESSAGE_", eventMsg); |
| } |
| List<String> eventMsgList = UtilGenerics.checkList(methodContext.getEnv(eventEventMessageListName)); |
| if (UtilValidate.isNotEmpty(eventMsgList)) { |
| methodContext.getRequest().setAttribute("_EVENT_MESSAGE_LIST_", eventMsgList); |
| } |
| response = (String) methodContext.getEnv(eventResponseCodeName); |
| if (UtilValidate.isEmpty(response)) { |
| if (forceError) { |
| // override response code, always use error code |
| Debug.logInfo("No response code string found, but error messages found so assuming error; returning code [" + defaultErrorCode + "]", module); |
| response = defaultErrorCode; |
| } else { |
| Debug.logInfo("No response code string or errors found, assuming success; returning code [" + defaultSuccessCode + "]", module); |
| response = defaultSuccessCode; |
| } |
| } else if ("null".equalsIgnoreCase(response)) { |
| response = null; |
| } |
| returnValue = response; |
| } else { |
| boolean forceError = false; |
| String tempErrorMsg = (String) methodContext.getEnv(serviceErrorMessageName); |
| if (errorMsg.length() > 0 || UtilValidate.isNotEmpty(tempErrorMsg)) { |
| errorMsg += tempErrorMsg; |
| methodContext.putResult(ModelService.ERROR_MESSAGE, errorMsg); |
| forceError = true; |
| summaryErrorStringBuffer.append(errorMsg); |
| } |
| List<Object> errorMsgList = UtilGenerics.checkList(methodContext.getEnv(serviceErrorMessageListName)); |
| if (UtilValidate.isNotEmpty(errorMsgList)) { |
| methodContext.putResult(ModelService.ERROR_MESSAGE_LIST, errorMsgList); |
| forceError = true; |
| summaryErrorStringBuffer.append("; "); |
| summaryErrorStringBuffer.append(errorMsgList.toString()); |
| } |
| Map<String, Object> errorMsgMap = UtilGenerics.checkMap(methodContext.getEnv(serviceErrorMessageMapName)); |
| if (UtilValidate.isNotEmpty(errorMsgMap)) { |
| methodContext.putResult(ModelService.ERROR_MESSAGE_MAP, errorMsgMap); |
| forceError = true; |
| summaryErrorStringBuffer.append("; "); |
| summaryErrorStringBuffer.append(errorMsgMap.toString()); |
| } |
| String successMsg = (String) methodContext.getEnv(serviceSuccessMessageName); |
| if (UtilValidate.isNotEmpty(successMsg)) { |
| methodContext.putResult(ModelService.SUCCESS_MESSAGE, successMsg); |
| } |
| List<Object> successMsgList = UtilGenerics.checkList(methodContext.getEnv(serviceSuccessMessageListName)); |
| if (UtilValidate.isNotEmpty(successMsgList)) { |
| methodContext.putResult(ModelService.SUCCESS_MESSAGE_LIST, successMsgList); |
| } |
| response = (String) methodContext.getEnv(serviceResponseMessageName); |
| if (UtilValidate.isEmpty(response)) { |
| if (forceError) { |
| // override response code, always use error code |
| Debug.logVerbose("No response code string found, but error messages found so assuming error; returning code [" + defaultErrorCode + "]", module); |
| response = defaultErrorCode; |
| } else { |
| Debug.logVerbose("No response code string or errors found, assuming success; returning code [" + defaultSuccessCode + "]", module); |
| response = defaultSuccessCode; |
| } |
| } |
| methodContext.putResult(ModelService.RESPONSE_MESSAGE, response); |
| returnValue = response; |
| } |
| // decide whether or not to commit based on the response message, ie only rollback if error is returned and not finished |
| boolean doCommit = true; |
| if (!finished && defaultErrorCode.equals(response)) { |
| doCommit = false; |
| } |
| if (doCommit) { |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "Begin commit transaction."); |
| } |
| // commit here passing beganTransaction to perform it properly |
| try { |
| TransactionUtil.commit(beganTransaction); |
| } catch (GenericTransactionException e) { |
| String errMsg = "Error trying to commit transaction, could not process method: " + e.getMessage(); |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "An exception was thrown while committing a transaction, returning error message:", errMsg); |
| } |
| errorMsg += errMsg; |
| } |
| } else { |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "Begin roll back transaction."); |
| } |
| // rollback here passing beganTransaction to either rollback, or set rollback only |
| try { |
| TransactionUtil.rollback(beganTransaction, "Error in simple-method [" + this.getShortDescription() + "]: " + summaryErrorStringBuffer, null); |
| } catch (GenericTransactionException e) { |
| String errMsg = "Error trying to rollback transaction, could not process method: " + e.getMessage(); |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "An exception was thrown while rolling back a transaction, returning error message:", errMsg); |
| } |
| errorMsg += errMsg; |
| } |
| } |
| if (methodContext.isTraceOn()) { |
| outputTraceMessage(methodContext, "End simple-method."); |
| } |
| return returnValue; |
| } |
| |
| @Override |
| public void gatherArtifactInfo(ArtifactInfoContext aic) { |
| for (MethodOperation methodOp : this.methodOperations) { |
| methodOp.gatherArtifactInfo(aic); |
| } |
| } |
| |
| @Deprecated |
| public Set<String> getAllEntityNamesUsed() throws MiniLangException { |
| ArtifactInfoContext aic = new ArtifactInfoContext(); |
| gatherArtifactInfo(aic); |
| return aic.getEntityNames(); |
| } |
| |
| @Deprecated |
| public Set<String> getAllServiceNamesCalled() throws MiniLangException { |
| ArtifactInfoContext aic = new ArtifactInfoContext(); |
| gatherArtifactInfo(aic); |
| return aic.getServiceNames(); |
| } |
| |
| public String getDefaultErrorCode() { |
| return this.defaultErrorCode; |
| } |
| |
| public String getDefaultSuccessCode() { |
| return this.defaultSuccessCode; |
| } |
| |
| public String getDelegatorEnvName() { |
| return "delegator"; |
| } |
| |
| public String getDispatcherEnvName() { |
| return "dispatcher"; |
| } |
| |
| public String getEventErrorMessageListName() { |
| return this.eventErrorMessageListName; |
| } |
| |
| public String getEventErrorMessageName() { |
| return this.eventErrorMessageName; |
| } |
| |
| public String getEventEventMessageListName() { |
| return this.eventEventMessageListName; |
| } |
| |
| public String getEventEventMessageName() { |
| return this.eventEventMessageName; |
| } |
| |
| // event fields |
| public String getEventRequestName() { |
| return this.eventRequestName; |
| } |
| |
| public String getEventResponseCodeName() { |
| return this.eventResponseCodeName; |
| } |
| |
| public String getEventSessionName() { |
| return this.eventSessionName; |
| } |
| |
| public String getFileName() { |
| return this.fromLocation.substring(this.fromLocation.lastIndexOf("/") + 1); |
| } |
| |
| public String getFromLocation() { |
| return this.fromLocation; |
| } |
| |
| public String getLocationAndName() { |
| return this.fromLocation + "#" + this.methodName; |
| } |
| |
| public boolean getLoginRequired() { |
| return this.loginRequired; |
| } |
| |
| public String getMethodName() { |
| return this.methodName; |
| } |
| |
| public List<MethodOperation> getMethodOperations() { |
| return this.methodOperations; |
| } |
| |
| public String getParameterMapName() { |
| return "parameters"; |
| } |
| |
| public String getSecurityEnvName() { |
| return "security"; |
| } |
| |
| public String getServiceErrorMessageListName() { |
| return this.serviceErrorMessageListName; |
| } |
| |
| public String getServiceErrorMessageMapName() { |
| return this.serviceErrorMessageMapName; |
| } |
| |
| public String getServiceErrorMessageName() { |
| return this.serviceErrorMessageName; |
| } |
| |
| public String getServiceResponseMessageName() { |
| return this.serviceResponseMessageName; |
| } |
| |
| public String getServiceSuccessMessageListName() { |
| return this.serviceSuccessMessageListName; |
| } |
| |
| public String getServiceSuccessMessageName() { |
| return this.serviceSuccessMessageName; |
| } |
| |
| public String getShortDescription() { |
| return this.shortDescription + " [" + this.fromLocation + "#" + this.methodName + "]"; |
| } |
| |
| @Override |
| public SimpleMethod getSimpleMethod() { |
| return this; |
| } |
| |
| public String getUserLoginEnvName() { |
| return "userLogin"; |
| } |
| |
| public boolean getUseTransaction() { |
| return this.useTransaction; |
| } |
| |
| private String returnError(MethodContext methodContext, String errorMsg) { |
| if (methodContext.getMethodType() == MethodContext.EVENT) { |
| methodContext.getRequest().setAttribute("_ERROR_MESSAGE_", errorMsg); |
| } else { |
| methodContext.putResult(ModelService.ERROR_MESSAGE, errorMsg); |
| methodContext.putResult(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR); |
| } |
| return defaultErrorCode; |
| } |
| } |