svn commit: r1834917 - in /ofbiz/ofbiz-framework/trunk/framework: base/src/main/java/org/apache/ofbiz/base/util/collections/ webapp/config/ webapp/src/main/java/org/apache/ofbiz/webapp/control/ webapp/src/test/java/org/apache/ofbiz/webapp/control/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1834917 - in /ofbiz/ofbiz-framework/trunk/framework: base/src/main/java/org/apache/ofbiz/base/util/collections/ webapp/config/ webapp/src/main/java/org/apache/ofbiz/webapp/control/ webapp/src/test/java/org/apache/ofbiz/webapp/control/

shijh
Author: shijh
Date: Tue Jul  3 06:21:02 2018
New Revision: 1834917

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

Removed:
    ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/util/collections/MultiValuedMapContext.java
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/MethodNotAllowedException.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
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java
    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

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=1834917&r1=1834916&r2=1834917&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/config/WebappUiLabels.xml Tue Jul  3 06:21:02 2018
@@ -339,8 +339,4 @@
         <value xml:lang="zh">没有完成事件</value>
         <value xml:lang="zh-TW">沒有完成事件</value>
     </property>
-    <property key="RequestMethodNotMatchConfig">
-        <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/ConfigXMLReader.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java?rev=1834917&r1=1834916&r2=1834917&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java Tue Jul  3 06:21:02 2018
@@ -23,21 +23,16 @@ import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 
 import javax.servlet.ServletContext;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.ofbiz.base.component.ComponentConfig.WebappInfo;
 import org.apache.ofbiz.base.location.FlexibleLocation;
@@ -54,7 +49,6 @@ import org.apache.ofbiz.base.util.UtilVa
 import org.apache.ofbiz.base.util.UtilXml;
 import org.apache.ofbiz.base.util.cache.UtilCache;
 import org.apache.ofbiz.base.util.collections.MapContext;
-import org.apache.ofbiz.base.util.collections.MultiValuedMapContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -198,7 +192,7 @@ public class ConfigXMLReader {
         private Map<String, Event> beforeLogoutEventList = new LinkedHashMap<String, Event>();
         private Map<String, String> eventHandlerMap = new HashMap<String, String>();
         private Map<String, String> viewHandlerMap = new HashMap<String, String>();
-        private MultivaluedMap<String, RequestMap> requestMapMap = new MultivaluedHashMap<>();
+        private Map<String, RequestMap> requestMapMap = new HashMap<String, RequestMap>();
         private Map<String, ViewMap> viewMapMap = new HashMap<String, ViewMap>();
 
         public ControllerConfig(URL url) throws WebAppConfigurationException {
@@ -282,57 +276,11 @@ public class ConfigXMLReader {
             return getIncludes(ccfg -> ccfg.protectView);
         }
 
-        // XXX: Temporary wrapper to handle conversion from Map to MultiMap.
         public Map<String, RequestMap> getRequestMapMap() throws WebAppConfigurationException {
-            return new Map<String, RequestMap> () {
-                private MultivaluedMap<String, RequestMap> deleg = getRequestMapMultiMap();
-                @Override public int size() { return deleg.size(); }
-                @Override public boolean isEmpty() { return deleg.isEmpty(); }
-                @Override public boolean containsKey(Object key) {
-                    return deleg.containsKey(key);
-                }
-                @Override public boolean containsValue(Object value) {
-                    return deleg.containsValue(value);
-                }
-                @Override public RequestMap get(Object key) {
-                    return deleg.getFirst((String) key);
-                }
-                @Override public RequestMap put(String key, RequestMap value) {
-                    RequestMap res = get(key);
-                    deleg.putSingle(key, value);
-                    return res;
-                }
-                @Override public RequestMap remove(Object key) {
-                    RequestMap res = get(key);
-                    deleg.remove(key);
-                    return res;
-                }
-                @Override public void putAll(Map<? extends String, ? extends RequestMap> m) {
-                    m.forEach(deleg::add);
-                }
-                @Override public void clear() { deleg.clear(); }
-                @Override public Set<String> keySet() { return deleg.keySet(); }
-                @Override public Collection<RequestMap> values() {
-                    return deleg.values()
-                                .stream()
-                                .map(m -> m.stream().findFirst().orElse(null))
-                                .filter(Objects::nonNull)
-                                .collect(Collectors.toList());
-                }
-                @Override public Set<Entry<String, RequestMap>> entrySet() {
-                    return deleg.keySet()
-                                .stream()
-                                .collect(Collectors.toMap(k -> k, k -> get(k)))
-                                .entrySet();
-                }
-            };
-        }
-
-        public MultivaluedMap<String, RequestMap> getRequestMapMultiMap() throws WebAppConfigurationException {
-            MultiValuedMapContext<String, RequestMap> result = MultiValuedMapContext.getMapContext();
+            MapContext<String, RequestMap> result = MapContext.getMapContext();
             for (URL includeLocation : includes) {
                 ControllerConfig controllerConfig = getControllerConfig(includeLocation);
-                result.push(controllerConfig.getRequestMapMultiMap());
+                result.push(controllerConfig.getRequestMapMap());
             }
             result.push(requestMapMap);
             return result;
@@ -455,7 +403,7 @@ public class ConfigXMLReader {
         private void loadRequestMap(Element root) {
             for (Element requestMapElement : UtilXml.childElementList(root, "request-map")) {
                 RequestMap requestMap = new RequestMap(requestMapElement);
-                this.requestMapMap.putSingle(requestMap.uri, requestMap);
+                this.requestMapMap.put(requestMap.uri, requestMap);
             }
         }
 
@@ -502,7 +450,6 @@ public class ConfigXMLReader {
 
     public static class RequestMap {
         public String uri;
-        public String method;
         public boolean edit = true;
         public boolean trackVisit = true;
         public boolean trackServerHit = true;
@@ -519,7 +466,6 @@ public class ConfigXMLReader {
         public RequestMap(Element requestMapElement) {
             // Get the URI info
             this.uri = requestMapElement.getAttribute("uri");
-            this.method = requestMapElement.getAttribute("method");
             this.edit = !"false".equals(requestMapElement.getAttribute("edit"));
             this.trackServerHit = !"false".equals(requestMapElement.getAttribute("track-serverhit"));
             this.trackVisit = !"false".equals(requestMapElement.getAttribute("track-visit"));

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=1834917&r1=1834916&r2=1834917&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 Tue Jul  3 06:21:02 2018
@@ -80,20 +80,18 @@ public class ControlServlet extends Http
     }
 
     /**
-     * @see javax.servlet.http.HttpServlet#doPost
+     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
      */
     @Override
-    protected void doPost(HttpServletRequest request, HttpServletResponse response)
-            throws ServletException, IOException {
+    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         doGet(request, response);
     }
 
     /**
-     * @see javax.servlet.http.HttpServlet#doGet
+     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
      */
     @Override
-    protected void doGet(HttpServletRequest request, HttpServletResponse response)
-            throws ServletException, IOException {
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         long requestStartTime = System.currentTimeMillis();
         RequestHandler requestHandler = this.getRequestHandler();
         HttpSession session = request.getSession();
@@ -213,12 +211,6 @@ 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) {

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=1834917&r1=1834916&r2=1834917&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 Tue Jul  3 06:21:02 2018
@@ -24,21 +24,16 @@ 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;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Optional;
 
 import javax.servlet.ServletContext;
 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.SSLUtil;
@@ -56,7 +51,6 @@ import org.apache.ofbiz.entity.GenericVa
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.webapp.OfbizUrlBuilder;
-import org.apache.ofbiz.webapp.control.ConfigXMLReader.RequestMap;
 import org.apache.ofbiz.webapp.event.EventFactory;
 import org.apache.ofbiz.webapp.event.EventHandler;
 import org.apache.ofbiz.webapp.event.EventHandlerException;
@@ -74,77 +68,12 @@ import org.apache.ofbiz.widget.model.The
 public class RequestHandler {
 
     public static final String module = RequestHandler.class.getName();
-    private final static String defaultStatusCodeString =
-            UtilProperties.getPropertyValue("requestHandler", "status-code", "302");
+    private final 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_");
@@ -181,59 +110,6 @@ public class RequestHandler {
         return null;
     }
 
-    /**
-     * Find a collection of request maps in {@code ctrl} matching {@code req}.
-     * Otherwise fall back to matching the {@code defaultReq} field.
-     *
-     * @param ctrl The controller containing the current configuration
-     * @param req The HTTP request to match
-     * @return a collection of request maps which might be empty
-     */
-    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 {
         HttpSession session = request.getSession();
         Delegator delegator = (Delegator) request.getAttribute("delegator");
@@ -249,13 +125,20 @@ public class RequestHandler {
         long startTime = System.currentTimeMillis();
         HttpSession session = request.getSession();
 
-        // Parse controller config.
+        // 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();
+        Map<String, ConfigXMLReader.RequestMap> requestMapMap = null;
+        String statusCodeString = null;
         try {
-            ctrl = new Controller(getControllerConfig());
+            requestMapMap = controllerConfig.getRequestMapMap();
+            statusCodeString = controllerConfig.getStatusCode();
         } 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);
@@ -270,32 +153,50 @@ public class RequestHandler {
             }
         }
 
-        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();
+        String overrideViewUri = RequestHandler.getOverrideViewUri(request.getPathInfo());
+
+        String requestMissingErrorMessage = "Unknown request [" + defaultRequestUri + "]; this request does not exist or cannot be called directly.";
+        ConfigXMLReader.RequestMap requestMap = null;
+        if (defaultRequestUri != null) {
+            requestMap = requestMapMap.get(defaultRequestUri);
+        }
+        // check for default request
+        if (requestMap == null) {
+            String defaultRequest;
+            try {
+                defaultRequest = controllerConfig.getDefaultRequest();
+            } catch (WebAppConfigurationException e) {
+                Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
+                throw new RequestHandlerException(e);
+            }
+            if (defaultRequest != null) { // required! to avoid a null pointer exception and generate a requesthandler exception if default request not found.
+                requestMap = requestMapMap.get(defaultRequest);
             }
         }
 
-        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);
-                });
+        // check for override view
+        if (overrideViewUri != null) {
+            ConfigXMLReader.ViewMap viewMap;
+            try {
+                viewMap = getControllerConfig().getViewMapMap().get(overrideViewUri);
+                if (viewMap == null) {
+                    String defaultRequest = controllerConfig.getDefaultRequest();
+                    if (defaultRequest != null) { // required! to avoid a null pointer exception and generate a requesthandler exception if default request not found.
+                        requestMap = requestMapMap.get(defaultRequest);
+                    }
+                }
+            } catch (WebAppConfigurationException e) {
+                Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
+                throw new RequestHandlerException(e);
+            }
+        }
+
+        // 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 eventReturn = null;
         if (requestMap.metrics != null && requestMap.metrics.getThreshold() != 0.0 && requestMap.metrics.getTotalEvents() > 3 && requestMap.metrics.getThreshold() < requestMap.metrics.getServiceRate()) {
@@ -303,11 +204,13 @@ public class RequestHandler {
         }
         ConfigXMLReader.RequestMap originalRequestMap = requestMap; // Save this so we can update the correct performance metrics.
 
+
         boolean interruptRequest = false;
+
         // Check for chained request.
         if (chain != null) {
             String chainRequestUri = RequestHandler.getRequestUri(chain);
-            requestMap = ctrl.getRequestMapMap().getFirst(chainRequestUri);
+            requestMap = requestMapMap.get(chainRequestUri);
             if (requestMap == null) {
                 throw new RequestHandlerException("Unknown chained request [" + chainRequestUri + "]; this request does not exist");
             }
@@ -331,11 +234,18 @@ 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 (ctrl.getDefaultRequest() == null || !ctrl.getRequestMapMap().getFirst(ctrl.getDefaultRequest()).securityDirectRequest) {
+                String defaultRequest;
+                try {
+                    defaultRequest = controllerConfig.getDefaultRequest();
+                } catch (WebAppConfigurationException e) {
+                    Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
+                    throw new RequestHandlerException(e);
+                }
+                if (defaultRequest == null || !requestMapMap.get(defaultRequest).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 = ctrl.getRequestMapMap().getFirst(ctrl.getDefaultRequest());
+                    requestMap = requestMapMap.get(defaultRequest);
                 }
             }
             // Check if we SHOULD be secure and are not.
@@ -378,7 +288,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, ctrl.getStatusCodeString());
+                        callRedirect(newUrl, response, request, statusCodeString);
                         return;
                     }
                 }
@@ -423,52 +333,63 @@ 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");
-                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'.");
+                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);
                         }
-                    } 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)
-            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;
+            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;
+                                        }
                                     }
                                 }
                             }
                         }
+                    } 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);
             }
         }
 
@@ -488,7 +409,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 = ctrl.getRequestMapMap().getFirst("checkLogin").event;
+            ConfigXMLReader.Event checkLoginEvent = requestMapMap.get("checkLogin").event;
             String checkLoginReturnString = null;
 
             try {
@@ -501,9 +422,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 = ctrl.getRequestMapMap().getFirst("checkLogin");
+                    requestMap = requestMapMap.get("checkLogin");
                 } else {
-                    requestMap = ctrl.getRequestMapMap().getFirst("ajaxCheckLogin");
+                    requestMap = requestMapMap.get("ajaxCheckLogin");
                 }
             }
         }
@@ -635,7 +556,7 @@ public class RequestHandler {
                     redirectTarget += "?" + queryString;
                 }
                 
-                callRedirect(makeLink(request, response, redirectTarget), response, request, ctrl.getStatusCodeString());
+                callRedirect(makeLink(request, response, redirectTarget), response, request, statusCodeString);
                 return;
             }
         }
@@ -682,35 +603,41 @@ public class RequestHandler {
             // ======== handle views ========
 
             // first invoke the post-processor events.
-            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'.");
+            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);
                     }
-                } 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))
-                ctrl.setStatusCodeString(responseStatusCode);
+                statusCodeString = 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, ctrl.getStatusCodeString());
+                callRedirect(nextRequestResponse.value, response, request, statusCodeString);
             } 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, ctrl.getStatusCodeString());
+                callRedirect(url + this.makeQueryString(request, nextRequestResponse), response, request, statusCodeString);
             } 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, ctrl.getStatusCodeString());
+                callRedirect(makeLinkWithQueryString(request, response, "/" + nextRequestResponse.value, nextRequestResponse), response, request, statusCodeString);
             } 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, ctrl.getStatusCodeString());
+                callRedirect(makeLink(request, response, nextRequestResponse.value), response, request, statusCodeString);
             } else if ("view".equals(nextRequestResponse.type)) {
                 if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler.doRequest]: Response is a view." + showSessionId(request), module);