/* This file is part of OpenMyEWB. OpenMyEWB is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenMyEWB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMyEWB. If not, see <http://www.gnu.org/licenses/>. OpenMyEWB is Copyright 2005-2009 Nicolas Kruchten (nicolas@kruchten.com), Francis Kung, Engineers Without Borders Canada, Michael Trauttmansdorff, Jon Fishbein, David Kadish */ package ca.myewb.frame; import java.io.Serializable; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.Vector; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.apache.velocity.context.Context; import org.hibernate.Session; import ca.myewb.frame.forms.Form; import ca.myewb.model.GroupChapterModel; import ca.myewb.model.GroupModel; import ca.myewb.model.UserModel; public abstract class Controller { public static final String path = Helpers.getAppPrefix(); protected Session hibernateSession; protected HttpSession httpSession; protected Logger log = Logger.getLogger(this.getClass()); public PostParamWrapper requestParams; protected GetParamWrapper urlParams; protected UserModel currentUser; private HttpServletRequest request = null; private HttpServletResponse response = null; public abstract void handle(Context ctx) throws Exception; public Set<String> defaultGroups() { return null; } public Set<String> invisibleGroups() { return null; } public boolean secureAccessRequired() { return false; } public String displayName() { return this.getClass().getName() .substring(this.getClass().getName().lastIndexOf('.') + 1); } public String oldName() { return null; } public int weight() { return 0; } public void setHibernateSession(Session session) { this.hibernateSession = session; } public void setHttpSession(HttpSession httpSession) { this.httpSession = httpSession; } public void setRequestParams(PostParamWrapper requestParams) { this.requestParams = requestParams; } public void setHttpRequest(HttpServletRequest request) { this.request = request; } public void setHttpResponse(HttpServletResponse response) { this.response = response; } public List<String> getNeededInterpageVars() { return new Vector<String>(); } @SuppressWarnings("unchecked") protected void setInterpageVar(String name, Object var) { Hashtable<String, Object> hashtable = (Hashtable)httpSession .getAttribute("interpageVars"); hashtable.put(name, var); } protected Object getInterpageVar(String name) { return ((Hashtable)httpSession.getAttribute("interpageVars")).get(name); } protected void removeInterpageVar(String name) { ((Hashtable)httpSession.getAttribute("interpageVars")).remove(name); } @SuppressWarnings("unchecked") protected PostParamWrapper getStoredParams(String datestamp) { try { log.debug("Number of stored params: " + ((Hashtable<String, PostParamWrapper>)httpSession.getAttribute("storedParams")).size()); return ((Hashtable<String, PostParamWrapper>)httpSession.getAttribute("storedParams")).get(datestamp); } catch( Exception e ) { return null; } } @SuppressWarnings("unchecked") protected Form getStoredForm(String datestamp) { try { return ((Hashtable<String, Form>)httpSession.getAttribute("storedForms")).get(datestamp); } catch( Exception e ) { return null; } } @SuppressWarnings("unchecked") protected void setConfirmData(String datestamp, Form f, PostParamWrapper p) { ((Hashtable<String, PostParamWrapper>)httpSession.getAttribute("storedParams")).put(datestamp, p); if( f != null ) { ((Hashtable<String, Form>)httpSession.getAttribute("storedForms")).put(datestamp, f); } } @SuppressWarnings("unchecked") protected void removeConfirmData(String datestamp) { ((Hashtable<String, PostParamWrapper>)httpSession.getAttribute("storedParams")).remove(datestamp); if(((Hashtable<String, Form>)httpSession.getAttribute("storedForms")).containsKey(datestamp)) { ((Hashtable<String, Form>)httpSession.getAttribute("storedForms")).remove(datestamp); } } public void setCurrentUser(UserModel currentUser) { this.currentUser = currentUser; } public void setUrlParams(GetParamWrapper urlParams) { this.urlParams = urlParams; } protected boolean isOnConfirmLeg() { return requestParams.get("confirmed") != null; } protected void requireConfirmation(String bigMessage, String littleMessage, String cancelURL, String confirmURL, String area, Form form) throws RedirectionException { requireConfirmation(bigMessage, littleMessage, cancelURL, confirmURL, area, form, false); } protected void requireConfirmation(String bigMessage, String littleMessage, String cancelURL, String confirmURL, String area, Form form, boolean fileMessage) throws RedirectionException { //NOTE: controllers calling this must have interpagevars from GenericConfirm.getRequiredInterpageVars //from the point of view of the controller, calling this function acts as a passthrough if confirmed //although the controller must create the form it intends to use AFTER the call, even if it was created before for validation //if not confirmed, if a form was passed in, that form is passed back to the cancelURL with a formmessage //if no form was passed in, the user just lands at the cancelURL if (requestParams.get("confirmed") != null) { String datestamp = requestParams.get("datestamp"); if (requestParams.get("confirmed").equals("yes")) { requestParams = getStoredParams(datestamp); if (requestParams == null) //we've somehow lost the interpagevars { log.debug("We've lost the interpagevars! Redirecting to " + cancelURL); removeConfirmData(datestamp); throw new RedirectionException(cancelURL); } removeConfirmData(datestamp); return; } else //should be 'no' { Form storedForm = getStoredForm(datestamp); if (storedForm != null) { if(fileMessage) { setSessionErrorMessage(("You didn't confirm: no action taken<br />Please reattach any files before resubmitting.")); } else { setSessionErrorMessage(("You didn't confirm: no action taken")); } httpSession.setAttribute("form", storedForm); } removeConfirmData(datestamp); throw new RedirectionException(cancelURL); } } else { String datestamp = Long.toString(System.currentTimeMillis()); log.info("Form data saved with datestamp: " + datestamp); setConfirmData(datestamp, form, requestParams); setInterpageVar("datestamp", datestamp); setInterpageVar("bigMessage", bigMessage); setInterpageVar("littleMessage", littleMessage); setInterpageVar("confirmURL", confirmURL); throw new RedirectionException(path + "/" + area + "/Confirm"); } } protected int requireIdUrlParam(String paramName) throws RedirectionException { String param = null; if (paramName == null) { param = urlParams.getParam(); //look at first parameter } else { param = urlParams.get(paramName); } try { param = param.replaceAll("\\.", "").replaceAll(",", ""); int trial = new Integer(param); if (trial < 1) { throw new Exception(); } else { return trial; } } catch (Exception e) //presumably an NPE or NFE or the number is negative { throw getSecurityException("The previously requested URL was invalid.", "invalid or missing urlParam", getLeadPage()); } } protected Object getAndCheckFromUrl(Class clazz) throws RedirectionException { return getAndCheckFromUrl(clazz, null); //look at first parameter } protected Object getAndCheckFromUrl(Class clazz, String paramName) throws RedirectionException { int id; if(clazz.equals(GroupModel.class) || clazz.equals(GroupChapterModel.class)) { String name = ""; if (paramName == null) { name = urlParams.getParam(); //look at first parameter } else { name = urlParams.get(paramName); } try { GroupChapterModel g = (GroupChapterModel)HibernateUtil.currentSession() .createQuery("FROM GroupChapterModel g where g.shortname=?") .setString(0, name).uniqueResult(); if(g != null) { return getAndCheck(clazz, g.getId()); } } catch(Exception e) { log.warn("can't happen"); } } try { id = requireIdUrlParam(paramName); } catch (RedirectionException e) { //log here again so we can catch WHAT she was trying to load with a bad ID log.warn("tried to request a " + clazz.getName() + " with a bad id"); throw e; } return getAndCheck(clazz, id); } public Object getAndCheck(Class clazz, Serializable id) throws RedirectionException { //this is basically a session.load() replacement, //as per the hib docs's recommendation to use get() and then check the result Object obj = hibernateSession.get(clazz, id); if (obj != null) { return obj; } else { throw getSecurityException("There was a minor server error... sorry!", "bad id for " + clazz.getName(), getLeadPage()); } } protected String getLeadPage() { String[] pkgs = this.getClass().getName().split("\\."); if (pkgs[pkgs.length - 2].equals("actions")) { return Helpers.getDefaultURL(); } String leadPage = path + "/" + pkgs[pkgs.length - 2] + "/" + pkgs[pkgs.length - 2].substring(0, 1).toUpperCase() + pkgs[pkgs.length - 2].substring(1); return leadPage; } public RedirectionException getSecurityException(String message, String returnPath) { return getSecurityException(message, null, returnPath); //most of the time, a note isn't needed, the message is descriptive enough } protected RedirectionException getSecurityException(String message, String note, String returnPath) { //leave a message in session httpSession.setAttribute("message", new ErrorMessage(message)); //security logging String logmsg = "user " + currentUser.getUsername() + " got message: \"" + message + "\" when accessing " + this.getClass().getName() + " with GET params=" + urlParams.toString() + " and POST params=" + requestParams.toString(); if (note != null) { logmsg += (" NOTE: " + note); } log.warn(logmsg); //return the exception to throw return new RedirectionException(returnPath, true); } protected Form checkForValidationFailure(Context ctx) { //we return a form which the controller generally then tries to downcast //that's just an extra check in case the flow got messed up Form possibleForm = (Form)httpSession.getAttribute("form"); if (possibleForm == null) { return null; } ctx.put("formmessage", httpSession.getAttribute("formmessage")); httpSession.removeAttribute("form"); httpSession.removeAttribute("formmessage"); return possibleForm; } protected RedirectionException getValidationException(Form form, Message message, String returnPath) { httpSession.setAttribute("formmessage", message); httpSession.setAttribute("form", form); log.debug("form validation failure: " + message.getMessage()); return new RedirectionException(returnPath); } protected String[] toStringArray(Object[] in) { String[] result = new String[in.length]; for(int i=0; i<in.length; i++) { result[i] = (String)in[i]; } return result; } protected void setSessionMessage(String msg) { httpSession.setAttribute("message", new Message(msg)); } protected void setSessionErrorMessage(String msg) { httpSession.setAttribute("message", new ErrorMessage(msg)); } public String getCookie(String name) { if (request == null) return null; Cookie[] cookies = request.getCookies(); if (cookies == null) return null; for (int i = 0; i < cookies.length; i++) if (cookies[i].getName().equals(name)) return cookies[i].getValue(); return null; } public boolean setCookie(String name, String value) { if (response == null) return false; Cookie cookie = new Cookie(name, value); cookie.setPath(Helpers.getAppPrefix() + "/"); cookie.setMaxAge(12 * 31 * 24 * 60 * 60); response.addCookie(cookie); return true; } }