use of org.apache.ofbiz.webapp.view.ViewHandler in project ofbiz-framework by apache.
the class RequestHandler method renderView.
private void renderView(String view, boolean allowExtView, HttpServletRequest req, HttpServletResponse resp, String saveName) throws RequestHandlerException {
GenericValue userLogin = (GenericValue) req.getSession().getAttribute("userLogin");
// workaround if we are in the root webapp
String cname = UtilHttp.getApplicationName(req);
String oldView = view;
if (UtilValidate.isNotEmpty(view) && 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();
if (UtilValidate.isNotEmpty(servletName) && servletName.length() > 1 || servletName.startsWith("/")) {
servletName = servletName.substring(1);
}
if (UtilHttp.getVisualTheme(req) == null) {
UtilHttp.setVisualTheme(req.getSession(), ThemeFactory.resolveVisualTheme(req));
}
if (Debug.infoOn())
Debug.logInfo("Rendering View [" + view + "]. " + showSessionId(req), module);
if (view.startsWith(servletName + "/")) {
view = view.substring(servletName.length() + 1);
if (Debug.infoOn())
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 + showSessionId(req), module);
// before mapping the view, set a request attribute so we know where we are
req.setAttribute("_CURRENT_VIEW_", view);
// save the view in the session for the last view, plus the parameters Map (can use all parameters as they will never go into a URL, will only stay in the session and extra data will be ignored as we won't go to the original request just the view); note that this is saved after the request/view processing has finished so when those run they will get the value from the previous request
Map<String, Object> paramMap = UtilHttp.getParameterMap(req);
// add in the attributes as well so everything needed for the rendering context will be in place if/when we get back to this view
paramMap.putAll(UtilHttp.getAttributeMap(req));
UtilMisc.makeMapSerializable(paramMap);
if (paramMap.containsKey("_LAST_VIEW_NAME_")) {
// Used by lookups to keep the real view (request)
req.getSession().setAttribute("_LAST_VIEW_NAME_", paramMap.get("_LAST_VIEW_NAME_"));
} else {
req.getSession().setAttribute("_LAST_VIEW_NAME_", view);
}
req.getSession().setAttribute("_LAST_VIEW_PARAMS_", paramMap);
if ("SAVED".equals(saveName)) {
// Debug.logInfo("======save current view: " + view);
req.getSession().setAttribute("_SAVED_VIEW_NAME_", view);
req.getSession().setAttribute("_SAVED_VIEW_PARAMS_", paramMap);
}
if ("HOME".equals(saveName)) {
// Debug.logInfo("======save home view: " + view);
req.getSession().setAttribute("_HOME_VIEW_NAME_", view);
req.getSession().setAttribute("_HOME_VIEW_PARAMS_", paramMap);
// clear other saved views
req.getSession().removeAttribute("_SAVED_VIEW_NAME_");
req.getSession().removeAttribute("_SAVED_VIEW_PARAMS_");
}
ConfigXMLReader.ViewMap viewMap = null;
try {
viewMap = (view == null ? null : getControllerConfig().getViewMapMap().get(view));
} catch (WebAppConfigurationException e) {
Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
throw new RequestHandlerException(e);
}
if (viewMap == null) {
throw new RequestHandlerException("No definition found for view with name [" + view + "]");
}
String nextPage;
if (viewMap.page == null) {
if (!allowExtView) {
throw new RequestHandlerException("No view to render.");
} else {
nextPage = "/" + oldView;
}
} else {
nextPage = viewMap.page;
}
if (Debug.verboseOn())
Debug.logVerbose("[Mapped To]: " + nextPage + showSessionId(req), module);
long viewStartTime = System.currentTimeMillis();
// setup character encoding and content type of the response:
// encoding/charset: use the one set in the view or, if not set, the one set in the request
// content type: use the one set in the view or, if not set, use "text/html"
String charset = req.getCharacterEncoding();
String viewCharset = viewMap.encoding;
// NOTE: if the viewCharset is "none" then no charset will be used
if (UtilValidate.isNotEmpty(viewCharset)) {
charset = viewCharset;
}
String contentType = "text/html";
String viewContentType = viewMap.contentType;
if (UtilValidate.isNotEmpty(viewContentType)) {
contentType = viewContentType;
}
if (UtilValidate.isNotEmpty(charset) && !"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);
boolean viewNoCache = viewMap.noCache;
if (viewNoCache) {
UtilHttp.setResponseBrowserProxyNoCache(resp);
if (Debug.verboseOn())
Debug.logVerbose("Sending no-cache headers for view [" + nextPage + "]", module);
}
// Security headers vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// See https://cwiki.apache.org/confluence/display/OFBIZ/How+to+Secure+HTTP+Headers
String xFrameOption = viewMap.xFrameOption;
// default to sameorigin
if (UtilValidate.isNotEmpty(xFrameOption)) {
if (!"none".equals(xFrameOption)) {
resp.addHeader("x-frame-options", xFrameOption);
}
} else {
resp.addHeader("x-frame-options", "sameorigin");
}
String strictTransportSecurity = viewMap.strictTransportSecurity;
// default to "max-age=31536000; includeSubDomains" 31536000 secs = 1 year
if (UtilValidate.isNotEmpty(strictTransportSecurity)) {
if (!"none".equals(strictTransportSecurity)) {
resp.addHeader("strict-transport-security", strictTransportSecurity);
}
} else {
if (EntityUtilProperties.getPropertyAsBoolean("requestHandler", "strict-transport-security", true)) {
// FIXME later pass req.getAttribute("delegator") as last argument
resp.addHeader("strict-transport-security", "max-age=31536000; includeSubDomains");
}
}
// The only x-content-type-options defined value, "nosniff", prevents Internet Explorer from MIME-sniffing a response away from the declared content-type.
// This also applies to Google Chrome, when downloading extensions.
resp.addHeader("x-content-type-options", "nosniff");
// This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
// It's usually enabled by default anyway, so the role of this header is to re-enable the filter for this particular website if it was disabled by the user.
// This header is supported in IE 8+, and in Chrome (not sure which versions). The anti-XSS filter was added in Chrome 4. Its unknown if that version honored this header.
// FireFox has still an open bug entry and "offers" only the noscript plugin
// https://wiki.mozilla.org/Security/Features/XSS_Filter
// https://bugzilla.mozilla.org/show_bug.cgi?id=528661
resp.addHeader("X-XSS-Protection", "1; mode=block");
// This is the default (in Firefox at least)
resp.setHeader("Referrer-Policy", "no-referrer-when-downgrade");
// resp.setHeader("Content-Security-Policy", "default-src 'self'");
// resp.setHeader("Content-Security-Policy-Report-Only", "default-src 'self'; report-uri webtools/control/ContentSecurityPolicyReporter");
resp.setHeader("Content-Security-Policy-Report-Only", "default-src 'self'");
try {
if (Debug.verboseOn())
Debug.logVerbose("Rendering view [" + nextPage + "] of type [" + viewMap.type + "]", module);
ViewHandler vh = viewFactory.getViewHandler(viewMap.type);
vh.render(view, nextPage, viewMap.info, 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) {
/* If any request gets aborted before completing, i.e if a user requests a page and cancels that request before the page is rendered and returned
or if request is an ajax request and user calls abort() method for on ajax request then its showing broken pipe exception on console,
skip throwing of RequestHandlerException. JIRA Ticket - OFBIZ-254
*/
if (Debug.verboseOn())
Debug.logVerbose("Skip Request Handler Exception that is caused due to aborted requests. " + e.getMessage(), module);
}
String vname = (String) req.getAttribute("_CURRENT_VIEW_");
if (this.trackStats(req) && vname != null) {
ServerHitBin.countView(cname + "." + vname, req, viewStartTime, System.currentTimeMillis() - viewStartTime, userLogin);
}
}
Aggregations