You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by sh...@apache.org on 2018/06/27 05:49:00 UTC

svn commit: r1834465 - in /ofbiz/ofbiz-framework/trunk/framework/webapp: config/ src/main/java/org/apache/ofbiz/webapp/control/ src/test/java/org/apache/ofbiz/webapp/control/

Author: shijh
Date: Wed Jun 27 05:48:59 2018
New Revision: 1834465

URL: http://svn.apache.org/viewvc?rev=1834465&view=rev
Log:
Implemented: Add method attribute to request-map to controll a uri can be called GET or POST only
OFBIZ-10438

ControlServlet.java returned to the previous doGet/doPost structure.

Thanks: Mathieu Lirzin for the contribution.

Added:
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java   (with props)
Modified:
    ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml?rev=1834465&r1=1834464&r2=1834465&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml Wed Jun 27 05:48:59 2018
@@ -340,7 +340,7 @@
         <value xml:lang="zh-TW">沒有完成事件</value>
     </property>
     <property key="RequestMethodNotMatchConfig">
-        <value xml:lang="en">[{0}] is restricted to be a [{1}] request, cannot be called by [{2}] method.</value>
-        <value xml:lang="zh">[{0}]必须使用[{1}]方法请求,不能用[{2}]方法请求。</value>
+        <value xml:lang="en">[{0}] cannot be called by [{1}] method.</value>
+        <value xml:lang="zh">[{0}]不能用[{1}]方法请求。</value>
     </property>
 </resource>

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java?rev=1834465&r1=1834464&r2=1834465&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java Wed Jun 27 05:48:59 2018
@@ -19,7 +19,6 @@
 package org.apache.ofbiz.webapp.control;
 
 import java.io.IOException;
-import java.net.URL;
 import java.util.Enumeration;
 
 import javax.servlet.RequestDispatcher;
@@ -30,14 +29,11 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilGenerics;
 import org.apache.ofbiz.base.util.UtilHttp;
-import org.apache.ofbiz.base.util.UtilMisc;
-import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilTimer;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.template.FreeMarkerWorker;
@@ -49,7 +45,6 @@ import org.apache.ofbiz.entity.transacti
 import org.apache.ofbiz.entity.transaction.TransactionUtil;
 import org.apache.ofbiz.security.Security;
 import org.apache.ofbiz.service.LocalDispatcher;
-import org.apache.ofbiz.webapp.control.ConfigXMLReader.RequestMap;
 import org.apache.ofbiz.webapp.stats.ServerHitBin;
 import org.apache.ofbiz.webapp.stats.VisitHandler;
 import org.apache.ofbiz.widget.renderer.VisualTheme;
@@ -63,9 +58,6 @@ import freemarker.ext.servlet.ServletCon
 public class ControlServlet extends HttpServlet {
 
     public static final String module = ControlServlet.class.getName();
-    private static final String METHOD_GET = "GET";
-    private static final String METHOD_POST = "POST";
-    private static final String REQUEST_METHOD_ALL = "all";
 
     public ControlServlet() {
         super();
@@ -88,20 +80,20 @@ public class ControlServlet extends Http
     }
 
     /**
-     * Handle every HTTP methods.
-     * @see javax.servlet.http.HttpServlet#service
+     * @see javax.servlet.http.HttpServlet#doPost
      */
     @Override
-    protected void service(HttpServletRequest request, HttpServletResponse response)
+    protected void doPost(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        doGet(request, response);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doGet
+     */
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
-        String method = request.getMethod();
-        if (!matchRequestMethod(request, response, method)) {
-            return;
-        }
-        if (!method.equals(METHOD_GET) && !method.equals(METHOD_POST)) {
-            super.service(request, response);
-            return;
-        }
         long requestStartTime = System.currentTimeMillis();
         RequestHandler requestHandler = this.getRequestHandler();
         HttpSession session = request.getSession();
@@ -221,6 +213,12 @@ public class ControlServlet extends Http
         try {
             // the ServerHitBin call for the event is done inside the doRequest method
             requestHandler.doRequest(request, response, null, userLogin, delegator);
+        } catch (MethodNotAllowedException e) {
+            response.setContentType("text/plain");
+            response.setCharacterEncoding(request.getCharacterEncoding());
+            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+            response.getWriter().print(e.getMessage());
+            Debug.logError(e.getMessage(), module);
         } catch (RequestHandlerException e) {
             Throwable throwable = e.getNested() != null ? e.getNested() : e;
             if (throwable instanceof IOException) {
@@ -388,29 +386,4 @@ public class ControlServlet extends Http
         }
         if (Debug.verboseOn()) Debug.logVerbose("--- End ServletContext Attributes ---", module);
     }
-
-    private boolean matchRequestMethod(HttpServletRequest request, HttpServletResponse response, String method) {
-        URL controllerConfigUrl = ConfigXMLReader.getControllerConfigURL(request.getServletContext());
-        try {
-            ConfigXMLReader.ControllerConfig controllerConfig = ConfigXMLReader.getControllerConfig(controllerConfigUrl);
-            MultivaluedMap<String, RequestMap> requestMapMap = controllerConfig.getRequestMapMultiMap();
-            if (UtilValidate.isEmpty(requestMapMap)) {
-                return true;
-            }
-            String uri = RequestHandler.getRequestUri(request.getPathInfo());
-            RequestMap requestMap = requestMapMap.getFirst(uri);
-            if (UtilValidate.isEmpty(requestMap) || UtilValidate.isEmpty(requestMap.method) || REQUEST_METHOD_ALL.equalsIgnoreCase(requestMap.method) || method.equalsIgnoreCase(requestMap.method)) {
-                return true;
-            }
-            String errMsg = UtilProperties.getMessage("WebappUiLabels", "RequestMethodNotMatchConfig", UtilMisc.toList(uri, requestMap.method, method), UtilHttp.getLocale(request));
-            response.setContentType("text/plain");
-            response.setCharacterEncoding(request.getCharacterEncoding());
-            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-            response.getWriter().print(errMsg);
-            Debug.logError(errMsg, module);
-        } catch (WebAppConfigurationException | IOException e) {
-            Debug.logError("Error while loading " + controllerConfigUrl, module);
-        }
-        return false;
-    }
 }

Added: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java?rev=1834465&view=auto
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java (added)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java Wed Jun 27 05:48:59 2018
@@ -0,0 +1,9 @@
+package org.apache.ofbiz.webapp.control;
+
+class MethodNotAllowedException extends RequestHandlerException {
+    private static final long serialVersionUID = -8765719278480440687L;
+
+    MethodNotAllowedException(String str) {
+        super(str);
+    }
+}

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java?rev=1834465&r1=1834464&r2=1834465&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java Wed Jun 27 05:48:59 2018
@@ -24,6 +24,8 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.net.URL;
 import java.security.cert.X509Certificate;
+
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -31,8 +33,6 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -74,12 +74,77 @@ import org.apache.ofbiz.widget.model.The
 public class RequestHandler {
 
     public static final String module = RequestHandler.class.getName();
-    private final String defaultStatusCodeString = UtilProperties.getPropertyValue("requestHandler", "status-code", "302");
+    private final static String defaultStatusCodeString =
+            UtilProperties.getPropertyValue("requestHandler", "status-code", "302");
     private final ViewFactory viewFactory;
     private final EventFactory eventFactory;
     private final URL controllerConfigURL;
     private final boolean trackServerHit;
     private final boolean trackVisit;
+    private Controller ctrl;
+
+    static class Controller {
+        private final MultivaluedMap<String, RequestMap> requestMapMap;
+        private final Map<String, ConfigXMLReader.ViewMap> viewMapMap;
+        private String statusCodeString;
+        private final String defaultRequest;
+        private final Map<String, ConfigXMLReader.Event> firstVisitEventList;
+        private final Map<String, ConfigXMLReader.Event> preprocessorEventList;
+        private final Map<String, ConfigXMLReader.Event> postprocessorEventList;
+        private final String protectView;
+
+        Controller(ConfigXMLReader.ControllerConfig ccfg)
+                throws WebAppConfigurationException {
+            preprocessorEventList = ccfg.getPreprocessorEventList();
+            postprocessorEventList = ccfg.getPostprocessorEventList();
+            requestMapMap = ccfg.getRequestMapMultiMap();
+            viewMapMap = ccfg.getViewMapMap();
+            defaultRequest = ccfg.getDefaultRequest();
+            firstVisitEventList = ccfg.getFirstVisitEventList();
+            protectView = ccfg.getProtectView();
+
+            String status = ccfg.getStatusCode();
+            statusCodeString = UtilValidate.isEmpty(status)
+                    ? defaultStatusCodeString
+                    : status;
+        }
+
+        public MultivaluedMap<String, RequestMap> getRequestMapMap() {
+            return requestMapMap;
+        }
+
+        public Map<String, ConfigXMLReader.ViewMap> getViewMapMap() {
+            return viewMapMap;
+        }
+
+        public String getStatusCodeString() {
+            return statusCodeString;
+        }
+
+        public String getDefaultRequest() {
+            return defaultRequest;
+        }
+
+        public void setStatusCodeString(String statusCodeString) {
+            this.statusCodeString = statusCodeString;
+        }
+
+        public Map<String, ConfigXMLReader.Event> getFirstVisitEventList() {
+            return firstVisitEventList;
+        }
+
+        public Map<String, ConfigXMLReader.Event> getPreprocessorEventList() {
+            return preprocessorEventList;
+        }
+
+        public Map<String, ConfigXMLReader.Event> getPostprocessorEventList() {
+            return postprocessorEventList;
+        }
+
+        public String getProtectView() {
+            return protectView;
+        }
+    }
 
     public static RequestHandler getRequestHandler(ServletContext servletContext) {
         RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_");
@@ -117,26 +182,56 @@ public class RequestHandler {
     }
 
     /**
-     * Find a request map in {@code reqMaps} matching {@code req}.
-     * Otherwise fall back to the one matching {@code defaultReq}.
+     * Find a collection of request maps in {@code ctrl} matching {@code req}.
+     * Otherwise fall back to matching the {@code defaultReq} field.
      *
-     * @param reqMaps The dictionary associating URI to request maps
+     * @param ctrl The controller containing the current configuration
      * @param req The HTTP request to match
-     * @param defaultReq the default request which serves as a fallback.
-     * @return an request map {@code Optional}
+     * @return a collection of request maps which might be empty
      */
-    static Optional<RequestMap> resolveURI(MultivaluedMap<String, RequestMap> reqMaps,
-            HttpServletRequest req, String defaultReq) {
-        String path = getRequestUri(req.getPathInfo());
-        List<RequestMap> rmaps = reqMaps.get(path);
-        if (rmaps == null && defaultReq != null) {
-            rmaps = reqMaps.get(defaultReq);
-        }
-        List<RequestMap> frmaps = (rmaps != null) ? rmaps : Collections.emptyList();
-        return Stream.of(req.getMethod(), "all", "")
-                .map(verb -> (Predicate<String>) verb::equalsIgnoreCase)
-                .flatMap(p -> frmaps.stream().filter(m -> p.test(m.method)))
-                .findFirst();
+    static Collection<RequestMap> resolveURI(Controller ctrl,
+                                             HttpServletRequest req) {
+        Map<String, List<RequestMap>> requestMapMap = ctrl.getRequestMapMap();
+        Map<String, ConfigXMLReader.ViewMap> viewMapMap = ctrl.getViewMapMap();
+        String defaultRequest = ctrl.getDefaultRequest();
+        String path = req.getPathInfo();
+        String requestUri = getRequestUri(path);
+        String viewUri = getOverrideViewUri(path);
+        Collection<RequestMap> rmaps;
+        if (requestMapMap.containsKey(requestUri)
+                && !viewMapMap.containsKey(viewUri)) {
+            rmaps = requestMapMap.get(requestUri);
+        } else if (defaultRequest != null) {
+            rmaps = requestMapMap.get(defaultRequest);
+        } else {
+            rmaps = null;
+        }
+        return rmaps != null ? rmaps : Collections.emptyList();
+    }
+
+    /**
+     * Find the request map matching {@code method}.
+     * Otherwise fall back to the one matching the "all" and "" special methods
+     * in that respective order.
+     *
+     * @param method the HTTP method to match
+     * @param rmaps the collection of request map candidates
+     * @return a request map {@code Optional}
+     */
+    static Optional<RequestMap> resolveMethod(String method,
+                                              Collection<RequestMap> rmaps) {
+        for (RequestMap map : rmaps) {
+            if (map.method.equalsIgnoreCase(method)) {
+                return Optional.of(map);
+            }
+        }
+        if (method.isEmpty()) {
+            return Optional.empty();
+        } else if (method.equals("all")) {
+            return resolveMethod("", rmaps);
+        } else {
+            return resolveMethod("all", rmaps);
+        }
     }
 
     public void doRequest(HttpServletRequest request, HttpServletResponse response, String requestUri) throws RequestHandlerException, RequestHandlerExceptionAllowExternalRequests {
@@ -154,33 +249,17 @@ public class RequestHandler {
         long startTime = System.currentTimeMillis();
         HttpSession session = request.getSession();
 
-        // get the controllerConfig once for this method so we don't have to get it over and over inside the method
-        ConfigXMLReader.ControllerConfig controllerConfig = this.getControllerConfig();
-        MultivaluedMap<String, ConfigXMLReader.RequestMap> requestMapMap = null;
-        String statusCodeString = null;
+        // Parse controller config.
         try {
-            requestMapMap = controllerConfig.getRequestMapMultiMap();
-            statusCodeString = controllerConfig.getStatusCode();
+            ctrl = new Controller(getControllerConfig());
         } catch (WebAppConfigurationException e) {
             Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
             throw new RequestHandlerException(e);
         }
-        if (UtilValidate.isEmpty(statusCodeString)) {
-            statusCodeString = defaultStatusCodeString;
-        }
 
         // workaround if we are in the root webapp
         String cname = UtilHttp.getApplicationName(request);
 
-        // Set the fallback default request.
-        String defaultRequest = null;
-        try {
-            defaultRequest = controllerConfig.getDefaultRequest();
-        } catch (WebAppConfigurationException e) {
-            Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
-            throw new RequestHandlerException(e);
-        }
-
         // Grab data from request object to process
         String defaultRequestUri = RequestHandler.getRequestUri(request.getPathInfo());
         if (request.getAttribute("targetRequestUri") == null) {
@@ -191,32 +270,32 @@ public class RequestHandler {
             }
         }
 
-        String overrideViewUri = RequestHandler.getOverrideViewUri(request.getPathInfo());
-
-        String requestMissingErrorMessage = "Unknown request [" + defaultRequestUri + "]; this request does not exist or cannot be called directly.";
-        RequestMap requestMap =
-                resolveURI(requestMapMap, request, defaultRequest).orElse(null);
-
-        // check for override view
-        if (overrideViewUri != null) {
-            try {
-                ConfigXMLReader.ViewMap viewMap =
-                        controllerConfig.getViewMapMap().get(overrideViewUri);
-                if (viewMap == null && defaultRequest != null) {
-                    requestMap = requestMapMap.getFirst(defaultRequest);
-                }
-            } catch (WebAppConfigurationException e) {
-                Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
-                throw new RequestHandlerException(e);
+        String requestMissingErrorMessage = "Unknown request ["
+                + defaultRequestUri
+                + "]; this request does not exist or cannot be called directly.";
+
+        String path = request.getPathInfo();
+        String requestUri = getRequestUri(path);
+        String overrideViewUri = getOverrideViewUri(path);
+
+        Collection<RequestMap> rmaps = resolveURI(ctrl, request);
+        if (rmaps.isEmpty()) {
+            if (throwRequestHandlerExceptionOnMissingLocalRequest) {
+              throw new RequestHandlerException(requestMissingErrorMessage);
+            } else {
+              throw new RequestHandlerExceptionAllowExternalRequests();
             }
         }
 
-        // if no matching request is found in the controller, depending on throwRequestHandlerExceptionOnMissingLocalRequest
-        //  we throw a RequestHandlerException or RequestHandlerExceptionAllowExternalRequests
-        if (requestMap == null) {
-            if (throwRequestHandlerExceptionOnMissingLocalRequest) throw new RequestHandlerException(requestMissingErrorMessage);
-            else throw new RequestHandlerExceptionAllowExternalRequests();
-        }
+        String method = request.getMethod();
+        RequestMap requestMap = resolveMethod(method, rmaps)
+                .orElseThrow(() -> {
+                    String msg = UtilProperties.getMessage("WebappUiLabels",
+                            "RequestMethodNotMatchConfig",
+                            UtilMisc.toList(requestUri, method),
+                            UtilHttp.getLocale(request));
+                    return new MethodNotAllowedException(msg);
+                });
 
         String eventReturn = null;
         if (requestMap.metrics != null && requestMap.metrics.getThreshold() != 0.0 && requestMap.metrics.getTotalEvents() > 3 && requestMap.metrics.getThreshold() < requestMap.metrics.getServiceRate()) {
@@ -228,7 +307,7 @@ public class RequestHandler {
         // Check for chained request.
         if (chain != null) {
             String chainRequestUri = RequestHandler.getRequestUri(chain);
-            requestMap = requestMapMap.getFirst(chainRequestUri);
+            requestMap = ctrl.getRequestMapMap().getFirst(chainRequestUri);
             if (requestMap == null) {
                 throw new RequestHandlerException("Unknown chained request [" + chainRequestUri + "]; this request does not exist");
             }
@@ -252,11 +331,11 @@ public class RequestHandler {
             // Check to make sure we are allowed to access this request directly. (Also checks if this request is defined.)
             // If the request cannot be called, or is not defined, check and see if there is a default-request we can process
             if (!requestMap.securityDirectRequest) {
-                if (defaultRequest == null || !requestMapMap.getFirst(defaultRequest).securityDirectRequest) {
+                if (ctrl.getDefaultRequest() == null || !ctrl.getRequestMapMap().getFirst(ctrl.getDefaultRequest()).securityDirectRequest) {
                     // use the same message as if it was missing for security reasons, ie so can't tell if it is missing or direct request is not allowed
                     throw new RequestHandlerException(requestMissingErrorMessage);
                 } else {
-                    requestMap = requestMapMap.getFirst(defaultRequest);
+                    requestMap = ctrl.getRequestMapMap().getFirst(ctrl.getDefaultRequest());
                 }
             }
             // Check if we SHOULD be secure and are not.
@@ -299,7 +378,7 @@ public class RequestHandler {
                     String newUrl = RequestHandler.makeUrl(request, response, urlBuf.toString());
                     if (newUrl.toUpperCase().startsWith("HTTPS")) {
                         // if we are supposed to be secure, redirect secure.
-                        callRedirect(newUrl, response, request, statusCodeString);
+                        callRedirect(newUrl, response, request, ctrl.getStatusCodeString());
                         return;
                     }
                 }
@@ -344,63 +423,52 @@ public class RequestHandler {
                 if (Debug.infoOn())
                     Debug.logInfo("This is the first request in this visit." + showSessionId(request), module);
                 session.setAttribute("_FIRST_VISIT_EVENTS_", "complete");
-                try {
-                    for (ConfigXMLReader.Event event: controllerConfig.getFirstVisitEventList().values()) {
-                        try {
-                            String returnString = this.runEvent(request, response, event, null, "firstvisit");
-                            if (returnString == null || "none".equalsIgnoreCase(returnString)) {
-                                interruptRequest = true;
-                            } else if (!"success".equalsIgnoreCase(returnString)) {
-                                throw new EventHandlerException("First-Visit event did not return 'success'.");
-                            }
-                        } catch (EventHandlerException e) {
-                            Debug.logError(e, module);
+                for (ConfigXMLReader.Event event: ctrl.getFirstVisitEventList().values()) {
+                    try {
+                        String returnString = this.runEvent(request, response, event, null, "firstvisit");
+                        if (returnString == null || "none".equalsIgnoreCase(returnString)) {
+                            interruptRequest = true;
+                        } else if (!"success".equalsIgnoreCase(returnString)) {
+                            throw new EventHandlerException("First-Visit event did not return 'success'.");
                         }
+                    } catch (EventHandlerException e) {
+                        Debug.logError(e, module);
                     }
-                } catch (WebAppConfigurationException e) {
-                    Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
-                    throw new RequestHandlerException(e);
                 }
             }
 
             // Invoke the pre-processor (but NOT in a chain)
-            try {
-                for (ConfigXMLReader.Event event: controllerConfig.getPreprocessorEventList().values()) {
-                    try {
-                        String returnString = this.runEvent(request, response, event, null, "preprocessor");
-                        if (returnString == null || "none".equalsIgnoreCase(returnString)) {
-                            interruptRequest = true;
-                        } else if (!"success".equalsIgnoreCase(returnString)) {
-                            if (!returnString.contains(":_protect_:")) {
-                                throw new EventHandlerException("Pre-Processor event [" + event.invoke + "] did not return 'success'.");
-                            } else { // protect the view normally rendered and redirect to error response view
-                                returnString = returnString.replace(":_protect_:", "");
-                                if (returnString.length() > 0) {
-                                    request.setAttribute("_ERROR_MESSAGE_", returnString);
-                                }
-                                eventReturn = null;
-                                // check to see if there is a "protect" response, if so it's ok else show the default_error_response_view
-                                if (!requestMap.requestResponseMap.containsKey("protect")) {
-                                    String protectView = controllerConfig.getProtectView();
-                                    if (protectView != null) {
-                                        overrideViewUri = protectView;
-                                    } else {
-                                        overrideViewUri = EntityUtilProperties.getPropertyValue("security", "default.error.response.view", delegator);
-                                        overrideViewUri = overrideViewUri.replace("view:", "");
-                                        if ("none:".equals(overrideViewUri)) {
-                                            interruptRequest = true;
-                                        }
+            for (ConfigXMLReader.Event event: ctrl.getPreprocessorEventList().values()) {
+                try {
+                    String returnString = this.runEvent(request, response, event, null, "preprocessor");
+                    if (returnString == null || "none".equalsIgnoreCase(returnString)) {
+                        interruptRequest = true;
+                    } else if (!"success".equalsIgnoreCase(returnString)) {
+                        if (!returnString.contains(":_protect_:")) {
+                            throw new EventHandlerException("Pre-Processor event [" + event.invoke + "] did not return 'success'.");
+                        } else { // protect the view normally rendered and redirect to error response view
+                            returnString = returnString.replace(":_protect_:", "");
+                            if (returnString.length() > 0) {
+                                request.setAttribute("_ERROR_MESSAGE_", returnString);
+                            }
+                            eventReturn = null;
+                            // check to see if there is a "protect" response, if so it's ok else show the default_error_response_view
+                            if (!requestMap.requestResponseMap.containsKey("protect")) {
+                                if (ctrl.getProtectView() != null) {
+                                    overrideViewUri = ctrl.getProtectView();
+                                } else {
+                                    overrideViewUri = EntityUtilProperties.getPropertyValue("security", "default.error.response.view", delegator);
+                                    overrideViewUri = overrideViewUri.replace("view:", "");
+                                    if ("none:".equals(overrideViewUri)) {
+                                        interruptRequest = true;
                                     }
                                 }
                             }
                         }
-                    } catch (EventHandlerException e) {
-                        Debug.logError(e, module);
                     }
+                } catch (EventHandlerException e) {
+                    Debug.logError(e, module);
                 }
-            } catch (WebAppConfigurationException e) {
-                Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
-                throw new RequestHandlerException(e);
             }
         }
 
@@ -420,8 +488,7 @@ public class RequestHandler {
             // Invoke the security handler
             // catch exceptions and throw RequestHandlerException if failed.
             if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler]: AuthRequired. Running security check. " + showSessionId(request), module);
-            ConfigXMLReader.Event checkLoginEvent =
-                    requestMapMap.getFirst("checkLogin").event;
+            ConfigXMLReader.Event checkLoginEvent = ctrl.getRequestMapMap().getFirst("checkLogin").event;
             String checkLoginReturnString = null;
 
             try {
@@ -434,9 +501,9 @@ public class RequestHandler {
                 eventReturn = checkLoginReturnString;
                 // if the request is an ajax request we don't want to return the default login check
                 if (!"XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
-                    requestMap = requestMapMap.getFirst("checkLogin");
+                    requestMap = ctrl.getRequestMapMap().getFirst("checkLogin");
                 } else {
-                    requestMap = requestMapMap.getFirst("ajaxCheckLogin");
+                    requestMap = ctrl.getRequestMapMap().getFirst("ajaxCheckLogin");
                 }
             }
         }
@@ -568,7 +635,7 @@ public class RequestHandler {
                     redirectTarget += "?" + queryString;
                 }
                 
-                callRedirect(makeLink(request, response, redirectTarget), response, request, statusCodeString);
+                callRedirect(makeLink(request, response, redirectTarget), response, request, ctrl.getStatusCodeString());
                 return;
             }
         }
@@ -615,41 +682,35 @@ public class RequestHandler {
             // ======== handle views ========
 
             // first invoke the post-processor events.
-            try {
-                for (ConfigXMLReader.Event event: controllerConfig.getPostprocessorEventList().values()) {
-                    try {
-                        String returnString = this.runEvent(request, response, event, requestMap, "postprocessor");
-                        if (returnString != null && !"success".equalsIgnoreCase(returnString)) {
-                            throw new EventHandlerException("Post-Processor event did not return 'success'.");
-                        }
-                    } catch (EventHandlerException e) {
-                        Debug.logError(e, module);
+            for (ConfigXMLReader.Event event: ctrl.getPostprocessorEventList().values()) {
+                try {
+                    String returnString = this.runEvent(request, response, event, requestMap, "postprocessor");
+                    if (returnString != null && !"success".equalsIgnoreCase(returnString)) {
+                        throw new EventHandlerException("Post-Processor event did not return 'success'.");
                     }
+                } catch (EventHandlerException e) {
+                    Debug.logError(e, module);
                 }
-            } catch (WebAppConfigurationException e) {
-                Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
-                throw new RequestHandlerException(e);
             }
 
             String responseStatusCode  = nextRequestResponse.statusCode;
             if(UtilValidate.isNotEmpty(responseStatusCode))
-                statusCodeString = responseStatusCode;            
-            
+                ctrl.setStatusCodeString(responseStatusCode);
             
             if ("url".equals(nextRequestResponse.type)) {
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a URL redirect." + showSessionId(request), module);
-                callRedirect(nextRequestResponse.value, response, request, statusCodeString);
+                callRedirect(nextRequestResponse.value, response, request, ctrl.getStatusCodeString());
             } else if ("cross-redirect".equals(nextRequestResponse.type)) {
                 // check for a cross-application redirect
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a Cross-Application redirect." + showSessionId(request), module);
                 String url = nextRequestResponse.value.startsWith("/") ? nextRequestResponse.value : "/" + nextRequestResponse.value;
-                callRedirect(url + this.makeQueryString(request, nextRequestResponse), response, request, statusCodeString);
+                callRedirect(url + this.makeQueryString(request, nextRequestResponse), response, request, ctrl.getStatusCodeString());
             } else if ("request-redirect".equals(nextRequestResponse.type)) {
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a Request redirect." + showSessionId(request), module);
-                callRedirect(makeLinkWithQueryString(request, response, "/" + nextRequestResponse.value, nextRequestResponse), response, request, statusCodeString);
+                callRedirect(makeLinkWithQueryString(request, response, "/" + nextRequestResponse.value, nextRequestResponse), response, request, ctrl.getStatusCodeString());
             } else if ("request-redirect-noparam".equals(nextRequestResponse.type)) {
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a Request redirect with no parameters." + showSessionId(request), module);
-                callRedirect(makeLink(request, response, nextRequestResponse.value), response, request, statusCodeString);
+                callRedirect(makeLink(request, response, nextRequestResponse.value), response, request, ctrl.getStatusCodeString());
             } else if ("view".equals(nextRequestResponse.type)) {
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a view." + showSessionId(request), module);
 

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java?rev=1834465&r1=1834464&r2=1834465&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java Wed Jun 27 05:48:59 2018
@@ -20,15 +20,22 @@ package org.apache.ofbiz.webapp.control;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.MultivaluedHashMap;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.ofbiz.webapp.control.ConfigXMLReader.RequestMap;
+import org.apache.ofbiz.webapp.control.ConfigXMLReader.ViewMap;
 import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Element;
@@ -36,12 +43,19 @@ import org.w3c.dom.Element;
 public class RequestHandlerTests {
     public static class ResolveURITests {
         private MultivaluedMap<String,RequestMap> reqMaps;
+        private Map<String, ViewMap> viewMaps;
         private HttpServletRequest req;
         private Element dummyElement;
+        private RequestHandler.Controller ctrl;
 
         @Before
         public void setUp() {
+            ctrl = mock(RequestHandler.Controller.class);
             reqMaps = new MultivaluedHashMap<>();
+            viewMaps = new HashMap<>();
+            when(ctrl.getDefaultRequest()).thenReturn(null);
+            when(ctrl.getRequestMapMap()).thenReturn(reqMaps);
+            when(ctrl.getViewMapMap()).thenReturn(viewMaps);
             req = mock(HttpServletRequest.class);
             dummyElement = mock(Element.class);
             when(dummyElement.getAttribute("method")).thenReturn("all");
@@ -55,7 +69,9 @@ public class RequestHandlerTests {
             reqMaps.putSingle("foo", foo);
             reqMaps.putSingle("bar", bar);
             when(req.getPathInfo()).thenReturn("/foo");
-            assertSame(foo, RequestHandler.resolveURI(reqMaps, req, null).get());
+            assertThat(RequestHandler.resolveURI(ctrl, req),
+                    both(hasItem(foo)).and(not(hasItem(bar))));
+            assertThat(RequestHandler.resolveURI(ctrl, req).size(), is(1));
         }
 
         @Test
@@ -66,9 +82,9 @@ public class RequestHandlerTests {
 
             RequestMap foo = new RequestMap(dummyElement);
 
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
+            assertTrue(RequestHandler.resolveURI(ctrl, req).isEmpty());
             reqMaps.putSingle("foo", foo);
-            assertTrue(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
+            assertFalse(RequestHandler.resolveURI(ctrl, req).isEmpty());
         }
 
         @Test
@@ -82,63 +98,38 @@ public class RequestHandlerTests {
 
             when(req.getPathInfo()).thenReturn("/foo");
             when(req.getMethod()).thenReturn("GET");
-            assertSame(foo, RequestHandler.resolveURI(reqMaps, req, null).get());
+            assertThat(RequestHandler.resolveURI(ctrl, req), hasItem(foo));
 
             when(req.getPathInfo()).thenReturn("/bar");
             when(req.getMethod()).thenReturn("PUT");
-            assertSame(bar, RequestHandler.resolveURI(reqMaps, req, null).get());
+            assertThat(RequestHandler.resolveURI(ctrl, req), hasItem(bar));
         }
 
+
         @Test
-        public void resolveURICatchAll() throws RequestHandlerException {
-            when(req.getPathInfo()).thenReturn("/foo");
+        public void resolveURIDefault() throws Exception {
             RequestMap foo = new RequestMap(dummyElement);
-            when(req.getMethod()).thenReturn("get");
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("post");
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("put");
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("delete");
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-
+            RequestMap bar = new RequestMap(dummyElement);
             reqMaps.putSingle("foo", foo);
-            when(req.getMethod()).thenReturn("get");
-            assertTrue(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("post");
-            assertTrue(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("put");
-            assertTrue(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-            when(req.getMethod()).thenReturn("delete");
-            assertTrue(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
-        }
-
-        @Test
-        public void resolveURISegregate() throws RequestHandlerException {
-            when(dummyElement.getAttribute("method")).thenReturn("put");
-            RequestMap fooPut = new RequestMap(dummyElement);
-            when(dummyElement.getAttribute("method")).thenReturn("all");
-            RequestMap fooAll = new RequestMap(dummyElement);
-            reqMaps.putSingle("foo", fooAll);
-            reqMaps.add("foo", fooPut);
+            reqMaps.putSingle("bar", bar);
 
-            when(req.getPathInfo()).thenReturn("/foo");
-            when(req.getMethod()).thenReturn("put");
-            assertSame(fooPut, RequestHandler.resolveURI(reqMaps, req, null).get());
-            when(req.getMethod()).thenReturn("get");
-            assertSame(fooAll, RequestHandler.resolveURI(reqMaps, req, null).get());
+            when(req.getPathInfo()).thenReturn("/baz");
+            when(ctrl.getDefaultRequest()).thenReturn("bar");
+            assertThat(RequestHandler.resolveURI(ctrl, req), hasItem(bar));
         }
 
         @Test
-        public void resolveURIDefault() throws Exception {
+        public void resolveURIOverrideView() throws Exception {
             RequestMap foo = new RequestMap(dummyElement);
             RequestMap bar = new RequestMap(dummyElement);
             reqMaps.putSingle("foo", foo);
             reqMaps.putSingle("bar", bar);
 
-            when(req.getPathInfo()).thenReturn("/bar");
-            when(req.getMethod()).thenReturn("get");
-            assertSame(bar, RequestHandler.resolveURI(reqMaps, req, "bar").get());
+            viewMaps.put("baz", new ViewMap(dummyElement));
+
+            when(req.getPathInfo()).thenReturn("/foo/baz");
+            when(ctrl.getDefaultRequest()).thenReturn("bar");
+            assertThat(RequestHandler.resolveURI(ctrl, req), hasItem(bar));
         }
 
         @Test
@@ -149,8 +140,41 @@ public class RequestHandlerTests {
             reqMaps.putSingle("bar", bar);
 
             when(req.getPathInfo()).thenReturn("/baz");
-            when(req.getMethod()).thenReturn("get");
-            assertFalse(RequestHandler.resolveURI(reqMaps, req, null).isPresent());
+            assertTrue(RequestHandler.resolveURI(ctrl, req).isEmpty());
+        }
+
+        @Test
+        public void resolveMethodCatchAll() throws RequestHandlerException {
+            when(req.getPathInfo()).thenReturn("/foo");
+            RequestMap foo = new RequestMap(dummyElement);
+            Collection<RequestMap> rmaps = RequestHandler.resolveURI(ctrl, req);
+            assertFalse(RequestHandler.resolveMethod("get", rmaps).isPresent());
+            assertFalse(RequestHandler.resolveMethod("post", rmaps).isPresent());
+            assertFalse(RequestHandler.resolveMethod("put", rmaps).isPresent());
+            assertFalse(RequestHandler.resolveMethod("delete", rmaps).isPresent());
+
+            reqMaps.putSingle("foo", foo);
+            Collection<RequestMap> rmaps2 = RequestHandler.resolveURI(ctrl, req);
+            assertTrue(RequestHandler.resolveMethod("get", rmaps2).isPresent());
+            assertTrue(RequestHandler.resolveMethod("post", rmaps2).isPresent());
+            assertTrue(RequestHandler.resolveMethod("put", rmaps2).isPresent());
+            assertTrue(RequestHandler.resolveMethod("delete", rmaps2).isPresent());
+        }
+
+        @Test
+        public void resolveMethodBasic() throws RequestHandlerException {
+            when(dummyElement.getAttribute("method")).thenReturn("put");
+            RequestMap fooPut = new RequestMap(dummyElement);
+            when(dummyElement.getAttribute("method")).thenReturn("all");
+            RequestMap fooAll = new RequestMap(dummyElement);
+            reqMaps.putSingle("foo", fooAll);
+            reqMaps.add("foo", fooPut);
+
+            when(req.getPathInfo()).thenReturn("/foo");
+            Collection<RequestMap> rmaps = RequestHandler.resolveURI(ctrl, req);
+            assertThat(rmaps, hasItems(fooPut, fooAll));
+            assertThat(RequestHandler.resolveMethod("put", rmaps).get(), is(fooPut));
+            assertThat(RequestHandler.resolveMethod("get", rmaps).get(), is(fooAll));
         }
     }
 }