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


Reply via email to