You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jl...@apache.org on 2011/03/18 07:45:55 UTC

svn commit: r1082829 - /ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java

Author: jleroux
Date: Fri Mar 18 06:45:54 2011
New Revision: 1082829

URL: http://svn.apache.org/viewvc?rev=1082829&view=rev
Log:
A patch from chris snow "SOAP improvements" (https://issues.apache.org/jira/browse/OFBIZ-4218) - OFBIZ-4218

1) SOAPHandler fault handling and error logging improvements
2) Current SOAPHandler allows multiple service requests in the SOAPBody. There should only be one service request.
3) Error messages give too much information in soap response to potential hackers.

Modified:
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java?rev=1082829&r1=1082828&r2=1082829&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java Fri Mar 18 06:45:54 2011
@@ -48,14 +48,14 @@ import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilGenerics;
 import org.ofbiz.base.util.UtilXml;
 import org.ofbiz.entity.GenericDelegator;
-import org.ofbiz.service.engine.SoapSerializer;
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
-import org.ofbiz.webapp.control.RequestHandler;
+import org.ofbiz.service.engine.SoapSerializer;
 import org.ofbiz.webapp.control.ConfigXMLReader.Event;
 import org.ofbiz.webapp.control.ConfigXMLReader.RequestMap;
+import org.ofbiz.webapp.control.RequestHandler;
 import org.w3c.dom.Document;
 
 /**
@@ -168,72 +168,100 @@ public class SOAPEventHandler implements
         Debug.logVerbose("[Processing]: SOAP Event", module);
 
         try {
-            // each is a different service call
             SOAPBody reqBody = reqEnv.getBody();
-            Iterator<Object> serviceIter = UtilGenerics.cast(reqBody.getChildElements());
-            while (serviceIter.hasNext()) {
-                Object serviceObj = serviceIter.next();
-                if (serviceObj instanceof OMElement) {
-                    OMElement serviceElement = (OMElement) serviceObj;
-                    String serviceName = serviceElement.getLocalName();
-                    Map<String, Object> parameters = UtilGenerics.cast(SoapSerializer.deserialize(serviceElement.toString(), delegator));
-                    try {
-                        // verify the service is exported for remote execution and invoke it
-                        ModelService model = dispatcher.getDispatchContext().getModelService(serviceName);
+            validateSOAPBody(reqBody);
+            OMElement serviceElement = reqBody.getFirstElement();
+            String serviceName = serviceElement.getLocalName();
+            Map<String, Object> parameters = UtilGenerics.cast(SoapSerializer.deserialize(serviceElement.toString(), delegator));
+            try {
+                // verify the service is exported for remote execution and invoke it
+                ModelService model = dispatcher.getDispatchContext().getModelService(serviceName);
+
+                if (model == null) {
+                    sendError(response, "Problem processing the service");
+                    Debug.logError("Could not find Service [" + serviceName + "].", module);
+                    return null;
+                }
 
-                        if (model != null && model.export) {
-                            Map<String, Object> results = dispatcher.runSync(serviceName, parameters);
-                            Debug.logVerbose("[EventHandler] : Service invoked", module);
-
-                            // setup the response
-                            Debug.logVerbose("[EventHandler] : Setting up response message", module);
-                            String xmlResults = SoapSerializer.serialize(results);
-                            XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xmlResults));
-                            StAXOMBuilder resultsBuilder = new StAXOMBuilder(reader);
-                            OMElement resultSer = resultsBuilder.getDocumentElement();
-
-                            // create the response soap
-                            SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
-                            SOAPEnvelope resEnv = factory.createSOAPEnvelope();
-                            SOAPBody resBody = factory.createSOAPBody();
-                            OMElement resService = factory.createOMElement(new QName(serviceName + "Response"));
-                            resService.addChild(resultSer.getFirstElement());
-                            resBody.addChild(resService);
-                            resEnv.addChild(resBody);
-
-                            // The declareDefaultNamespace method doesn't work see (https://issues.apache.org/jira/browse/AXIS2-3156)
-                            // so the following doesn't work:
-                            // resService.declareDefaultNamespace(ModelService.TNS);
-                            // instead, create the xmlns attribute directly:
-                            OMAttribute defaultNS = factory.createOMAttribute("xmlns", null, ModelService.TNS);
-                            resService.addAttribute(defaultNS);
-
-                            // log the response message
-                            if (Debug.verboseOn()) {
-                                try {
-                                    Debug.log("Response Message:\n" + resEnv + "\n", module);
-                                } catch (Throwable t) {
-                                }
-                            }
+                if (!model.export) {
+                    sendError(response, "Problem processing the service");
+                    Debug.logError("Trying to call Service [" + serviceName + "] that is not exported.", module);
+                    return null;
+                }
 
-                            resEnv.serialize(response.getOutputStream());
-                            response.getOutputStream().flush();
-                        }
+                Map<String, Object> serviceResults = dispatcher.runSync(serviceName, parameters);
+                Debug.logVerbose("[EventHandler] : Service invoked", module);
 
-                    } catch (GenericServiceException e) {
-                        //sendError(response, "Problem processing the service"); this causes a not a valid XML response. See https://issues.apache.org/jira/browse/OFBIZ-4207
-                        throw new EventHandlerException(e.getMessage(), e);
-                    }
-                }
+                createAndSendSOAPResponse(serviceResults, serviceName, response);
+
+            } catch (GenericServiceException e) {
+                sendError(response, "Problem processing the service");
+                Debug.logError(e, module);
+                return null;
             }
         } catch (Exception e) {
             sendError(response, e.getMessage());
-            throw new EventHandlerException(e.getMessage(), e);
+            Debug.logError(e, module);
+            return null;
         }
 
         return null;
     }
 
+    private void validateSOAPBody(SOAPBody reqBody) throws EventHandlerException {
+        // ensure the SOAPBody contains only one service call request
+        Integer numServiceCallRequests = 0;
+        Iterator<Object> serviceIter = UtilGenerics.cast(reqBody.getChildElements());
+        while (serviceIter.hasNext()) {
+            numServiceCallRequests++;
+            serviceIter.next();
+        }
+        if (numServiceCallRequests != 1) {
+            throw new EventHandlerException("One service call expected, but received: " + numServiceCallRequests.toString());
+        }
+    }
+
+    private void createAndSendSOAPResponse(Map<String, Object> serviceResults, String serviceName, HttpServletResponse response) throws EventHandlerException {
+        try {
+        // setup the response
+            Debug.logVerbose("[EventHandler] : Setting up response message", module);
+            String xmlResults = SoapSerializer.serialize(serviceResults);
+            XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xmlResults));
+            StAXOMBuilder resultsBuilder = new StAXOMBuilder(reader);
+            OMElement resultSer = resultsBuilder.getDocumentElement();
+
+            // create the response soap
+            SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
+            SOAPEnvelope resEnv = factory.createSOAPEnvelope();
+            SOAPBody resBody = factory.createSOAPBody();
+            OMElement resService = factory.createOMElement(new QName(serviceName + "Response"));
+            resService.addChild(resultSer.getFirstElement());
+            resBody.addChild(resService);
+            resEnv.addChild(resBody);
+
+            // The declareDefaultNamespace method doesn't work see (https://issues.apache.org/jira/browse/AXIS2-3156)
+            // so the following doesn't work:
+            // resService.declareDefaultNamespace(ModelService.TNS);
+            // instead, create the xmlns attribute directly:
+            OMAttribute defaultNS = factory.createOMAttribute("xmlns", null, ModelService.TNS);
+            resService.addAttribute(defaultNS);
+            
+            // log the response message
+            if (Debug.verboseOn()) {
+                try {
+                    Debug.log("Response Message:\n" + resEnv + "\n", module);
+                } catch (Throwable t) {
+                }
+            }
+
+            resEnv.serialize(response.getOutputStream());
+            response.getOutputStream().flush();
+        } catch (Exception e) {
+            Debug.logError(e, module);
+            throw new EventHandlerException(e.getMessage(), e);
+        }
+    }
+
     private void sendError(HttpServletResponse res, String errorMessage) throws EventHandlerException {
         try {
             // setup the response