/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.servlets; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.log4j.*; import com.silverwrist.util.StringUtil; import com.silverwrist.util.ServletMultipartHandler; import com.silverwrist.util.ServletMultipartException; import com.silverwrist.venice.core.*; import com.silverwrist.venice.servlets.format.*; public abstract class VeniceServlet extends HttpServlet { /*-------------------------------------------------------------------------------- * Static data values *-------------------------------------------------------------------------------- */ private static final String LOCATION_ATTR = "com.silverwrist.venice.servlets.internal.Location"; private static Category logger = Category.getInstance(VeniceServlet.class.getName()); /*-------------------------------------------------------------------------------- * Internal functions *-------------------------------------------------------------------------------- */ private static final void notSupported(HttpServletRequest request, String message) throws ErrorResult { String protocol = request.getProtocol(); if (protocol.endsWith("1.1")) throw new ErrorResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED,message); else throw new ErrorResult(HttpServletResponse.SC_BAD_REQUEST,message); } // end notSupported private static final SIGContext getSIGParameter(String str, UserContext user, boolean required, String on_error) throws ErrorBox { if (StringUtil.isStringEmpty(str)) { // there's no SIG parameter if (required) { // no SIG parameter - bail out now! logger.error("SIG parameter not specified!"); throw new ErrorBox(null,"No SIG specified.",on_error); } // end if else { // a null SIGContext is permitted logger.debug("no SIG specified"); return null; } // end else } // end if SIGContext rc = null; try { // turn the string into a SIGID, and thence to a SIGContext int tmp_id = Integer.parseInt(str); rc = user.getSIGContext(tmp_id); if (rc==null) { // trap any null results (may not be possible with SIGs, but you never know) logger.error("SIG #" + tmp_id + " was not found!"); throw new ErrorBox(null,"The specified SIG (#" + tmp_id + ") was not found in the database.",on_error); } // end if if (logger.isDebugEnabled()) logger.debug("found SIG #" + rc.getSIGID()); } // end try catch (NumberFormatException nfe) { // error in Integer.parseInt logger.error("Cannot convert SIG parameter '" + str + "'!"); throw new ErrorBox(null,"Invalid SIG parameter.",on_error); } // end catch catch (DataException de) { // error looking up the SIG throw new ErrorBox("Database Error","Database error finding SIG: " + de.getMessage(),on_error); } // end catch return rc; } // end getSIGParameter private static TopicContext getTopicParameter(String str, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { if (StringUtil.isStringEmpty(str)) { // there's no topic parameter if (required) { // no topic parameter - bail out now! logger.error("Topic parameter not specified!"); throw new ErrorBox(null,"No topic specified.",on_error); } // end if else { // a null TopicContext is permitted logger.debug("no topic specified"); return null; } // end else } // end if TopicContext rc = null; try { // turn the string into a topic number, and thence to a TopicContext short tmp_id = Short.parseShort(str); rc = conf.getTopic(tmp_id); if (rc==null) { // the topic was not found! logger.error("ConfID #" + conf.getConfID() + " did not have topic #" + tmp_id); throw new ErrorBox(null,"Topic #" + tmp_id + " was not found in the '" + conf.getName() + "' conference.",on_error); } // end if if (logger.isDebugEnabled()) logger.debug("found topic #" + rc.getTopicID()); } // end try catch (NumberFormatException nfe) { // error in Integer.parseInt logger.error("Cannot convert topic parameter '" + str + "'!"); throw new ErrorBox(null,"Invalid topic parameter.",on_error); } // end catch catch (AccessError ae) { // these all get handled in pretty much the same way throw new ErrorBox("Access Error",ae.getMessage(),on_error); } // end catch catch (DataException de) { // error looking up the topic throw new ErrorBox("Database Error","Database error finding topic: " + de.getMessage(),"top"); } // end catch return rc; } // end getTopicParameter private static TopicMessageContext getMessageParameter(String str, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { if (StringUtil.isStringEmpty(str)) { // there's no message parameter if (required) { // no message parameter - bail out now! logger.error("Message parameter not specified!"); throw new ErrorBox(null,"No message specified.",on_error); } // end if else { // a null TopicMessageContext is permitted logger.debug("no message specified"); return null; } // end else } // end if TopicMessageContext rc = null; try { // turn the string into a postid, and thence to a TopicMessageContext long tmp_id = Long.parseLong(str); rc = conf.getMessageByPostID(tmp_id); if (rc==null) { // the message was not found logger.error("ConfID #" + conf.getConfID() + " does not contain postid " + tmp_id); throw new ErrorBox(null,"The post with ID number " + tmp_id + " was not found in the '" + conf.getName() + "' conference.",on_error); } // end if if (logger.isDebugEnabled()) logger.debug("found post #" + rc.getPostID()); } // end try catch (NumberFormatException nfe) { // error in Integer.parseInt logger.error("Cannot convert message parameter '" + str + "'!"); throw new ErrorBox(null,"Invalid message parameter.",on_error); } // end catch catch (AccessError ae) { // these all get handled in pretty much the same way throw new ErrorBox("Access Error",ae.getMessage(),on_error); } // end catch catch (DataException de) { // error looking up the conference throw new ErrorBox("Database Error","Database error finding message: " + de.getMessage(),on_error); } // end catch return rc; } // end getMessageParameter private static TopicMessageContext getMessageParameter(String str, TopicContext topic, boolean required, String on_error) throws ErrorBox { if (StringUtil.isStringEmpty(str)) { // there's no message parameter if (required) { // no message parameter - bail out now! logger.error("Message parameter not specified!"); throw new ErrorBox(null,"No message specified.",on_error); } // end if else { // a null TopicMessageContext is permitted logger.debug("no message specified"); return null; } // end else } // end if TopicMessageContext rc = null; try { // turn the string into a post number, and thence to a TopicMessageContext int tmp_id = Integer.parseInt(str); rc = topic.getMessage(tmp_id); if (rc==null) { // could not find the message logger.error("TopicID " + topic.getTopicID() + " does not contain message #" + tmp_id); throw new ErrorBox(null,"There is no message #" + tmp_id + " in the '" + topic.getName() + "' topic.", on_error); } // end if if (logger.isDebugEnabled()) logger.debug("found post #" + rc.getPostID()); } // end try catch (NumberFormatException nfe) { // error in Integer.parseInt logger.error("Cannot convert message parameter '" + str + "'!"); throw new ErrorBox(null,"Invalid message parameter.",on_error); } // end catch catch (AccessError ae) { // these all get handled in pretty much the same way throw new ErrorBox("Access Error",ae.getMessage(),on_error); } // end catch catch (DataException de) { // error looking up the conference throw new ErrorBox("Database Error","Database error finding message: " + de.getMessage(),on_error); } // end catch return rc; } // end getMessageParameter /*-------------------------------------------------------------------------------- * Internal operations intended for use by derived classes *-------------------------------------------------------------------------------- */ protected static final boolean isImageButtonClicked(ServletRequest request, String name) { String val = request.getParameter(name + ".x"); return (val!=null); } // end isImageButtonClicked protected final void putUserContext(HttpServletRequest request, UserContext ctxt) { Variables.putUserContext(request.getSession(true),ctxt); } // end putUserContext protected final void clearUserContext(HttpServletRequest request) { Variables.clearUserContext(request.getSession(true)); } // end clearUserContext protected static final List getCountryList(ServletContext ctxt) throws ServletException { return Variables.getCountryList(ctxt); } // end getCountryList protected final List getCountryList() throws ServletException { return Variables.getCountryList(getServletContext()); } // end getCountryList protected final List getLanguageList(ServletContext ctxt) throws ServletException { return Variables.getLanguageList(ctxt); } // end getLanguageList protected final List getLanguageList() throws ServletException { return Variables.getLanguageList(getServletContext()); } // end getLanguageList protected final void changeMenuTop(HttpServletRequest request) { Variables.setMenuTop(getServletContext(),request.getSession(true)); } // end changeMenuTop protected final void changeMenuSIG(HttpServletRequest request, SIGContext sig) { Variables.setMenuSIG(request.getSession(true),sig); } // end changeMenuSIG protected final void clearMenu(HttpServletRequest request) { Variables.clearMenu(request.getSession(true)); } // end clearMenu protected final String getStandardCommandParam(ServletRequest request) { String foo = request.getParameter("cmd"); if (foo==null) return "???"; else return foo; } // end getStandardCommandParam protected final void setMyLocation(ServletRequest request, String loc) { request.setAttribute(LOCATION_ATTR,loc); } // end setMyLocation protected final static SIGContext getSIGParameter(ServletRequest request, UserContext user, boolean required, String on_error) throws ErrorBox { return getSIGParameter(request.getParameter("sig"),user,required,on_error); } // end getSIGParameter protected final static SIGContext getSIGParameter(ServletMultipartHandler mphandler, UserContext user, boolean required, String on_error) throws ErrorBox { if (mphandler.isFileParam("sig")) throw new ErrorBox(null,"Internal Error: SIG should be a normal param",on_error); return getSIGParameter(mphandler.getValue("sig"),user,required,on_error); } // end getSIGParameter protected static ConferenceContext getConferenceParameter(String str, SIGContext sig, boolean required, String on_error) throws ErrorBox { if (StringUtil.isStringEmpty(str)) { // there's no conference parameter if (required) { // no conference parameter - bail out now! logger.error("Conference parameter not specified!"); throw new ErrorBox(null,"No conference specified.",on_error); } // end if else { // a null ConferenceContext is permitted logger.debug("no conference specified"); return null; } // end else } // end if ConferenceContext rc = null; try { // turn the string into a ConfID, and thence to a ConferenceContext int tmp_id = Integer.parseInt(str); rc = sig.getConferenceContext(tmp_id); if (rc==null) { // couldn't find the conference logger.error("SIG #" + sig.getSIGID() + " does not contain conference #" + tmp_id); throw new ErrorBox(null,"The conference #" + tmp_id + " could not be found in the '" + sig.getName() + "' SIG.",on_error); } // end if if (logger.isDebugEnabled()) logger.debug("found conf #" + rc.getConfID()); } // end try catch (NumberFormatException nfe) { // error in Integer.parseInt logger.error("Cannot convert conference parameter '" + str + "'!"); throw new ErrorBox(null,"Invalid conference parameter.",on_error); } // end catch catch (AccessError ae) { // these all get handled in pretty much the same way throw new ErrorBox("Access Error",ae.getMessage(),on_error); } // end catch catch (DataException de) { // error looking up the conference throw new ErrorBox("Database Error","Database error finding conference: " + de.getMessage(),on_error); } // end catch return rc; } // end getConferenceParameter protected final static ConferenceContext getConferenceParameter(ServletRequest request, SIGContext sig, boolean required, String on_error) throws ErrorBox { return getConferenceParameter(request.getParameter("conf"),sig,required,on_error); } // end getConferenceParameter protected final static ConferenceContext getConferenceParameter(ServletMultipartHandler mphandler, SIGContext sig, boolean required, String on_error) throws ErrorBox { if (mphandler.isFileParam("conf")) throw new ErrorBox(null,"Internal Error: conference should be a normal param",on_error); return getConferenceParameter(mphandler.getValue("conf"),sig,required,on_error); } // end getConferenceParameter protected final static TopicContext getTopicParameter(ServletRequest request, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { return getTopicParameter(request.getParameter("top"),conf,required,on_error); } // end getTopicParameter protected final static TopicContext getTopicParameter(ServletMultipartHandler mphandler, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { if (mphandler.isFileParam("top")) throw new ErrorBox(null,"Internal Error: topic should be a normal param",on_error); return getTopicParameter(mphandler.getValue("top"),conf,required,on_error); } // end getTopicParameter protected final static TopicMessageContext getMessageParameter(ServletRequest request, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { return getMessageParameter(request.getParameter("msg"),conf,required,on_error); } // end getMessageParameter protected final static TopicMessageContext getMessageParameter(ServletMultipartHandler mphandler, ConferenceContext conf, boolean required, String on_error) throws ErrorBox { if (mphandler.isFileParam("msg")) throw new ErrorBox(null,"Internal Error: message should be a normal param",on_error); return getMessageParameter(mphandler.getValue("msg"),conf,required,on_error); } // end getMessageParameter protected final static TopicMessageContext getMessageParameter(ServletRequest request, TopicContext topic, boolean required, String on_error) throws ErrorBox { return getMessageParameter(request.getParameter("msg"),topic,required,on_error); } // end getMessageParameter protected final static TopicMessageContext getMessageParameter(ServletMultipartHandler mphandler, TopicContext topic, boolean required, String on_error) throws ErrorBox { if (mphandler.isFileParam("msg")) throw new ErrorBox(null,"Internal Error: message should be a normal param",on_error); return getMessageParameter(mphandler.getValue("msg"),topic,required,on_error); } // end getMessageParameter /*-------------------------------------------------------------------------------- * Overrideable operations *-------------------------------------------------------------------------------- */ protected String getMyLocation(HttpServletRequest request, VeniceEngine engine, UserContext user, RenderData rdat) { return (String)(request.getAttribute(LOCATION_ATTR)); } // end getMyLocation protected VeniceContent doVeniceGet(HttpServletRequest request, VeniceEngine engine, UserContext user, RenderData rdat) throws ServletException, IOException, VeniceServletResult { notSupported(request,"GET method not supported"); return null; } // end doVeniceGet protected VeniceContent doVenicePost(HttpServletRequest request, VeniceEngine engine, UserContext user, RenderData rdat) throws ServletException, IOException, VeniceServletResult { notSupported(request,"POST method not supported for normal form posts"); return null; } // end doVenicePost protected VeniceContent doVenicePost(HttpServletRequest request, ServletMultipartHandler mphandler, VeniceEngine engine, UserContext user, RenderData rdat) throws ServletException, IOException, VeniceServletResult { notSupported(request,"POST method not supported for multipart/form-data posts"); return null; } // end doVenicePost /*-------------------------------------------------------------------------------- * Overrides from class HttpServlet *-------------------------------------------------------------------------------- */ public final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext ctxt = getServletContext(); VeniceEngine engine = Variables.getVeniceEngine(ctxt); VeniceContent content = null; // Make all log messages for the request carry the remote address. NDC.push(request.getRemoteAddr()); try { // get the user context UserContext user = Variables.getUserContext(ctxt,request,request.getSession(true)); boolean record_uname = user.isLoggedIn(); if (record_uname) NDC.push(user.getUserName()); try { // and now we proceed! RenderData rdat = RenderConfig.createRenderData(ctxt,user,request,response); try { // run the actual "get" in the servlet content = doVeniceGet(request,engine,user,rdat); } // end try catch (VeniceServletResult res) { // special VeniceServletResult catch here - figure out what result it is if (res instanceof VeniceContent) content = (VeniceContent)res; // this is content else if (res instanceof ContentResult) { // this contains content ContentResult cres = (ContentResult)res; content = cres.getContent(); } // end else if else if (res instanceof ExecuteResult) { // direct-execution result ExecuteResult xres = (ExecuteResult)res; Variables.flushCookies(request,response); xres.execute(rdat); return; } // end else if else // unrecognized VeniceServletResult content = null; } // end catch catch (RuntimeException re) { // record that we caught a runtime exception in here! logger.error("VeniceServlet.doGet caught " + re.getClass().getName() + " in doVeniceGet",re); throw re; } // end catch Variables.flushCookies(request,response); if (content!=null) { // display the content! BaseJSPData base = new BaseJSPData(getMyLocation(request,engine,user,rdat),content); base.transfer(ctxt,rdat); } // end if else // there is no content - display the null response rdat.nullResponse(); } // end try finally { // pop the username from the NDC if we used it if (record_uname) NDC.pop(); } // end finally } // end try finally { // pop the nested diagnostic context NDC.pop(); } // end finally } // end doGet public final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext ctxt = getServletContext(); VeniceEngine engine = Variables.getVeniceEngine(ctxt); ServletMultipartHandler mphandler = null; VeniceContent content = null; // Make all log messages for the request carry the remote address. NDC.push(request.getRemoteAddr()); try { // get the user context UserContext user = Variables.getUserContext(ctxt,request,request.getSession(true)); boolean record_uname = user.isLoggedIn(); if (record_uname) NDC.push(user.getUserName()); try { // and now we proceed! RenderData rdat = RenderConfig.createRenderData(ctxt,user,request,response); if (ServletMultipartHandler.canHandle(request)) { // if this is a multipart/form-data request, invoke our special handler code try { // create the multipart handler mphandler = new ServletMultipartHandler(request); } // end try catch (ServletMultipartException e) { // this is an error message we need to generate and just bail out on logger.error("ServletMultipartException caught in doVenicePost!",e); BaseJSPData base = new BaseJSPData(getMyLocation(request,engine,user,rdat), new ErrorBox(null,"Internal Error: " + e.getMessage(),null)); base.transfer(ctxt,rdat); return; } // end if } // end if try { // call the appropriate doVenicePost method if (mphandler!=null) content = doVenicePost(request,mphandler,engine,user,rdat); else content = doVenicePost(request,engine,user,rdat); } // end try catch (VeniceServletResult res) { // special VeniceServletResult catch here - figure out what result it is if (res instanceof VeniceContent) content = (VeniceContent)res; // this is content else if (res instanceof ContentResult) { // this contains content ContentResult cres = (ContentResult)res; content = cres.getContent(); } // end else if else if (res instanceof ExecuteResult) { // direct-execution result ExecuteResult xres = (ExecuteResult)res; Variables.flushCookies(request,response); xres.execute(rdat); return; } // end else if else // unrecognized VeniceServletResult content = null; } // end catch catch (RuntimeException re) { // record that we caught a runtime exception in here! logger.error("VeniceServlet.doPost caught " + re.getClass().getName() + " in doVenicePost",re); throw re; } // end catch Variables.flushCookies(request,response); if (content!=null) { // display the content! BaseJSPData base = new BaseJSPData(getMyLocation(request,engine,user,rdat),content); base.transfer(ctxt,rdat); } // end if else // there is no content - display the null response rdat.nullResponse(); } // end try finally { // pop the username from the NDC if we used it if (record_uname) NDC.pop(); } // end finally } // end try finally { // pop the nested diagnostic context NDC.pop(); } // end finally } // end doPost } // end class VeniceServlet