📄 butoraction.java
字号:
/* * Copyright (C) butor.com. All rights reserved. * * This software is published under the terms of the GNU Library General * Public License (GNU LGPL), a copy of which has been included with this * distribution in the LICENSE.txt file. */package org.butor.web.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.net.MalformedURLException;import java.net.URL;import java.util.Calendar;import java.util.Collection;import java.util.Date;import java.util.Enumeration;import java.util.Iterator;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionMessage;import org.apache.struts.action.ActionMessages;import org.butor.config.Config;import org.butor.config.lowlevel.IProperties;import org.butor.helper.DateManip;import org.butor.helper.IMessage;import org.butor.log.Log;import org.butor.security.ISecurityChecker;import org.butor.web.context.IWebContext;import org.butor.web.context.WebContext;import org.butor.web.context.WebContextService;import org.butor.web.helper.StandardAttributes;/** * This special abstract Action contains methods to recurrent * tasks a concrete action might need. * * @version $Revision: 755 $ * @author mateusfi */public abstract class ButorAction extends Action { public static final String FORWARD_SUCCESS = "success"; public static final String FORWARD_FAILURE = "failure"; public static final String FORWARD_INIT = "init"; public static final String FORWARD_ADD = "add"; public static final String FORWARD_SEARCH = "search"; public static final String PROPERTY_HOST_LANGUAGE = "host_lang"; public static final String PROPERTY_PASSWORD_URL = "password_url"; public static final String PROPERTY_LOGOUT_URL = "logout_url"; public static final String PROPERTY_HOME_URL = "home_url"; public static final String CONFIG_APP_ACCESS_FNC_CDE = "app_access_fnc_cde"; public static final String PRECONDITION_FAILED_MSG_KEY = "precondition_failed_msg_key"; public static final String MSG_KEY_BAD_TOKEN = "errors.bad_token"; /** * Special value for getHelpKey to indicate that the action * does not have a help topic and must not remove the current help key. */ public static final String NO_HELP_KEY = "no_help_key"; /** * Subclasses place their control code in this method. */ protected abstract ActionForward executeAction(ActionMapping mapping, IButorActionForm form) throws Exception; public void addError(IMessage message) { getContext().addMessage(message); } public static IWebContext getContext() { return WebContextService.getContext(); } protected boolean hasAccessToApplication() { IProperties accessFunctions = Config.getPropertyList(CONFIG_APP_ACCESS_FNC_CDE); if (accessFunctions == null || accessFunctions.size() == 0) { return true; } // This application have application access security ISecurityChecker securityChecker = getContext().getSecurityChecker(); String role = null; for (int i = 0; i < accessFunctions.size(); i++) { role = (String) accessFunctions.getProperty(i); if (securityChecker.access(role)) { return true; } } return false; } protected boolean hasAccessToAction() { return true; } protected final boolean checkAccess() { return hasAccessToApplication() && hasAccessToAction(); } protected void setResponseHeaderProperties(HttpServletResponse response) { Calendar calendar = Calendar.getInstance(); calendar.set(1970, 0, 1, 0, 0, 0); Date expires = calendar.getTime(); response.setHeader("Expires", DateManip.formatDate("EEE, d MMM yyyy HH:mm:ss zzz", expires)); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); } /** * Common code for all actions. */ public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { setResponseHeaderProperties(response); ActionForward actionForward = null; refreshContext(request, response); IWebContext context = getContext(); Log.logStr(this, Log.LOG_TYPE_INFO, "execute()", "Start execute, URI: " +request.getRequestURI()); if (Log.shouldLog(ButorAction.class.getName(), Log.LOG_LEVEL_MEDIUM)) { StringBuffer buff = new StringBuffer(); Enumeration en = request.getAttributeNames(); String key = null; while (en.hasMoreElements()) { key = (String) en.nextElement(); buff.append(key); buff.append("=["); buff.append(request.getAttribute(key)); buff.append("], "); } Log.logStr(this, Log.LOG_TYPE_INFO, "execute()", "Request params: " +buff.toString()); } try { // a mapping can exist without a form if (form != null && !(form instanceof IButorActionForm)) { throw new UnsupportedOperationException("CommonAction must be used with ICommonActionForm"); } IButorActionForm commonForm = (IButorActionForm)form; // Checks if this action must check the password if (mustCheckPassword()) { // The presence of the attribute indicates a mandatory password change if (context.readProperty(StandardAttributes.MUST_CHANGE_PASSWORD) != null) { String passwordUrl = Config.getProperty(PROPERTY_PASSWORD_URL, null); if (passwordUrl == null) { Log.logStr(this, Log.LOG_TYPE_WARN, "execute", "User must change his password but " + PROPERTY_PASSWORD_URL + " is not defined in config."); } else { return new ActionForward(passwordUrl); } } } // sets standard attributes buildCurrentUrl(request); context.setProperty(StandardAttributes.HOME_URL, Config.getProperty(PROPERTY_HOME_URL, "undefined")); context.setProperty(StandardAttributes.LOGOUT_URL, Config.getProperty(PROPERTY_LOGOUT_URL, "undefined")); // Check access to application or function if (!checkAccess()) { Log.logStr(this, Log.LOG_TYPE_WARN, "execute()", "Forbidden access catch : " + request.getRequestURI()); response.setStatus(HttpServletResponse.SC_FORBIDDEN); return null; } // Execute Action actionForward = executeAction(mapping, (IButorActionForm)form); processErrors(request); } catch (Exception e) { Log.logException(this, Log.LOG_TYPE_ERROR, "execute", e); // Let Tomcat handle the response. response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { long age = 0; if (context != null) { age = context.getAge(); } Log.logStr(this, Log.LOG_TYPE_INFO, "execute()", "End execute, age of request: " + age + " ms"); } return actionForward; } /** * Set forbidden access code in http servlet response * * @return true if the forbidden access status is set, else will return false. */ protected final boolean setForbiddenAccess(){ IWebContext context = getContext(); if (context == null) { Log.logStr(this, Log.LOG_TYPE_ERROR, "setForbiddenAccess()", "Got null context. Could not set forbidden access"); return false; } HttpServletResponse response = context.getResponse(); if (response == null) { Log.logStr(this, Log.LOG_TYPE_ERROR, "setForbiddenAccess()", "Got null response in context. Could not set forbidden access"); return false; } response.setStatus(HttpServletResponse.SC_FORBIDDEN); return true; } /** * Check token is valid? * compare to last updated token with the one provided. * This method is used in an Action to validate * a one time post operation. In the form there must be a hidden field containing * the last generated token (use taglib). */ public boolean checkToken() { IWebContext context = getContext(); if (context == null) { Log.logStr(this, Log.LOG_TYPE_ERROR, "checkToken()", "Got null context. Could not set bad token!"); return false; } if (isTokenValid(context.getRequest())) { return true; } HttpServletResponse response = context.getResponse(); if (response == null) { Log.logStr(this, Log.LOG_TYPE_ERROR, "checkToken()", "Got null response in context. Could not set bad token!"); } context.setProperty(PRECONDITION_FAILED_MSG_KEY, MSG_KEY_BAD_TOKEN); response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); return false; } /** * Create a new token and keep it in session * for later usage with checkToken(). */ public boolean updateToken() { IWebContext context = getContext(); if (context == null) { Log.logStr(this, Log.LOG_TYPE_ERROR, "updateToken()", "Got null context. Could not update token!"); return false; } saveToken(context.getRequest()); return true; } /** * Record the last URL so any JSP can know the origin of this request. * For example, this allows to do a language change from any page. * Two attributes are set here: * - the current url relative to current webapp * - the absolute url */ protected void buildCurrentUrl(HttpServletRequest request) { // Record the last URL so any JSP can know the origin of this // request. StringBuffer url = new StringBuffer(); url.append(request.getServletPath()); String queryString = buildQueryString(request); if (!queryString.equals("")) { url.append("?" + queryString); } if (Log.shouldLog(ButorAction.class.getName(), Log.LOG_LEVEL_MEDIUM)) { Log.logStr(this, Log.LOG_TYPE_WARN, "buildCurrentUrl()", "Request URL=[" +url.toString() +"]"); } request.setAttribute(StandardAttributes.CURRENT_URL, url.toString()); try { String relativeUrl = request.getContextPath() + url.toString(); URL absoluteUrl = new URL(request.getScheme(), request.getServerName(), request.getServerPort(), relativeUrl); request.setAttribute(StandardAttributes.CURRENT_ABSOLUTE_URL, absoluteUrl.toString()); } catch (MalformedURLException e) { Log.logException(this, Log.LOG_TYPE_WARN, "buildCurrentUrl", e); } } protected String buildQueryString(HttpServletRequest request) { String queryString = request.getQueryString(); if (queryString == null) { queryString = ""; } return queryString; } /** * Default behavior: checks if the user must change his password. * Subclasses who do not want the password check to be done must * override this method and return false. */ protected boolean mustCheckPassword() { return true; } protected void processErrors(HttpServletRequest request) { // Retrieves errors from context IWebContext context = getContext(); ActionMessages actionMessages = null; Collection messages = context.getMessages(); if (messages != null) { // Get struts saved errors actionMessages = getMessages(request); if (actionMessages == null) { actionMessages = new ActionMessages(); } Iterator it = messages.iterator(); IMessage msg = null; while(it.hasNext()) { msg = (IMessage)it.next(); if (msg.getSeverity() == IMessage.SEVERITY_INFO) { // Messages actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("label.literal", msg.getText())); } else { //TODO // Warnings and errors actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("label.literal", msg.getText())); } } context.clearMessages(); } /*TODO if (errors != null && !errors.isEmpty()) { saveErrors(request, errors); } */ } /** * Refresh the context with request and response just gotten by this action. * (May be different from request and response object gotton from a filter for example). */ protected void refreshContext(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); WebContext context = (WebContext)WebContextService.getContext(); if (context != null) { context.setRequest(request); context.setResponse(response); context.setSession(session); } else { Log.logStr(this, Log.LOG_TYPE_ERROR, "refreshContext", "context is null"); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -