/* * 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-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.ui.servlet; import java.awt.Dimension; import java.io.*; import java.lang.ref.*; import java.sql.Blob; import java.sql.SQLException; import java.text.DateFormat; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.log4j.*; import org.w3c.dom.*; import com.silverwrist.util.*; import com.silverwrist.venice.core.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.ui.*; import com.silverwrist.venice.ui.config.*; import com.silverwrist.venice.ui.dlg.Dialog; import com.silverwrist.venice.ui.helpers.*; import com.silverwrist.venice.ui.menus.CommunityMenu; import com.silverwrist.venice.ui.menus.Menu; import com.silverwrist.venice.ui.menus.MenuComponent; import com.silverwrist.venice.ui.script.*; import com.silverwrist.venice.util.XMLLoader; public class RequestImpl implements RequestInput { /*-------------------------------------------------------------------------------- * Internal class which implements the output. *-------------------------------------------------------------------------------- */ class OutputImpl implements RequestOutput { /*==================================================================== * Attributes *==================================================================== */ private Writer wr = null; /*==================================================================== * Constructor *==================================================================== */ OutputImpl() { // do nothing } // end constructor /*==================================================================== * Implementations from interface ServiceProvider *==================================================================== */ public Object queryService(Class klass) { if (klass==HTMLRendering.class) return RequestImpl.this.queryService(klass); throw new NoSuchServiceException("RequestOutput",klass); } // end queryService public Object queryService(Class klass, String serviceid) { return this.queryService(klass); } // end queryService /*==================================================================== * Implementations from interface RequestOutput *==================================================================== */ public Writer getWriter() throws IOException { if (wr==null) wr = response.getWriter(); return wr; } // end getWriter public void write(String s) throws IOException { if (wr==null) wr = response.getWriter(); wr.write(s); } // end write public void writeStackTrace(Throwable t) throws IOException { if (wr==null) wr = response.getWriter(); PrintWriter tmp; if (wr instanceof PrintWriter) tmp = (PrintWriter)wr; else tmp = new PrintWriter(wr); t.printStackTrace(tmp); if (!(wr instanceof PrintWriter)) tmp.flush(); } // end writeStackTrace public void flush() throws IOException { if (wr!=null) wr.flush(); response.flushBuffer(); } // end flush public void output(Content c) throws IOException, ServletException { if (c instanceof ContentDirect) { // render the content object here ContentDirect cd = (ContentDirect)c; if (wr!=null) { // attempt to flush the writer try { // flush the output wr.flush(); } // end try catch (IOException e) { // do nothing } // end catch } // end if response.flushBuffer(); // flush the previous stuff to disk cd.render(this); response.flushBuffer(); // flush the included page properly return; } // end if if (c instanceof ContentJSP) { // include the JSP page here ContentJSP cj = (ContentJSP)c; RequestDispatcher disp = ctxt.getRequestDispatcher(config.getFormatJSPPath(cj.getJSPName())); // Configure the request attributes. request.setAttribute(REQUEST_INPUT,(RequestInput)(RequestImpl.this)); request.setAttribute(REQUEST_OUTPUT,(RequestOutput)this); Object stack = request.getAttribute(REQUEST_CONTENT); request.setAttribute(REQUEST_CONTENT,c); // Configure the writer, if it's present. if (wr!=null) { // attempt to flush the writer try { // flush the output wr.flush(); } // end try catch (IOException e) { // do nothing } // end catch } // end if Writer wr_stack = wr; wr = null; cj.initialize(RequestImpl.this); try { // Include the content now! response.flushBuffer(); // flush the previous stuff to disk disp.include(request,response); // include the JSP if (wr!=null) wr.flush(); response.flushBuffer(); // flush the included page properly } // end try finally { // Clean up the stacked objects. cj.terminate(RequestImpl.this); wr = wr_stack; if (stack==null) request.removeAttribute(REQUEST_CONTENT); else request.setAttribute(REQUEST_CONTENT,stack); } // end finally return; } // end if // if nothing else... this.write(c.toString()); } // end output public void output(Writer out, Content c) throws IOException, ServletException { if (c instanceof ContentDirect) { // do a ContentDirect render, but replace the internal Writer with the specified one // before we do so ContentDirect cd = (ContentDirect)c; if (wr!=null) { // attempt to flush the writer try { // flush the output wr.flush(); } // end try catch (IOException e) { // do nothing } // end catch } // end if Writer wr_stack = wr; wr = out; try { // do the actual output cd.render(this); wr.flush(); } // end try finally { // restore the stacked stuff before we go wr = wr_stack; } // end finally return; } // end if this.output(c); // fall back in ContentJSP case } // end output public void writeFrameHead(Writer out, Content c) throws IOException { HTMLRendering html = (HTMLRendering)(RequestImpl.this.queryService(HTMLRendering.class)); out.write("\n" + config.getPageTitle(c.getPageTitle(this)) + "\n" + config.getBaseFontTag() + "\n"); if (config.usingStyleSheet()) out.write("\n"); String tmp = config.getPageIconTags(); if (tmp!=null) out.write(tmp); if (!(config.useSmartTags())) out.write("\n"); if (c instanceof ContentMetadata) { // look for additional metadata on the content ContentMetadata cm = (ContentMetadata)c; Map meta = cm.getMetadata(); if (meta==null) meta = Collections.EMPTY_MAP; Iterator it; for (it=meta.entrySet().iterator(); it.hasNext(); ) { // write the metadata Map.Entry ntry = (Map.Entry)(it.next()); out.write("\n"); } // end for meta = cm.getHTTPMetadata(); if (meta==null) meta = Collections.EMPTY_MAP; for (it=meta.entrySet().iterator(); it.hasNext(); ) { // write the metadata Map.Entry ntry = (Map.Entry)(it.next()); out.write("\n"); } // end for } // end if out.write("\n"); } // end writeFrameHead public void writeFrameHead(Content c) throws IOException { if (wr==null) wr = response.getWriter(); this.writeFrameHead(wr,c); } // end writeFrameHead public void writeSiteImageTag(Writer out) throws IOException { HTMLRendering html = (HTMLRendering)(RequestImpl.this.queryService(HTMLRendering.class)); String href = config.getSiteLogoLink(); if (href!=null) out.write(""); out.write(config.getSiteLogoImageTag()); if (href!=null) out.write(""); } // end writeSiteImageTag public void writeSiteImageTag() throws IOException { if (wr==null) wr = response.getWriter(); this.writeSiteImageTag(wr); } // end writeSiteImageTag public void writeVeniceLogo(Writer out) throws IOException { out.write(config.getVeniceLogoTag()); } // end writeVeniceLogo public void writeVeniceLogo() throws IOException { if (wr==null) wr = response.getWriter(); this.writeVeniceLogo(wr); } // end writeVeniceLogo public void writeContentHeader(Writer out, String primary, String secondary) throws IOException { out.write(config.getContentHeader(primary,secondary)); } // end writeContentHeader public void writeContentHeader(String primary, String secondary) throws IOException { if (wr==null) wr = response.getWriter(); wr.write(config.getContentHeader(primary,secondary)); } // end writeContentHeader } // end class OutputImpl /*-------------------------------------------------------------------------------- * Internal class which implements the execution output. *-------------------------------------------------------------------------------- */ class ExecImpl implements RequestExec { /*==================================================================== * Constructor *==================================================================== */ ExecImpl() { // do nothing } // end constructor /*==================================================================== * Implementations from interface RequestExec *==================================================================== */ public void error(int code) throws IOException { flushCookies(); if (logger.isDebugEnabled()) logger.debug("ExecImpl.error(): code " + code); response.sendError(code); } // end sendError public void error(int code, String message) throws IOException { flushCookies(); if (logger.isDebugEnabled()) logger.debug("ExecImpl.error(): code " + code + ", msg: " + message); if (message==null) response.sendError(code); else response.sendError(code,message); } // end sendError public void redirect(String where, int type) throws IOException { flushCookies(); String fmt_url; if (type==ABSOLUTE) fmt_url = where; else if (type==SERVLET) fmt_url = response.encodeRedirectURL(request.getContextPath() + "/" + where); else if (type==FRAME) fmt_url = response.encodeRedirectURL(request.getContextPath() + "/frame/" + where); else throw new IndexOutOfBoundsException("invalid format type index for redirect"); if (logger.isDebugEnabled()) logger.debug("ExecImpl.redirect(): going to \"" + fmt_url + "\""); response.sendRedirect(fmt_url); } // end redirect public void noContent() { flushCookies(); response.setStatus(HttpServletResponse.SC_NO_CONTENT); } // end noContent public void sendBinary(String type, String filename, int length, InputStream data) throws IOException { flushCookies(); if (logger.isDebugEnabled()) logger.debug("ExecImpl.sendBinary(): MIME " + type + ", filename \"" + filename + "\", length " + length); response.setContentType(type); response.setContentLength(length); addDynamicHeaders(); if (filename!=null) // make sure we pass the filename along, too response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\";"); // Copy the contents of the "data" stream to the output. IOUtil.copy(data,response.getOutputStream()); response.flushBuffer(); } // end sendBinary public void sendBinary(String type, int length, InputStream data) throws IOException { this.sendBinary(type,null,length,data); } // end sendBinary public void sendBinary(String type, String filename, Blob data) throws IOException, SQLException { this.sendBinary(type,filename,(int)(data.length()),data.getBinaryStream()); } // end sendBinary public void sendBinary(String type, Blob data) throws IOException, SQLException { this.sendBinary(type,null,(int)(data.length()),data.getBinaryStream()); } // end sendBinary public void sendBinary(String type, String filename, byte[] data) throws IOException { this.sendBinary(type,filename,data.length,new ByteArrayInputStream(data)); } // end sendBinary public void sendBinary(String type, byte[] data) throws IOException { this.sendBinary(type,null,data.length,new ByteArrayInputStream(data)); } // end sendBinary public void sendText(String type, String data) throws IOException { flushCookies(); if (logger.isDebugEnabled()) logger.debug("ExecImpl.sendText(): MIME " + type + ", length " + data.length()); response.setContentType(type); response.setContentLength(data.length()); addDynamicHeaders(); Writer wr = response.getWriter(); wr.write(data); wr.flush(); response.flushBuffer(); } // end sendText public void sendText(String type, char[] data) throws IOException { flushCookies(); if (logger.isDebugEnabled()) logger.debug("ExecImpl.sendText(): MIME " + type + ", length " + data.length); response.setContentType(type); response.setContentLength(data.length); addDynamicHeaders(); Writer wr = response.getWriter(); wr.write(data); wr.flush(); response.flushBuffer(); } // end sendText } // end class ExecImpl /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(RequestImpl.class); private static int s_serial_gen = 1; private static final String APP_ATTRIBUTE_STEM = "com.silverwrist.venice.ui.variables."; public static final String REQUEST_CONTENT = "com.silverwrist.venice.ui.Content"; public static final String REQUEST_INPUT = "com.silverwrist.venice.ui.RequestInput"; public static final String REQUEST_OUTPUT = "com.silverwrist.venice.ui.RequestOutput"; public static final String REQUEST_ATTRIBUTE_STEM = "com.silverwrist.venice.ui.variables."; /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private int m_serial; // serial number of this request private ServletContext ctxt; // the servlet context private HttpServletRequest request; // the servlet request data private HttpServletResponse response; // the servlet response data private VeniceUISession session; // the current HTTP session private VeniceEngine engine; // the Venice engine context private RootConfig config; // the UI configuration data private ServletMultipartHandler mphandler = null; // if this is a multipart/form-data POST private boolean end_response = true; // do we need to properly end the response? private Locale my_locale; // user's current locale private TimeZone my_timezone; // user's current time zone private String location; // current servlet location private boolean show_login = true; // do we show the login links? private ScriptManager script_mgr; // the script manager to use for executing script private CommunityContext community = null; // the current community private LinkedList auto_cleanup = null; // auto-cleanup callbacks private Document request_doc = null; // request parsed as an XML document private SessionControlImpl session_control = null; // session control interface private CookieControlImpl cookie_control = null; // cookie control interface private HTMLRenderingImpl html_rendering = null; // HTML rendering interface private ScriptSupportImpl script_support = null; // script support interface /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ RequestImpl(ServletContext ctxt, HttpServletRequest request, HttpServletResponse response, VeniceEngine engine, RootConfig config, VeniceUISessionFactory factory) throws ServletException, ValidationException { // Set up the basic variables. this.ctxt = ctxt; this.request = request; this.response = response; this.engine = engine; this.config = config; synchronized (RequestImpl.class) { // add serial number m_serial = s_serial_gen++; } // end synchronized block if (request.getMethod().equals("POST")) { // POSTs can have special handling for the request data if (request.getContentType().startsWith("text/xml")) { // this is some sort of XML-based request - parse it into a DOM tree XMLLoader loader = XMLLoader.get(); try { // load the document request_doc = loader.loadPostData(request.getInputStream()); // may throw ValidationException } // end try catch (IOException ioe) { // IO exception...sigh logger.error("IO error loading request document",ioe); throw new ServletException("IO error loading request document: " + ioe.toString(),ioe); } // end catch } // end if else if (ServletMultipartHandler.canHandle(request)) { // if this is a multipart/form-data POST, create the handler object try { // use the multipart handler and get something mphandler = new ServletMultipartHandler(request); } // end try catch (ServletMultipartException smpe) { // unable to parse POST data for some reason logger.error("Multipart data acquisition failed: " + smpe.getMessage(),smpe); throw new ValidationException("invalid multipart request: " + smpe.getMessage(),smpe); } // end catch } // end else if } // end if // Come up with a "first guess" at the location. StringBuffer loc_buf = new StringBuffer(request.getServletPath()); if (loc_buf.charAt(0)=='/') loc_buf.delete(0,1); String tmp = request.getPathInfo(); if (tmp!=null) loc_buf.append(tmp); tmp = request.getQueryString(); if (tmp!=null) loc_buf.append('?').append(tmp); location = loc_buf.toString(); // Retrieve a scripting engine. try { // get the script engine ScriptManagerContainer cnr = ScriptManagerContainer.get(ctxt); script_mgr = cnr.getScriptManager(); // push in the variables script_mgr.pushContext(); script_mgr.register("request",(RequestInput)this); script_mgr.register("engine",engine); } // end try catch (ScriptingException e) { // unable to load the scripting engine for some reason logger.error("Scripting engine get failed: " + e.getMessage(),e); throw new ServletException("Unable to retrieve scripting engine: " + e.getMessage(),e); } // end catch // Default the locale and time zone temporarily while we initialize the session. my_locale = Locale.getDefault(); my_timezone = TimeZone.getDefault(); // Create the UI session. We do this only after the script engine has been initialized // because HttpVeniceUISession now calls the script engine to launch session_init.js. session = factory.createSession(ctxt,request,response,engine,config); session.preprocess(this); if (!(session instanceof NullSession)) { // read the user's preferred locale try { // get the user default locale my_locale = session.getUser().getLocale(); } // end try catch (DataException de) { // locale problems... my_locale = Locale.getDefault(); } // end catch // read the user's preferred time zone try { // get the user default timezone my_timezone = session.getUser().getTimeZone(); } // end try catch (DataException de) { // time zone problems... my_timezone = TimeZone.getDefault(); } // end catch } // end if // else leave the locale and time zone where they are } // end constructor /*-------------------------------------------------------------------------------- * Internal operations *-------------------------------------------------------------------------------- */ private final void flushCookies() { if (cookie_control!=null) cookie_control.flushCookies(response); } // end flushCookies private final void addDynamicHeaders() { // these should prevent browsers and proxy servers from caching a dynamically-generated Venice page response.addHeader("Pragma","No-cache"); response.addHeader("Cache-Control","no-cache"); response.addDateHeader("Expires",1); } // end addDynamicHeaders private final void updateMenus(int selector) { MenuComponent oldmenu = (MenuComponent)(getSessionAttribute(LEFT_MENU_SESSION_ATTR)); MenuComponent newmenu = null; boolean change = false; switch (selector) { case Content.MENU_SELECTOR_TOP: if ((oldmenu!=null) && (oldmenu instanceof Menu)) { // check to see if the "top" menu is still in place Menu mu = (Menu)oldmenu; change = !(mu.getIdentifier().equals("top")); } // end if else // force change change = true; if (change) newmenu = config.getMenu("top"); break; case Content.MENU_SELECTOR_COMMUNITY: if (community!=null) { // this only makes sense if the community is properly set if ((oldmenu!=null) && (oldmenu instanceof CommunityMenu)) { // get the community menu and see if the CID has changed CommunityMenu cm = (CommunityMenu)(oldmenu); change = (cm.getID()!=community.getCommunityID()); } // end if else // force change change = true; if (change) newmenu = config.getCommunityMenu(community); } // end if else if (oldmenu==null) // set a reasonable default newmenu = config.getMenu("top"); break; default: if (oldmenu==null) // only set the menu if we don't have it already newmenu = config.getMenu("top"); break; } // end switch if (newmenu!=null) setSessionAttribute(LEFT_MENU_SESSION_ATTR,newmenu); } // end updateMenus private final void updateMenus(Content c) { updateMenus(c.getMenuSelector()); } // end updateMenus /*-------------------------------------------------------------------------------- * Operations called by other objects in this package *-------------------------------------------------------------------------------- */ final VeniceUISession getSession() { return session; } // end getSession final void setSession(VeniceUISession s) { session = s; } // end setSession final void endSession() { session.invalidate(); session = null; } // end endSession final boolean sessionBound() { return ((session!=null) && !(session instanceof NullSession)); } // end sessionBound final String encodeServletPath(String servlet) { return response.encodeURL(request.getContextPath() + "/" + servlet); } // end encodeServletPath final Locale getLocale() { return my_locale; } // end getLocale final TimeZone getTimeZone() { return my_timezone; } // end getTimeZone /** * Expands the pathname of the servlet into a fully-specified HTTP URL. For instance, * the servlet name "foobar" might be expanded into * "http://venice.example.org/venice/foobar". * * @param spath Servlet path to be expanded. * @param encode true to encode the servlet path first, false to not do so. * @return The fully-expanded servlet path. */ final String expandServletPath(String spath, boolean encode) { StringBuffer buf = new StringBuffer("http://"); buf.append(request.getServerName()); if (request.getServerPort()!=80) buf.append(':').append(request.getServerPort()); if (encode) buf.append(encodeServletPath(spath)); else buf.append(request.getContextPath()).append('/').append(spath); return buf.toString(); } // end expandServletPath /*-------------------------------------------------------------------------------- * Overrides from class Object *-------------------------------------------------------------------------------- */ public String toString() { StringBuffer buf = new StringBuffer("{RequestImpl #"); buf.append(m_serial).append("from [").append(request.getRemoteAddr()).append("] for "); buf.append(request.getServletPath()).append("}"); return buf.toString(); } // end toString /*-------------------------------------------------------------------------------- * Implementations from interface ServiceProvider *-------------------------------------------------------------------------------- */ /** * Queries this object for a specified service. * * @param klass The class of the object that should be returned as a service. * @return A service object. The service object is guaranteed to be of the class * specified by klass; that is, if queryService(klass) * yields some object x, then the expression klass.isInstance(x) * is true. * @exception com.silverwrist.venice.except.NoSuchServiceException If no service is available in * the specified class. */ public Object queryService(Class klass) { if (klass==ScriptManager.class) return script_mgr; if (klass==SessionControl.class) { // create session control and return it if (session_control==null) session_control = new SessionControlImpl(this); return session_control; } // end if if (klass==CookieControl.class) { // create cookie control and return it if (cookie_control==null) cookie_control = new CookieControlImpl(request); return cookie_control; } // end if if (klass==HTMLRendering.class) { // create HTML rendering object and return it if (html_rendering==null) html_rendering = new HTMLRenderingImpl(this,config); return html_rendering; } // end if if (klass==ScriptSupport.class) { // create script support object and return it if (script_support==null) script_support = new ScriptSupportImpl(this,config); return script_support; } // end if throw new NoSuchServiceException("RequestInput",klass); } // end queryService /** * Queries this object for a specified service. * * @param klass The class of the object that should be returned as a service. * @param serviceid ID for the service to be requested, to further discriminate between requests. * @return A service object. The service object is guaranteed to be of the class * specified by klass; that is, if queryService(klass) * yields some object x, then the expression klass.isInstance(x) * is true. * @exception com.silverwrist.venice.except.NoSuchServiceException If no service is available in * the specified class. */ public Object queryService(Class klass, String serviceid) { if ((klass==Document.class) && (serviceid!=null) && serviceid.equalsIgnoreCase("requestDocument")) return request_doc; return this.queryService(klass); } // end queryService /*-------------------------------------------------------------------------------- * Implementations from interface RequestInput *-------------------------------------------------------------------------------- */ /** * Returns a String containing the real path for a given virtual path. For example, * the virtual path "/index.html" has a real path of whatever file on the server's filesystem * would be served by a request for "/index.html".

* This method returns null if the virtual path cannot be translated to a real path for * any reason. * * @param s A String specifying a virtual path. * @return A String specifying the real path, or null if the translation cannot * be performed. */ public String mapPath(String s) { return ctxt.getRealPath(s); } // end mapPath /** * Returns the portion of the request URI that indicates the context of the request, i.e. the servlet * context under which Venice is installed. The context path always comes first in a request URI. The * path starts with a "/" character but does not end with a "/" character. * * @return A String specifying the portion of the request URI that indicates the context * of the request. */ public String getContextPath() { return request.getContextPath(); } // end getContextPath /** * Returns the part of this request's URI that calls the servlet. This includes either the servlet name * or a path to the servlet, but does not include any extra path information or a query string. * * @return A String containing the name or path of the servlet being called, as specified * in the request URI. */ public String getServletPath() { return request.getServletPath(); } // end getServletPath /** * Returns any extra path information associated with the URI the client sent when it made this request. * The extra path information follows the servlet path but precedes the query string. This method * returns null if there was no extra path information. In Venice, the path information is * used to specify parameters in certain servlets. * * @return A String specifying extra path information that comes after the servlet path * but before the query string in the request URI; or null if the URI does not * have any extra path information. */ public String getPathInfo() { return request.getPathInfo(); } // end getPathInfo /** * Returns the query string that is contained in the request URI after the path. This method returns * null if the URI does not have a query string. * * @return A String containing the query string or null if the URI contains * no query string. */ public String getQueryString() { return request.getQueryString(); } // end getQueryString /** * Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. * * @return A String specifying the name of the method with which this request was made. */ public String getVerb() { return request.getMethod(); } // end getVerb /** * Returns the Internet Protocol (IP) address of the client that sent the request. * * @return A String containing the IP address of the client that sent the request. */ public String getSourceAddress() { return request.getRemoteAddr(); } // end getSourceAddress /** * Returns true if the request parameter with the specified name is defined, * false if not. For standard Venice requests, parameters are contained in the * query string or posted form data. * * @param name Parameter name to be checked. * @return See above. */ public boolean hasParameter(String name) { if (request_doc!=null) return false; if (mphandler!=null) return mphandler.hasParameter(name); else return (request.getParameter(name)!=null); } // end hasParameter /** * Returns the value of a request parameter as a String, or null if the * parameter does not exist. For standard Venice requests, parameters are contained in the query * string or posted form data.

* You should only use this method when you are sure the parameter has only one value. If the parameter * might have more than one value, use {@link #getParameterValues(java.lang.String)}.

* If you use this method with a multivalued parameter, the value returned is equal to the first value * in the array returned by getParameterValues. * * @param name A String specifying the name of the parameter. * @return A String representing the single value of the parameter. * @see #getParameterValues(java.lang.String) */ public String getParameter(String name) { if (request_doc!=null) return null; if (mphandler!=null) return mphandler.getValue(name); else return request.getParameter(name); } // end getParameter /** * Returns the value of a request parameter as a int, or a specified default value if * the parameter does not exist. For standard Venice requests, parameters are contained in the query * string or posted form data.

* If you use this method with a multivalued parameter, the value returned is equal to the * int equivalent of the first value in the array returned by getParameterValues. * * @param name A String specifying the name of the parameter. * @param default_value The default value to use for the parameter if the specified parameter does not exist. * @return An int representing the single value of the parameter. */ public int getParameterInt(String name, int default_value) { String s = this.getParameter(name); if (s==null) return default_value; try { // turn the parameter into an integer return Integer.parseInt(s); } // end try catch (NumberFormatException nfe) { // on conversion error, just return the default return default_value; } // end catch } // end getParameterInt /** * Returns the value of a request parameter as a short, or a specified default value if * the parameter does not exist. For standard Venice requests, parameters are contained in the query * string or posted form data.

* If you use this method with a multivalued parameter, the value returned is equal to the * short equivalent of the first value in the array returned by getParameterValues. * * @param name A String specifying the name of the parameter. * @param default_value The default value to use for the parameter if the specified parameter does not exist. * @return A short representing the single value of the parameter. */ public short getParameterShort(String name, short default_value) { String s = this.getParameter(name); if (s==null) return default_value; try { // turn the parameter into a short return Short.parseShort(s); } // end try catch (NumberFormatException nfe) { // on conversion error, just return the default return default_value; } // end catch } // end getParameterShort /** * Returns the value of a request parameter as a long, or a specified default value if * the parameter does not exist. For standard Venice requests, parameters are contained in the query * string or posted form data.

* If you use this method with a multivalued parameter, the value returned is equal to the * long equivalent of the first value in the array returned by getParameterValues. * * @param name A String specifying the name of the parameter. * @param default_value The default value to use for the parameter if the specified parameter does not exist. * @return A long representing the single value of the parameter. */ public long getParameterLong(String name, long default_value) { String s = this.getParameter(name); if (s==null) return default_value; try { // turn the parameter into a long return Long.parseLong(s); } // end try catch (NumberFormatException nfe) { // on conversion error, just return the default return default_value; } // end catch } // end getParameterLong /** * Returns an Enumeration of String objects containing the names of the * parameters contained in this request. If the request has no parameters, the method returns an empty * Enumeration. * * @return An Enumeration of String objects, each String * containing the name of a request parameter, or an empty Enumeration if the * request has no parameters. */ public Enumeration getParameterNames() { if (request_doc!=null) return Collections.enumeration(Collections.EMPTY_LIST); if (mphandler!=null) return mphandler.getNames(); else return request.getParameterNames(); } // end getParameterNames /** * Returns an array of String objects containing all of the values the given request * parameter has, or null if the parameter does not exist.

* If the parameter has a single value, the array has a length of 1. * * @param name A String containing the name of the parameter whose value is requested. * @return An array of String objects containing the parameter's values. * @see #getParameter(java.lang.String) */ public String[] getParameterValues(String name) { if (request_doc!=null) return new String[0]; if (mphandler!=null) return mphandler.getParamValues(name); else return request.getParameterValues(name); } // end getParameterValues /** * Returns true if the specified parameter is a file parameter, false if * not. If the parameter does not exist, the return value is false. * * @param name A String containing the name of the parameter to test. * @return See above. */ public boolean isFileParam(String name) { if (request_doc!=null) return false; if (mphandler!=null) return mphandler.isFileParam(name); else return false; } // end isFileParam /** * Returns the MIME type of the specified parameter. If the type cannot be determined, the return * value is null.

* N.B.: For non-file parameters, or all parameters to a request that is not a file upload, the MIME * type is "text/plain". * * @param name A String containing the name of the parameter to test. * @return See above. */ public String getParameterType(String name) { if (request_doc!=null) return null; if (mphandler!=null) return mphandler.getContentType(name); else if (request.getParameter(name)!=null) return "text/plain"; else return null; } // end getParameterType /** * Returns the size in bytes of the specified parameter. If the size cannot be determined, the return * value is -1.

* N.B.: For non-file parameters, or all parameters to a request that is not a file upload, the size * is the number of bytes occupied by the parameter, expressed in UTF-8 encoding. * * @param name A String containing the name of the parameter to test. * @return See above. */ public int getParameterSize(String name) { if (request_doc!=null) return -1; if (mphandler!=null) return mphandler.getContentSize(name); else { // just fake a return value String blort = request.getParameter(name); if (blort==null) return -1; try { // convert to bytes, return length return blort.getBytes("UTF-8").length; } // end try catch (UnsupportedEncodingException e) { // this sucks...this shouldn't happen return -1; } // end catch } // end else } // end getParameterSize /** * Returns an InputStream reading from the data of the named file parameter. If the * named parameter does not exist or is not a file parameter, returns null; * * @param name A String containing the name of the parameter whose value is requested. * @return See above. * @exception com.silverwrist.util.ServletMultipartException If there is a problem retrieving * the parameter data stream. */ public InputStream getParameterDataStream(String name) throws ServletMultipartException { if (mphandler!=null) return mphandler.getFileContentStream(name); else // ServletMultipartHandler will return null if parameter is not a file parameter return null; } // end getParameterDataStream /** * Returns true if the parameter set reflects the clicking of an image button with a * specified name, false if not. * * @param name A String containing the name of the image button to test. * @return See above. */ public boolean isImageButtonClicked(String name) { return this.hasParameter(name + ".x"); } // end isImageButtonClicked /** * Returns the application-level attribute with the given name, or null if there is no * attribute by that name. * * @param name A String specifying the name of the attribute. * @return An Object containing the value of the attribute, or null if no * attribute exists matching the given name. */ public Object getAppAttribute(String name) { return getAppAttribute(ctxt,name); } // end getAppAttribute /** * Sets the application-level attribute with the given name. * * @param name A String specifying the name of the attribute. * @param o The object to be bound as the value of that attribute, or null if the binding * is to be removed. */ public void setAppAttribute(String name, Object o) { setAppAttribute(ctxt,name,o); } // end setAppAttribute /** * Returns the session-level attribute with the given name, or null if there is no * attribute by that name. * * @param name A String specifying the name of the attribute. * @return An Object containing the value of the attribute, or null if no * attribute exists matching the given name. */ public Object getSessionAttribute(String name) { return session.getAttribute(name); } // end getSessionAttribute /** * Sets the session-level attribute with the given name. * * @param name A String specifying the name of the attribute. * @param o The object to be bound as the value of that attribute, or null if the binding * is to be removed. */ public void setSessionAttribute(String name, Object o) { if (o==null) session.removeAttribute(name); else session.setAttribute(name,o); } // end setSessionAttribute /** * Returns the request-level attribute with the given name, or null if there is no * attribute by that name. * * @param name A String specifying the name of the attribute. * @return An Object containing the value of the attribute, or null if no * attribute exists matching the given name. */ public Object getRequestAttribute(String name) { return getRequestAttribute(request,name); } // end getRequestAttribute /** * Sets the request-level attribute with the given name. * * @param name A String specifying the name of the attribute. * @param o The object to be bound as the value of that attribute, or null if the binding * is to be removed. */ public void setRequestAttribute(String name, Object o) { setRequestAttribute(request,name,o); } // end setRequestAttribute /** * Returns the instance of the Venice engine associated with the application. * * @return See above. */ public VeniceEngine getEngine() { return engine; } // end getEngine /** * Returns the instance of the Venice user object associated with the session. * * @return See above. */ public UserContext getUser() { return session.getUser(); } // end getUser /** * Returns the current servlet location. * * @return The current servlet location. */ public String getLocation() { return location; } // end getLocation /** * Sets the "current" servlet location that is displayed. This is used, for instance, * as the context to return to after a login. * * @param str The new location to be set. */ public void setLocation(String str) { location = str; } // end setLocation /** * Returns true if the "Log In" link is to be displayed on the outer frame, * false if not. * * @return See above. */ public boolean getDisplayLogin() { return show_login; } // end getDisplayLogin public void setDisplayLogin(boolean val) { show_login = val; } // end setDisplayLogin public MenuComponent getMenu(String name) { return config.getMenu(name); } // end getMenu public MenuComponent getMenu(String name, Map vars) { return config.getMenu(name,vars); } // end getMenu public Dialog getDialog(String name) { return config.getDialog(name); } // end getDialog public Content[] getSideBoxes() throws AccessError, DataException { UserContext user = session.getUser(); SideBoxManager sbmgr = config.getSideBoxManager(); List descrs = user.getSideBoxList(); Content[] rc = new Content[descrs.size()]; for (int i=0; i0) { // pop items off and clean them up AutoCleanup ac = (AutoCleanup)(auto_cleanup.removeFirst()); ac.cleanup(); } // end while and if // blow a bunch of our object fields to hell (this might make garbage collection easier) session_control = null; cookie_control = null; html_rendering = null; script_support = null; auto_cleanup = null; community = null; my_locale = null; my_timezone = null; mphandler = null; request = null; response = null; session = null; // release the script manager script_mgr.popContext(); ScriptManagerContainer cnr = ScriptManagerContainer.get(ctxt); cnr.releaseScriptManager(script_mgr); script_mgr = null; } // end end } // end class RequestImpl class SessionControlImpl implements SessionControl { /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private RequestImpl req; // request we're tied to private LinkedList session_stack = null; // session stack /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ SessionControlImpl(RequestImpl req) { this.req = req; } // end constructor /*-------------------------------------------------------------------------------- * Implementations from interface SessionControl *-------------------------------------------------------------------------------- */ public void endSession() { req.endSession(); } // end endSession public void pushSession(VeniceUISession sess) { if (session_stack==null) session_stack = new LinkedList(); session_stack.addFirst(req.getSession()); req.setSession(sess); } // end pushSession public void popSession() { if ((session_stack!=null) && (session_stack.size()>0)) req.setSession((VeniceUISession)(session_stack.removeFirst())); } // end popSession public void replaceUser(UserContext new_user) { req.getSession().setUser(new_user); } // end replaceUser } // end class SessionControlImpl class CookieControlImpl implements CookieControl { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(CookieControlImpl.class); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private HttpServletRequest httpreq; // HTTP request object private HashMap old_cookies = null; // cookies from the request private HashMap new_cookies = null; // cookies to be added to the response /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ CookieControlImpl(HttpServletRequest httpreq) { this.httpreq = httpreq; } // end constructor /*-------------------------------------------------------------------------------- * Internal operations *-------------------------------------------------------------------------------- */ private final void loadCookies() { if (old_cookies==null) { // load the cookies into a HashMap old_cookies = new HashMap(); Cookie[] raw_list = httpreq.getCookies(); if (raw_list!=null) for (int i=0; itrue if a cookie by this name is present, false if not. */ public boolean isCookiePresent(String name) { loadCookies(); return old_cookies.containsKey(name); } // end isCookiePresent /** * Returns the value of a particular request cookie. * * @param name Name of the cookie to retrieve the value of. * @return The value of that cookie, or null if the cookie is not present. */ public String getCookie(String name) { loadCookies(); Cookie tmp = (Cookie)(old_cookies.get(name)); return ((tmp==null) ? null : tmp.getValue()); } // end getCookie /** * Returns a set containing all the cookie names associated with this request. * * @return See above. */ public Set getCookieNames() { loadCookies(); if (old_cookies.isEmpty()) return Collections.EMPTY_SET; else return Collections.unmodifiableSet(old_cookies.keySet()); } // end getCookieNames /** * Adds a new persistent cookie to the application. The cookie will be stored by the * browser's persistent storage facility.

* Cookies should be used sparingly, to avoid possible privacy concerns. * * @param name Name of the cookie to be set. * @param value Value of the cookie to be set. * @param max_age The maximum lifespan of the persistent cookie, in seconds. */ public void savePersistentCookie(String name, String value, int max_age) { Cookie c = new Cookie(name,value); c.setMaxAge(Math.max(max_age,1)); c.setPath(httpreq.getContextPath()); putCookie(c); } // end savePersistentCookie /** * Adds a new temporary cookie to the application. The cookie will be stored in the * browser's memory only, and will disappear when the browser is closed. * Cookies should be used sparingly, to avoid possible privacy concerns. * * @param name Name of the cookie to be set. * @param value Value of the cookie to be set. */ public void saveTemporaryCookie(String name, String value) { Cookie c = new Cookie(name,value); c.setMaxAge(-1); c.setPath(httpreq.getContextPath()); putCookie(c); } // end saveTemporaryCookie /** * Deletes a cookie (either persistent or temporary) from the application. The cookie * will be erased from the browser. * * @param name Name of the cookie to remove. */ public void deleteCookie(String name) { Cookie c = new Cookie(name,""); c.setMaxAge(0); c.setPath(httpreq.getContextPath()); putCookie(c); } // end deleteCookie /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ /** * Takes all cookies that have been set on the current request and writes them to the * HTTP output. * * @param response HTTP response to receive all the cookies. */ final void flushCookies(HttpServletResponse response) { if (new_cookies==null) return; // no-op if (logger.isDebugEnabled()) logger.debug("flushCookies(): " + new_cookies.size() + " cookie(s) to output"); // loop over the cookies and add them to the response Iterator it = new_cookies.values().iterator(); while (it.hasNext()) { // add cookies to the response Cookie c = (Cookie)(it.next()); response.addCookie(c); } // end while new_cookies = null; } // end flushCookies } // end class CookieControlImpl class HTMLRenderingImpl implements HTMLRendering { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(HTMLRenderingImpl.class); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private RequestImpl req; // request we're attached to private RootConfig config; // configuration data private DateFormat display_date = null; // format to use for displaying dates private DateFormat activity_time = null; // format to use for activity string times /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ HTMLRenderingImpl(RequestImpl req, RootConfig config) { this.req = req; this.config = config; } // end constructor /*-------------------------------------------------------------------------------- * Implementations from interface HTMLRendering *-------------------------------------------------------------------------------- */ public String getColor(int selector) { return config.getColor(selector); } // end getColor public String getColor(String name) { return config.getColor(name); } // end getColor public boolean useHTMLComments() { return config.useHTMLComments(); } // end useHTMLComments public String formatURL(String url, int type) { if (type==ABSOLUTE) return url; else if (type==SERVLET) return req.encodeServletPath(url); else if (type==FRAME) return req.encodeServletPath("frame/" + url); else if (type==FULLSERVLET) return req.expandServletPath(url,true); else throw new IndexOutOfBoundsException("invalid format type index for formatURL"); } // end formatURL public String formatDate(Date date) { synchronized (this) { // create the display date formatter if we don't yet have it if (display_date==null) { // create the display date formatter display_date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM,req.getLocale()); display_date.setTimeZone(req.getTimeZone()); } // end if } // end synchronized block return display_date.format(date); } // end formatDate public String getFontTag(int colorsel, int size) { return config.getFontTag(colorsel,size); } // end getFontTag public String getFontTag(String color, int size) { return config.getFontTag(color,size); } // end getFontTag public String getFontTag(int colorsel, String size) { return config.getFontTag(colorsel,size); } // end getFontTag public String getFontTag(String color, String size) { return config.getFontTag(color,size); } // end getFontTag public int convertLinkType(String str) { return config.convertLinkType(str); } // end convertLinkType public String getStockMessage(String key) { return config.getStockMessage(key); } // end getStockMessage public String getStockMessage(String key, Map vars) { return config.getStockMessage(key,vars); } // end getStockMessage public String getStaticPath(String s) { return config.getStaticPath(s); } // end getStaticPath public String getExternalStaticPath(String s) { return config.getExternalStaticPath(s); } // end getExternalStaticPath public String getImagePath(String s) { return config.getImagePath(s); } // end getImagePath public String getButtonVisual(String id) { return config.getButtonVisual(id); } // end getButtonVisual public String getButtonInput(String id) { return config.getButtonInput(id); } // end getButtonInput public String getUserPhotoTag(String url) { return getUserPhotoTag(url,req.getEngine().getUserPhotoSize()); } // end getUserPhotoTag public String getUserPhotoTag(String url, Dimension size) { StringBuffer buf = new StringBuffer("\"\""); return buf.toString(); } // end getUserPhotoTag public String getActivityString(Date date) { if (date==null) return "Never"; // safeguard // Set up the two calendars we'll use for comparison. Calendar c_last = new GregorianCalendar(req.getTimeZone(),req.getLocale()); c_last.setTime(date); Calendar c_now = new GregorianCalendar(req.getTimeZone(),req.getLocale()); // Determine the exact number of days in the delta. int delta_days = 0; while ( (c_last.get(Calendar.YEAR)!=c_now.get(Calendar.YEAR)) || (c_last.get(Calendar.DAY_OF_YEAR)!=c_now.get(Calendar.DAY_OF_YEAR))) { // advance until we're pointing at the same year and the same day of the year delta_days++; c_last.add(Calendar.DAY_OF_YEAR,1); } // end while // For today or yesterday, we want to paste the time in as well. String s = null; if (delta_days<=1) { // set up to convert the time into a string if (activity_time==null) { // get the "activity" time formatter activity_time = DateFormat.getTimeInstance(DateFormat.MEDIUM,req.getLocale()); activity_time.setTimeZone(req.getTimeZone()); } // end if s = activity_time.format(date); } // end if // Return the actual activity string. if (delta_days==0) return "Today, " + s; else if (delta_days==1) return "Yesterday, " + s; else return String.valueOf(delta_days) + " days ago"; } // end getActivityString public String getCommunityLogoTag(String url) { StringBuffer buf = new StringBuffer("\"\""); return buf.toString(); } // end getCommunityLogoTag public String expandServletPath(String spath) { return req.expandServletPath(spath,false); } // end expandServletPath } // end class HTMLRenderingImpl class ScriptSupportImpl implements ScriptSupport { /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private RequestImpl req; // request we're attached to private RootConfig config; // configuration data /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ ScriptSupportImpl(RequestImpl req, RootConfig config) { this.req = req; this.config = config; } // end constructor /*-------------------------------------------------------------------------------- * Internal operations *-------------------------------------------------------------------------------- */ private static final String createLoggerName(String prefix, String raw_name) { // Strip all extensions from the end of the file. int limit = raw_name.lastIndexOf('/'); int x = raw_name.lastIndexOf('.'); while (x>limit) { // remove all extensions from the end raw_name = raw_name.substring(0,x); x = raw_name.lastIndexOf('.'); } // end while // convert the name to a logger name StringBuffer rc = new StringBuffer(prefix); for (x=0; xlimit) script = script.substring(0,x); } // end if return config.getScriptPath(script); } // end getScriptName public String getScriptLoggerName(String raw_name) { return createLoggerName("SCRIPT.",raw_name); } // end getScriptLoggerName public String getScriptLoggerName() { String script = req.getServletPath(); if (script.charAt(0)=='/') script = script.substring(1); return this.getScriptLoggerName(script); } // end getScriptLoggerName public String getRPCScriptName(String raw_name) { return config.getRPCScriptPath(raw_name); } // end getScriptName public String getRPCScriptLoggerName(String raw_name) { return createLoggerName("RPCSCRIPT.",raw_name); } // end getScriptLoggerName } // end class ScriptSupportImpl