Package org.ofbiz.webapp.control

Source Code of org.ofbiz.webapp.control.RequestHandler

/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.ofbiz.webapp.control;

import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.security.cert.X509Certificate;
import java.security.KeyStore;
import java.security.GeneralSecurityException;
import java.security.KeyStoreException;
import java.net.URL;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import javolution.util.FastMap;

import org.ofbiz.base.util.*;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.webapp.event.EventFactory;
import org.ofbiz.webapp.event.EventHandler;
import org.ofbiz.webapp.event.EventHandlerException;
import org.ofbiz.webapp.stats.ServerHitBin;
import org.ofbiz.webapp.stats.VisitHandler;
import org.ofbiz.webapp.view.ViewFactory;
import org.ofbiz.webapp.view.ViewHandler;
import org.ofbiz.webapp.view.ViewHandlerException;
import org.ofbiz.webapp.website.WebSiteWorker;

/**
* RequestHandler - Request Processor Object
*/
public class RequestHandler implements Serializable {

    public static final String module = RequestHandler.class.getName();
    public static final String err_resource = "WebappUiLabels";

    public static RequestHandler getRequestHandler(ServletContext servletContext) {
        RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_");
        if (rh == null) {
            rh = new RequestHandler();
            servletContext.setAttribute("_REQUEST_HANDLER_", rh);
            rh.init(servletContext);           
        }
        return rh;
    }

    private ServletContext context = null;
    private RequestManager requestManager = null;
    private ViewFactory viewFactory = null;
    private EventFactory eventFactory = null;

    public void init(ServletContext context) {
        Debug.logInfo("[RequestHandler Loading...]", module);
        this.context = context;
        this.requestManager = new RequestManager(context);
        this.viewFactory = new ViewFactory(this);
        this.eventFactory = new EventFactory(this);
    }

    public void doRequest(HttpServletRequest request, HttpServletResponse response, String chain,
            GenericValue userLogin, GenericDelegator delegator) throws RequestHandlerException {

        HttpSession session = request.getSession();
        String eventType;
        String eventPath;
        String eventMethod;

        // workaraound if we are in the root webapp
        String cname = UtilHttp.getApplicationName(request);

        // Grab data from request object to process
        String requestUri = RequestHandler.getRequestUri(request.getPathInfo());
        String nextView = RequestHandler.getNextPageUri(request.getPathInfo());
        if (request.getAttribute("targetRequestUri") == null) {
            if (request.getSession().getAttribute("_PREVIOUS_REQUEST_") != null) {
                request.setAttribute("targetRequestUri", request.getSession().getAttribute("_PREVIOUS_REQUEST_"));
            } else {
                request.setAttribute("targetRequestUri", "/" + requestUri);
            }
        }

        // Check for chained request.
        if (chain != null) {
            requestUri = RequestHandler.getRequestUri(chain);
            if (request.getAttribute("_POST_CHAIN_VIEW_") != null) {
                nextView = (String) request.getAttribute("_POST_CHAIN_VIEW_");
            } else {
                nextView = RequestHandler.getNextPageUri(chain);
            }
            if (Debug.infoOn()) Debug.logInfo("[RequestHandler]: Chain in place: requestUri=" + requestUri + " nextView=" + nextView + " sessionId=" + UtilHttp.getSessionId(request), module);
        } else {
            // 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 an process
            if (!requestManager.allowDirectRequest(requestUri)) {
                if (!requestManager.allowDirectRequest(requestManager.getDefaultRequest())) {
                    throw new RequestHandlerException("Unknown request [" + requestUri + "]; this request does not exist or cannot be called directly.");
                } else {
                    requestUri = requestManager.getDefaultRequest();
                }
            }

            // Check if we SHOULD be secure and are not. If we are posting let it pass to not lose data. (too late now anyway)
            if (!request.isSecure() && requestManager.requiresHttps(requestUri) && !request.getMethod().equalsIgnoreCase("POST")) {
                StringBuffer urlBuf = new StringBuffer();
                urlBuf.append(request.getPathInfo());
                if (request.getQueryString() != null) {
                    urlBuf.append("?").append(request.getQueryString());
                }
                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);
                }
            }

            // Check if X509 is required and we are not secure; throw exception
            if (!request.isSecure() && requestManager.requiresHttpsClientCert(requestUri)) {
                throw new RequestHandlerException("Unknown request [" + requestUri + "]; this request does not exist or cannot be called directly.");
            }           

            // Check for HTTPS client (x.509) security
            if (request.isSecure() && requestManager.requiresHttpsClientCert(requestUri)) {           
                X509Certificate[] clientCerts = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); // 2.2 spec
                if (clientCerts == null) {
                    clientCerts = (X509Certificate[]) request.getAttribute("javax.net.ssl.peer_certificates"); // 2.1 spec
                }
                if (clientCerts == null) {
                    Debug.logWarning("Received no client certificates from browser", module);
                }

                // check if the client has a valid certificate (in our db store)
                boolean foundTrustedCert = false;

                if (clientCerts == null) {
                    throw new RequestHandlerException("Unknown request [" + requestUri + "]; this request does not exist or cannot be called directly.");
                } else {
                    for (int i = 0; i < clientCerts.length; i++) {
                        Debug.log(clientCerts[i].getSubjectX500Principal().getName(), module);
                    }
                  
                    // check if this is a trusted cert
                    if (SSLUtil.isClientTrusted(clientCerts, null)) {
                        foundTrustedCert = true;
                    }
                }

                if (!foundTrustedCert) {
                    Debug.logWarning("No trusted certificate found for request [" + requestUri + "]", module);
                    throw new RequestHandlerException("Unknown request [" + requestUri + "]; this request does not exist or cannot be called directly.");
                }
            }

            // If its the first visit run the first visit events.
            if (session.getAttribute("visit") == null) {
                Debug.logInfo("This is the first request in this visit." + " sessionId=" + UtilHttp.getSessionId(request), module);
                // This isn't an event because it is required to run. We do not want to make it optional.
                VisitHandler.setInitialVisit(request, response);
                Collection events = requestManager.getFirstVisitEvents();

                if (events != null) {
                    Iterator i = events.iterator();

                    while (i.hasNext()) {
                        Map eventMap = (Map) i.next();
                        String eType = (String) eventMap.get(ConfigXMLReader.EVENT_TYPE);
                        String ePath = (String) eventMap.get(ConfigXMLReader.EVENT_PATH);
                        String eMeth = (String) eventMap.get(ConfigXMLReader.EVENT_METHOD);

                        try {
                            String returnString = this.runEvent(request, response, eType, ePath, eMeth);
                            if (returnString != null && !returnString.equalsIgnoreCase("success")) {
                                throw new EventHandlerException("First-Visit event did not return 'success'.");
                            } else if (returnString == null) {
                                nextView = "none:";
                            }
                        } catch (EventHandlerException e) {
                            Debug.logError(e, module);
                        }
                    }
                }
            }

            // Invoke the pre-processor (but NOT in a chain)
            Collection preProcEvents = requestManager.getPreProcessor();
            if (preProcEvents != null) {
                Iterator i = preProcEvents.iterator();

                while (i.hasNext()) {
                    Map eventMap = (Map) i.next();
                    String eType = (String) eventMap.get(ConfigXMLReader.EVENT_TYPE);
                    String ePath = (String) eventMap.get(ConfigXMLReader.EVENT_PATH);
                    String eMeth = (String) eventMap.get(ConfigXMLReader.EVENT_METHOD);
                    try {
                        String returnString = this.runEvent(request, response, eType, ePath, eMeth);
                        if (returnString != null && !returnString.equalsIgnoreCase("success")) {
                            throw new EventHandlerException("Pre-Processor event did not return 'success'.");
                        } else if (returnString == null) {
                            nextView = "none:";
                        }
                    } catch (EventHandlerException e) {
                        Debug.logError(e, module);
                    }
                }
            }
        }

        // Pre-Processor/First-Visit event(s) can interrupt the flow by returning null.
        // Warning: this could cause problems if more then one event attempts to return a response.
        if ("none:".equals(nextView)) {
            if (Debug.infoOn()) Debug.logInfo("[Pre-Processor Interrupted Request, not running: " + requestUri + " sessionId=" + UtilHttp.getSessionId(request), module);
            return;
        }

        if (Debug.infoOn()) Debug.logInfo("[Processing Request]: " + requestUri + " sessionId=" + UtilHttp.getSessionId(request), module);
        request.setAttribute("thisRequestUri", requestUri); // store the actual request URI
       
        String eventReturnString = null;

        // Perform security check.
        if (requestManager.requiresAuth(requestUri)) {
            // Invoke the security handler
            // catch exceptions and throw RequestHandlerException if failed.
            Debug.logVerbose("[RequestHandler]: AuthRequired. Running security check." + " sessionId=" + UtilHttp.getSessionId(request), module);
            String checkLoginType = requestManager.getEventType("checkLogin");
            String checkLoginPath = requestManager.getEventPath("checkLogin");
            String checkLoginMethod = requestManager.getEventMethod("checkLogin");
            String checkLoginReturnString;

            try {
                checkLoginReturnString = this.runEvent(request, response, checkLoginType,
                        checkLoginPath, checkLoginMethod);
            } catch (EventHandlerException e) {
                throw new RequestHandlerException(e.getMessage(), e);
            }
            if (!"success".equalsIgnoreCase(checkLoginReturnString)) {
                // previous URL already saved by event, so just do as the return says...
                eventReturnString = checkLoginReturnString;
                requestUri = "checkLogin";                           
            }
        }

        // Invoke the defined event (unless login failed)
        if (eventReturnString == null) {
            eventType = requestManager.getEventType(requestUri);
            eventPath = requestManager.getEventPath(requestUri);
            eventMethod = requestManager.getEventMethod(requestUri);
            if (eventType != null && eventPath != null && eventMethod != null) {
                try {
                    long eventStartTime = System.currentTimeMillis();

                    // run the event
                    eventReturnString = this.runEvent(request, response, eventType, eventPath, eventMethod);

                    // save the server hit
                    ServerHitBin.countEvent(cname + "." + eventMethod, request, eventStartTime,
                            System.currentTimeMillis() - eventStartTime, userLogin, delegator);

                    // set the default event return
                    if (eventReturnString == null) {
                        nextView = "none:";
                    }
                } catch (EventHandlerException e) {
                    // check to see if there is an "error" response, if so go there and make an request error message
                    String tryErrorMsg = requestManager.getRequestAttribute(requestUri, "error");

                    if (tryErrorMsg != null) {
                        eventReturnString = "error";
                        Locale locale = UtilHttp.getLocale(request);
                        String errMsg = UtilProperties.getMessage(RequestHandler.err_resource, "requestHandler.error_call_event", locale);
                        request.setAttribute("_ERROR_MESSAGE_", errMsg + ": " + e.toString());
                    } else {
                        throw new RequestHandlerException("Error calling event and no error repsonse was specified", e);
                    }
                }
            }
        }

         // If error, then display more error messages:
         if ("error".equals(eventReturnString)) {
             if (Debug.errorOn()) {
                 String errorMessageHeader = "Request " + requestUri + " caused an error with the following message: ";
                 if (request.getAttribute("_ERROR_MESSAGE_") != null) {
                     Debug.logError(errorMessageHeader + request.getAttribute("_ERROR_MESSAGE_"), module);
                 }
                 if (request.getAttribute("_ERROR_MESSAGE_LIST_") != null) {
                     Debug.logError(errorMessageHeader + request.getAttribute("_ERROR_MESSAGE_LIST_"), module);
                 }
             }
         }

        // Process the eventReturn.
        String eventReturn = requestManager.getRequestAttribute(requestUri, eventReturnString);
        if (Debug.verboseOn()) Debug.logVerbose("[Response Qualified]: " + eventReturn + " sessionId=" + UtilHttp.getSessionId(request), module);

        // Set the next view (don't use event return if success, default to nextView (which is set to eventReturn later if null); also even if success if it is a type "none" response ignore the nextView, ie use the eventReturn)
        if (eventReturn != null && (!"success".equals(eventReturnString) || eventReturn.startsWith("none:"))) nextView = eventReturn;
        if (Debug.verboseOn()) Debug.logVerbose("[Event Response Mapping]: " + nextView + " sessionId=" + UtilHttp.getSessionId(request), module);

        // get the previous request info
        String previousRequest = (String) request.getSession().getAttribute("_PREVIOUS_REQUEST_");
        String loginPass = (String) request.getAttribute("_LOGIN_PASSED_");

        // restore previous redirected request's attribute, so redirected page can display previous request's error msg etc.
        String preReqAttStr = (String) request.getSession().getAttribute("_REQ_ATTR_MAP_");
        if (preReqAttStr != null) {
            request.getSession().removeAttribute("_REQ_ATTR_MAP_");
            byte[] reqAttrMapBytes = StringUtil.fromHexString(preReqAttStr);
            Map preRequestMap = (Map) UtilObject.getObject(reqAttrMapBytes);
            if (preRequestMap != null && preRequestMap.size() > 0) {
                Iterator keys = preRequestMap.keySet().iterator();
                while (keys.hasNext()){
                    String key = (String) keys.next();
                    if("_ERROR_MESSAGE_LIST_".equals(key) || "_ERROR_MESSAGE_MAP_".equals(key) || "_ERROR_MESSAGE_".equals(key) ||
                            "_EVENT_MESSAGE_LIST_".equals(key) || "_EVENT_MESSAGE_".equals(key)) {
                        Object value = preRequestMap.get(key);
                        request.setAttribute(key, value);
                   }
                }
            }
        }

        if (Debug.verboseOn()) Debug.logVerbose("[RequestHandler]: previousRequest - " + previousRequest + " (" + loginPass + ")" + " sessionId=" + UtilHttp.getSessionId(request), module);

        // if previous request exists, and a login just succeeded, do that now.
        if (previousRequest != null && loginPass != null && loginPass.equalsIgnoreCase("TRUE")) {
            request.getSession().removeAttribute("_PREVIOUS_REQUEST_");
            // special case to avoid login/logout looping: if request was "logout" before the login, change to null for default success view; do the same for "login" to avoid going back to the same page
            if ("logout".equals(previousRequest) || "/logout".equals(previousRequest) || "login".equals(previousRequest) || "/login".equals(previousRequest) || "checkLogin".equals(previousRequest) || "/checkLogin".equals(previousRequest) || "/checkLogin/login".equals(previousRequest)) {
                Debug.logWarning("Found special _PREVIOUS_REQUEST_ of [" + previousRequest + "], setting to null to avoid problems, not running request again", module);
                previousRequest = null;
            } else {
                if (Debug.infoOn()) Debug.logInfo("[Doing Previous Request]: " + previousRequest + " sessionId=" + UtilHttp.getSessionId(request), module);
                doRequest(request, response, previousRequest, userLogin, delegator);
                return; // this is needed or else we will run the view twice
            }
        }

        String successView = requestManager.getViewName(requestUri);
        if ("success".equals(eventReturnString) && successView.startsWith("request:")) {
            // chains will override any url defined views; but we will save the view for the very end
            if (nextView != null) {
                request.setAttribute("_POST_CHAIN_VIEW_", nextView);
            }
            nextView = successView;
        }

        // Make sure we have some sort of response to go to
        if (nextView == null) nextView = successView;
        if (Debug.verboseOn()) Debug.logVerbose("[Current View]: " + nextView + " sessionId=" + UtilHttp.getSessionId(request), module);

        // Handle the responses - chains/views
        if (nextView != null && nextView.startsWith("request:")) {
            // chained request
            Debug.logInfo("[RequestHandler.doRequest]: Response is a chained request." + " sessionId=" + UtilHttp.getSessionId(request), module);
            nextView = nextView.substring(8);
            doRequest(request, response, nextView, userLogin, delegator);
        } else { // handle views
            // first invoke the post-processor events.
            Collection postProcEvents = requestManager.getPostProcessor();
            if (chain == null && postProcEvents != null) { // don't run post-proc events on chained requests
                Iterator i = postProcEvents.iterator();

                while (i.hasNext()) {
                    Map eventMap = (Map) i.next();
                    String eType = (String) eventMap.get(ConfigXMLReader.EVENT_TYPE);
                    String ePath = (String) eventMap.get(ConfigXMLReader.EVENT_PATH);
                    String eMeth = (String) eventMap.get(ConfigXMLReader.EVENT_METHOD);
                    try {
                        String returnString = this.runEvent(request, response, eType, ePath, eMeth);
                        if (returnString != null && !returnString.equalsIgnoreCase("success"))
                            throw new EventHandlerException("Post-Processor event did not return 'success'.");
                        else if (returnString == null)
                            nextView = "none:";
                    } catch (EventHandlerException e) {
                        Debug.logError(e, module);
                    }
                }
            }

            if (nextView != null && nextView.startsWith("url:")) {
                // check for a url for redirection
                Debug.logInfo("[RequestHandler.doRequest]: Response is a URL redirect." + " sessionId=" + UtilHttp.getSessionId(request), module);
                nextView = nextView.substring(4);
                callRedirect(nextView, response, request);
            } else if (nextView != null && nextView.startsWith("cross-redirect:")) {
                // check for a cross-application redirect
                Debug.logInfo("[RequestHandler.doRequest]: Response is a Cross-Application redirect." + " sessionId=" + UtilHttp.getSessionId(request), module);
                nextView = nextView.substring(15);
                String url = nextView.startsWith("/") ? nextView : "/" + nextView;
                callRedirect(url + this.makeQueryString(request), response, request);
            } else if (nextView != null && nextView.startsWith("request-redirect:")) {
                // check for a Request redirect
                Debug.logInfo("[RequestHandler.doRequest]: Response is a Request redirect." + " sessionId=" + UtilHttp.getSessionId(request), module);
                nextView = nextView.substring(17);
                callRedirect(makeLinkWithQueryString(request, response, "/" + nextView), response, request);
            } else if (nextView != null && nextView.startsWith("request-redirect-noparam:")) {
                // check for a Request redirect
                Debug.logInfo("[RequestHandler.doRequest]: Response is a Request redirect with no parameters." + " sessionId=" + UtilHttp.getSessionId(request), module);
                nextView = nextView.substring(25);
                callRedirect(makeLink(request, response, nextView), response, request);
            } else if (nextView != null && nextView.startsWith("view:")) {
                // check for a View
                Debug.logInfo("[RequestHandler.doRequest]: Response is a view." + " sessionId=" + UtilHttp.getSessionId(request), module);
                nextView = nextView.substring(5);
                renderView(nextView, requestManager.allowExtView(requestUri), request, response);
            } else if (nextView != null && nextView.startsWith("none:")) {
                // check for a no dispatch return (meaning the return was processed by the event
                Debug.logInfo("[RequestHandler.doRequest]: Response is handled by the event." + " sessionId=" + UtilHttp.getSessionId(request), module);
            } else if (nextView != null) {
                // a page request
                Debug.logInfo("[RequestHandler.doRequest]: Response is a page [" + nextView + "]" + " sessionId=" + UtilHttp.getSessionId(request), module);
                renderView(nextView, requestManager.allowExtView(requestUri), request, response);
            } else {
                // unknown request
                throw new RequestHandlerException("Illegal response; handler could not process [" + eventReturnString + "].");
            }
        }
    }

    /** Find the event handler and invoke an event. */
    public String runEvent(HttpServletRequest request, HttpServletResponse response, String type,
            String path, String method) throws EventHandlerException {
        EventHandler eventHandler = eventFactory.getEventHandler(type);
        return eventHandler.invoke(path, method, request, response);
    }

    /** Returns the default error page for this request. */
    public String getDefaultErrorPage(HttpServletRequest request) {
        //String requestUri = RequestHandler.getRequestUri(request.getPathInfo());
        //return requestManager.getErrorPage(requestUri);
        return requestManager.getDefaultErrorPage();
    }

    public String makeQueryString(HttpServletRequest request) {
        Map paramMap = UtilHttp.getParameterMap(request);
        StringBuffer queryString = new StringBuffer();
        if (paramMap != null && paramMap.size() > 0) {
            queryString.append("?");
            Iterator i = paramMap.keySet().iterator();
            while (i.hasNext()) {
                String name = (String) i.next();
                Object value = paramMap.get(name);
                if (value instanceof String) {
                    if (queryString.length() > 1) {
                        queryString.append("&");
                    }
                    queryString.append(name);
                    queryString.append("=");
                    queryString.append(value);
                }
            }
        }
        return queryString.toString();
    }

    /** Returns the RequestManager Object. */
    public RequestManager getRequestManager() {
        return requestManager;
    }

    /** Returns the ServletContext Object. */
    public ServletContext getServletContext() {
        return context;
    }

    /** Returns the ViewFactory Object. */
    public ViewFactory getViewFactory() {
        return viewFactory;
    }

    /** Returns the EventFactory Object. */
    public EventFactory getEventFactory() {
        return eventFactory;
    }

    public static String getRequestUri(String path) {
        List pathInfo = StringUtil.split(path, "/");
        if (pathInfo == null || pathInfo.size() == 0) {
            Debug.logWarning("Got nothing when splitting URI: " + path, module);
            return null;
        }
        if (((String)pathInfo.get(0)).indexOf('?') > -1) {
            return ((String) pathInfo.get(0)).substring(0, ((String)pathInfo.get(0)).indexOf('?'));
        } else {
            return (String) pathInfo.get(0);
        }
    }

    public static String getNextPageUri(String path) {
        List pathInfo = StringUtil.split(path, "/");
        String nextPage = null;
        if (pathInfo == null) {
            return nextPage;
        }

        for (int i = 1; i < pathInfo.size(); i++) {
            String element = (String) pathInfo.get(i);
            if (element.indexOf('~') != 0) {
                if (element.indexOf('?') > -1) {
                    element = element.substring(0, element.indexOf('?'));
                }
                if (i == 1) {
                    nextPage = element;
                } else {
                    nextPage = (nextPage == null ? element : nextPage + "/" + element);
                }
            }
        }
        return nextPage;
    }

    private void callRedirect(String url, HttpServletResponse resp, HttpServletRequest req) throws RequestHandlerException {
        if (Debug.infoOn()) Debug.logInfo("[Sending redirect]: " + url + " sessionId=" + UtilHttp.getSessionId(req), module);
        // set the attributes in the session so we can access it.
        java.util.Enumeration attributeNameEnum = req.getAttributeNames();
        Map reqAttrMap = FastMap.newInstance();
        while (attributeNameEnum.hasMoreElements()) {
            String name = (String) attributeNameEnum.nextElement();
            Object obj = req.getAttribute(name);
            if (obj instanceof Serializable) {
                reqAttrMap.put(name, obj);
            }
        }
        if (reqAttrMap.size() > 0) {
            reqAttrMap.remove("_REQUEST_HANDLER_")// RequestHandler is not serializable and must be removed first.  See http://issues.apache.org/jira/browse/OFBIZ-750
            byte[] reqAttrMapBytes = UtilObject.getBytes(reqAttrMap);
            if (reqAttrMapBytes != null) {
                req.getSession().setAttribute("_REQ_ATTR_MAP_", StringUtil.toHexString(reqAttrMapBytes));
            }
        }

        // send the redirect
        try {
            resp.sendRedirect(url);
        } catch (IOException ioe) {
            throw new RequestHandlerException(ioe.getMessage(), ioe);
        } catch (IllegalStateException ise) {
            throw new RequestHandlerException(ise.getMessage(), ise);
        }
    }

    private void renderView(String view, boolean allowExtView, HttpServletRequest req, HttpServletResponse resp) throws RequestHandlerException {
        GenericValue userLogin = (GenericValue) req.getSession().getAttribute("userLogin");
        GenericDelegator delegator = (GenericDelegator) req.getAttribute("delegator");
        // workaraound if we are in the root webapp
        String cname = UtilHttp.getApplicationName(req);
        String oldView = view;

        if (view != null && view.length() > 0 && view.charAt(0) == '/') view = view.substring(1);

        // if the view name starts with the control servlet name and a /, then it was an
        // attempt to override the default view with a call back into the control servlet,
        // so just get the target view name and use that
        String servletName = req.getServletPath().substring(1);

        Debug.logInfo("servletName=" + servletName + ", view=" + view + " sessionId=" + UtilHttp.getSessionId(req), module);
        if (view.startsWith(servletName + "/")) {
            view = view.substring(servletName.length() + 1);
            Debug.logInfo("a manual control servlet request was received, removing control servlet path resulting in: view=" + view, module);
        }

        if (Debug.verboseOn()) Debug.logVerbose("[Getting View Map]: " + view + " sessionId=" + UtilHttp.getSessionId(req), module);

        // before mapping the view, set a session attribute so we know where we are
        req.setAttribute("_CURRENT_VIEW_", view);

        String viewType = requestManager.getViewType(view);
        String tempView = requestManager.getViewPage(view);
        String nextPage;

        if (tempView == null) {
            if (!allowExtView) {
                throw new RequestHandlerException("No view to render.");
            } else {
                nextPage = "/" + oldView;
            }
        } else {
            nextPage = tempView;
        }

        if (Debug.verboseOn()) Debug.logVerbose("[Mapped To]: " + nextPage + " sessionId=" + UtilHttp.getSessionId(req), module);

        long viewStartTime = System.currentTimeMillis();

        // setup chararcter encoding and content type
        String charset = getServletContext().getInitParameter("charset");

        if (charset == null || charset.length() == 0) charset = req.getCharacterEncoding();
        if (charset == null || charset.length() == 0) charset = "UTF-8";

        String viewCharset = requestManager.getViewEncoding(view);
        //NOTE: if the viewCharset is "none" then no charset will be used
        if (viewCharset != null && viewCharset.length() > 0) charset = viewCharset;

        if (!"none".equals(charset)) {
            try {
                req.setCharacterEncoding(charset);
            } catch (UnsupportedEncodingException e) {
                throw new RequestHandlerException("Could not set character encoding to " + charset, e);
            } catch (IllegalStateException e) {
                Debug.logInfo(e, "Could not set character encoding to " + charset + ", something has probably already committed the stream", module);
            }
        }

        // setup content type
        String contentType = "text/html";
        String viewContentType = requestManager.getViewContentType(view);
        if (viewContentType != null && viewContentType.length() > 0) contentType = viewContentType;

        if (charset.length() > 0 && !"none".equals(charset)) {
            resp.setContentType(contentType + "; charset=" + charset);
        } else {
            resp.setContentType(contentType);
        }

        if (Debug.verboseOn()) Debug.logVerbose("The ContentType for the " + view + " view is: " + contentType, module);

        try {
            if (Debug.verboseOn()) Debug.logVerbose("Rendering view [" + nextPage + "] of type [" + viewType + "]", module);
            ViewHandler vh = viewFactory.getViewHandler(viewType);
            vh.render(view, nextPage, requestManager.getViewInfo(view), contentType, charset, req, resp);
        } catch (ViewHandlerException e) {
            Throwable throwable = e.getNested() != null ? e.getNested() : e;

            throw new RequestHandlerException(e.getNonNestedMessage(), throwable);
        }

        // before getting the view generation time flush the response output to get more consistent results
        try {
            resp.flushBuffer();
        } catch (java.io.IOException e) {
            throw new RequestHandlerException("Error flushing response buffer", e);
        }

        String vname = (String) req.getAttribute("_CURRENT_VIEW_");

        if (vname != null) {
            ServerHitBin.countView(cname + "." + vname, req, viewStartTime,
                System.currentTimeMillis() - viewStartTime, userLogin, delegator);
        }
    }

    public static String getDefaultServerRootUrl(HttpServletRequest request, boolean secure) {
        String httpsPort = UtilProperties.getPropertyValue("url.properties", "port.https", "443");
        String httpsServer = UtilProperties.getPropertyValue("url.properties", "force.https.host");
        String httpPort = UtilProperties.getPropertyValue("url.properties", "port.http", "80");
        String httpServer = UtilProperties.getPropertyValue("url.properties", "force.http.host");
        boolean useHttps = UtilProperties.propertyValueEqualsIgnoreCase("url.properties", "port.https.enabled", "Y");

        StringBuffer newURL = new StringBuffer();

        if (secure && useHttps) {
            String server = httpsServer;
            if (server == null || server.length() == 0) {
                server = request.getServerName();
            }

            newURL.append("https://");
            newURL.append(server);
            if (!httpsPort.equals("443")) {
                newURL.append(":").append(httpsPort);
            }

        } else {
            String server = httpServer;
            if (server == null || server.length() == 0) {
                server = request.getServerName();
            }

            newURL.append("http://");
            newURL.append(server);
            if (!httpPort.equals("80")) {
                newURL.append(":").append(httpPort);
            }
        }
        return newURL.toString();
    }


    public String makeLinkWithQueryString(HttpServletRequest request, HttpServletResponse response, String url) {
        String initialLink = this.makeLink(request, response, url);
        String queryString = this.makeQueryString(request);
        return initialLink + queryString;
    }

    public String makeLink(HttpServletRequest request, HttpServletResponse response, String url) {
        return makeLink(request, response, url, false, false, true);
    }

    public String makeLink(HttpServletRequest request, HttpServletResponse response, String url, boolean fullPath, boolean secure, boolean encode) {
        GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
        String webSiteId = WebSiteWorker.getWebSiteId(request);

        String httpsPort = null;
        String httpsServer = null;
        String httpPort = null;
        String httpServer = null;
        Boolean enableHttps = null;

        // load the properties from the website entity
        GenericValue webSite;
        if (webSiteId != null) {
            try {
                webSite = delegator.findByPrimaryKeyCache("WebSite", UtilMisc.toMap("webSiteId", webSiteId));
                if (webSite != null) {
                    httpsPort = webSite.getString("httpsPort");
                    httpsServer = webSite.getString("httpsHost");
                    httpPort = webSite.getString("httpPort");
                    httpServer = webSite.getString("httpHost");
                    enableHttps = webSite.getBoolean("enableHttps");
                }
            } catch (GenericEntityException e) {
                Debug.logWarning(e, "Problems with WebSite entity; using global defaults", module);
            }
        }

        // fill in any missing properties with fields from the global file
        if (UtilValidate.isEmpty(httpsPort)) {
            httpsPort = UtilProperties.getPropertyValue("url.properties", "port.https", "443");
        }
        if (UtilValidate.isEmpty(httpServer)) {
            httpsServer = UtilProperties.getPropertyValue("url.properties", "force.https.host");
        }
        if (UtilValidate.isEmpty(httpPort)) {
            httpPort = UtilProperties.getPropertyValue("url.properties", "port.http", "80");
        }
        if (UtilValidate.isEmpty(httpServer)) {
            httpServer = UtilProperties.getPropertyValue("url.properties", "force.http.host");
        }
        if (enableHttps == null) {
            enableHttps = Boolean.valueOf(UtilProperties.propertyValueEqualsIgnoreCase("url.properties", "port.https.enabled", "Y"));
        }

        // create the path the the control servlet
        String controlPath = (String) request.getAttribute("_CONTROL_PATH_");

        String requestUri = RequestHandler.getRequestUri(url);
        StringBuffer newURL = new StringBuffer();

        boolean useHttps = enableHttps.booleanValue();
        boolean didFullSecure = false;
        boolean didFullStandard = false;
        if (useHttps || fullPath || secure) {
            if (secure || (useHttps && requestManager.requiresHttps(requestUri) && !request.isSecure())) {
                String server = httpsServer;
                if (server == null || server.length() == 0) {
                    server = request.getServerName();
                }

                newURL.append("https://");
                newURL.append(server);
                if (!httpsPort.equals("443")) {
                    newURL.append(":").append(httpsPort);
                }

                didFullSecure = true;
            } else if (fullPath || (useHttps && !requestManager.requiresHttps(requestUri) && request.isSecure())) {
                String server = httpServer;
                if (server == null || server.length() == 0) {
                    server = request.getServerName();
                }

                newURL.append("http://");
                newURL.append(server);
                if (!httpPort.equals("80")) {
                    newURL.append(":").append(httpPort);
                }

                didFullStandard = true;
            }
        }

        newURL.append(controlPath);

        // now add the actual passed url, but if it doesn't start with a / add one first
        if (!url.startsWith("/")) {
            newURL.append("/");
        }
        newURL.append(url);

        String encodedUrl;
        if (encode) {
            boolean forceManualJsessionid = false;

            // if this isn't a secure page, but we made a secure URL, make sure we manually add the jsessionid since the response.encodeURL won't do that
            if (!request.isSecure() && didFullSecure) {
                forceManualJsessionid = true;
            }

            // if this is a secure page, but we made a standard URL, make sure we manually add the jsessionid since the response.encodeURL won't do that
            if (request.isSecure() && didFullStandard) {
                forceManualJsessionid = true;
            }

            if (response != null && !forceManualJsessionid) {
                encodedUrl = response.encodeURL(newURL.toString());
            } else {
                String sessionId = ";jsessionid=" + request.getSession().getId();
                // this should be inserted just after the "?" for the parameters, if there is one, or at the end of the string
                int questionIndex = newURL.indexOf("?");
                if (questionIndex == -1) {
                    newURL.append(sessionId);
                } else {
                    newURL.insert(questionIndex, sessionId);
                }
                encodedUrl = newURL.toString();
            }
        } else {
            encodedUrl = newURL.toString();
        }
        //if (encodedUrl.indexOf("null") > 0) {
            //Debug.logError("in makeLink, controlPath:" + controlPath + " url:" + url, "");
            //throw new RuntimeException("in makeLink, controlPath:" + controlPath + " url:" + url);
        //}

        //Debug.logInfo("Making URL, encode=" + encode + " for URL: " + newURL + "\n encodedUrl: " + encodedUrl, module);

        return encodedUrl;
    }

    public static String makeUrl(HttpServletRequest request, HttpServletResponse response, String url) {
        return makeUrl(request, response, url, false, false, false);
    }

    public static String makeUrl(HttpServletRequest request, HttpServletResponse response, String url, boolean fullPath, boolean secure, boolean encode) {
        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
        return rh.makeLink(request, response, url, fullPath, secure, encode);
    }

    public void runAfterLoginEvents(HttpServletRequest request, HttpServletResponse response) {
        List afterLoginEvents = requestManager.getAfterLoginEventList();
        if (afterLoginEvents != null) {
            Iterator i = afterLoginEvents.iterator();
            while (i.hasNext()) {
                Map eventMap = (Map) i.next();
                String eType = (String) eventMap.get(ConfigXMLReader.EVENT_TYPE);
                String ePath = (String) eventMap.get(ConfigXMLReader.EVENT_PATH);
                String eMeth = (String) eventMap.get(ConfigXMLReader.EVENT_METHOD);
                try {
                    String returnString = this.runEvent(request, response, eType, ePath, eMeth);
                    if (returnString != null && !returnString.equalsIgnoreCase("success")) {
                        throw new EventHandlerException("Pre-Processor event did not return 'success'.");
                    }
                } catch (EventHandlerException e) {
                    Debug.logError(e, module);
                }
            }
        }
    }

    public void runBeforeLogoutEvents(HttpServletRequest request, HttpServletResponse response) {
        List beforeLogoutEvents = requestManager.getBeforeLogoutEventList();
        if (beforeLogoutEvents != null) {
            Iterator i = beforeLogoutEvents.iterator();
            while (i.hasNext()) {
                Map eventMap = (Map) i.next();
                String eType = (String) eventMap.get(ConfigXMLReader.EVENT_TYPE);
                String ePath = (String) eventMap.get(ConfigXMLReader.EVENT_PATH);
                String eMeth = (String) eventMap.get(ConfigXMLReader.EVENT_METHOD);
                try {
                    String returnString = this.runEvent(request, response, eType, ePath, eMeth);
                    if (returnString != null && !returnString.equalsIgnoreCase("success")) {
                        throw new EventHandlerException("Pre-Processor event did not return 'success'.");
                    }
                } catch (EventHandlerException e) {
                    Debug.logError(e, module);
                }
            }
        }
    }
}
TOP

Related Classes of org.ofbiz.webapp.control.RequestHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.