the first implementation of an XML-RPC server endpoint within Venice...

also tweaked the session code to allow session types other than standard HTTP
cookie-based sessions.  The XML-RPC code doesn't do anything interesting yet.
This commit is contained in:
Eric J. Bowersox 2002-01-13 09:12:51 +00:00
parent bcd76541ab
commit 6ea41dc619
22 changed files with 2238 additions and 131 deletions

View File

@ -271,6 +271,17 @@
</remap> </remap>
</remapper> </remapper>
<!-- Configuration for the RPC interfaces. -->
<rpc>
<xmlrpc-methods>
<method name="venice:test\.sumDifference">
<object class="com.silverwrist.venice.ui.rpc.XmlRpcTestHandler"/>
<env name="e1" value="foo"/>
<env name="p1" value="${param.0}"/>
</method>
</xmlrpc-methods>
</rpc>
<!-- Contains standard messages displayed by front end --> <!-- Contains standard messages displayed by front end -->
<messages> <messages>
<!-- The message displayed at the top of "top" when you're not logged in (HTML). --> <!-- The message displayed at the top of "top" when you're not logged in (HTML). -->

View File

@ -119,6 +119,12 @@
<servlet-class>com.silverwrist.venice.ui.servlet.RemapperServlet</servlet-class> <servlet-class>com.silverwrist.venice.ui.servlet.RemapperServlet</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>XmlRpc</servlet-name>
<description>Handles XML-RPC calls for the application.</description>
<servlet-class>com.silverwrist.venice.ui.rpc.XmlRpcServlet</servlet-class>
</servlet>
<!-- Servlet mappings --> <!-- Servlet mappings -->
<servlet-mapping> <servlet-mapping>
@ -182,6 +188,11 @@
<url-pattern>/verifyemail</url-pattern> <url-pattern>/verifyemail</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>XmlRpc</servlet-name>
<url-pattern>/RPC2</url-pattern>
</servlet-mapping>
<!-- Global parameters for the HTTP session --> <!-- Global parameters for the HTTP session -->
<session-config> <session-config>
<session-timeout>60</session-timeout> <!-- 1 hour --> <session-timeout>60</session-timeout> <!-- 1 hour -->

1
lib/.gitignore vendored
View File

@ -1,5 +1,6 @@
bsf.jar bsf.jar
jacl.jar jacl.jar
jakarta-regexp*.jar
js.jar js.jar
log4j.jar log4j.jar
mysql.jar mysql.jar

View File

@ -6,6 +6,7 @@ compatible with the versions specified here.
Library Version File Name(s) Install To Library Version File Name(s) Install To
------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------
Apache Jakarta Regexp 1.2 jakarta-regexp-1.2.jar Venice "lib" subdirectory
Apache LOG4J 1.1.3 log4j.jar Venice "lib" subdirectory Apache LOG4J 1.1.3 log4j.jar Venice "lib" subdirectory
Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory
Jacl (Tcl interpreter) 1.3(CVS) jacl.jar, tcljava.jar Venice "lib" subdirectory Jacl (Tcl interpreter) 1.3(CVS) jacl.jar, tcljava.jar Venice "lib" subdirectory

View File

@ -31,8 +31,7 @@ if (user.isLoggedIn())
{ // user is logged in - we want to log out { // user is logged in - we want to log out
// TODO: only remove the login cookie if it was actually set! // TODO: only remove the login cookie if it was actually set!
rinput.deleteCookie(RequestInput.LOGIN_COOKIE); // remove the login cookie rinput.deleteCookie(RequestInput.LOGIN_COOKIE); // remove the login cookie
rinput.replaceUser(null); // no more user context rinput.endSession();
rinput.setSessionAttribute(RequestInput.LEFT_MENU_SESSION_ATTR,null); // and clear menus too
target = "top.js.vs"; // take 'em back to the top target = "top.js.vs"; // take 'em back to the top

View File

@ -0,0 +1,164 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.ui.config.RootConfig;
public class NullSession implements VeniceUISession, VeniceUISessionFactory
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static NullSession self = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
private NullSession()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private final void bogus()
{
throw new IllegalStateException("null session is not valid");
} // end bogus
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceUISession
*--------------------------------------------------------------------------------
*/
public long getCreationTime()
{
bogus();
return 0;
} // end getCreationTime
public String getID()
{
return null;
} // end getID
public long getLastAccessedTime()
{
return 0;
} // end getLastAccessedTime
public void setMaxInactiveInterval(int interval)
{ // do nothing
} // end setMaxInactiveInterval
public int getMaxInactiveInterval()
{
return -1;
} // end getMaxInactiveInterval
public Object getAttribute(String name)
{
bogus();
return null;
} // end getAttribute
public Enumeration getAttributeNames()
{
bogus();
return null;
} // end getAttributeNames
public void setAttribute(String name, Object o)
{
bogus();
} // end setAttribute
public void removeAttribute(String name)
{
bogus();
} // end removeAttribute
public void invalidate()
{
bogus();
} // end invalidate
public UserContext getUser()
{
bogus();
return null;
} // end getUser
public void setUser(UserContext user)
{
bogus();
} // end setUser
public void preprocess(RequestInput ri)
{ // do nothing
} // end preprocess
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceUISessionFactory
*--------------------------------------------------------------------------------
*/
public VeniceUISession createSession(ServletContext ctxt, HttpServletRequest request,
HttpServletResponse response, VeniceEngine engine,
RootConfig config)
{
return this;
} // end createSession
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static final synchronized NullSession get()
{
if (self==null)
self = new NullSession();
return self;
} // end get
} // end class NullSession

View File

@ -11,7 +11,7 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
*/ */
@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import org.w3c.dom.Document;
import com.silverwrist.util.ServletMultipartException; import com.silverwrist.util.ServletMultipartException;
import com.silverwrist.venice.core.CommunityContext; import com.silverwrist.venice.core.CommunityContext;
import com.silverwrist.venice.core.UserContext; import com.silverwrist.venice.core.UserContext;
@ -53,6 +54,8 @@ public interface RequestInput extends LinkTypes
public abstract String getSourceAddress(); public abstract String getSourceAddress();
public abstract void endSession();
public abstract boolean hasParameter(String name); public abstract boolean hasParameter(String name);
public abstract String getParameter(String name); public abstract String getParameter(String name);
@ -75,6 +78,10 @@ public interface RequestInput extends LinkTypes
public abstract InputStream getParameterDataStream(String name) throws ServletMultipartException; public abstract InputStream getParameterDataStream(String name) throws ServletMultipartException;
public abstract Document getRequestDocument();
public abstract boolean sessionBound();
public abstract boolean isImageButtonClicked(String name); public abstract boolean isImageButtonClicked(String name);
public abstract Object getAppAttribute(String name); public abstract Object getAppAttribute(String name);

View File

@ -0,0 +1,51 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui;
import java.util.*;
import com.silverwrist.venice.core.*;
public interface VeniceUISession
{
public abstract long getCreationTime();
public abstract String getID();
public abstract long getLastAccessedTime();
public abstract void setMaxInactiveInterval(int interval);
public abstract int getMaxInactiveInterval();
public abstract Object getAttribute(String name);
public abstract Enumeration getAttributeNames();
public abstract void setAttribute(String name, Object o);
public abstract void removeAttribute(String name);
public abstract void invalidate();
public abstract UserContext getUser();
public abstract void setUser(UserContext user);
public abstract void preprocess(RequestInput ri);
} // end class VeniceUISession

View File

@ -0,0 +1,31 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.core.VeniceEngine;
import com.silverwrist.venice.ui.config.RootConfig;
public interface VeniceUISessionFactory
{
public abstract VeniceUISession createSession(ServletContext ctxt, HttpServletRequest request,
HttpServletResponse response, VeniceEngine engine,
RootConfig config) throws ServletException;
} // end interface VeniceUISessionFactory

View File

@ -11,7 +11,7 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
*/ */
@ -30,6 +30,7 @@ import com.silverwrist.venice.ui.menus.CommunityMenu;
import com.silverwrist.venice.ui.menus.CommunityMenuFactory; import com.silverwrist.venice.ui.menus.CommunityMenuFactory;
import com.silverwrist.venice.ui.menus.Menu; import com.silverwrist.venice.ui.menus.Menu;
import com.silverwrist.venice.ui.menus.MenuComponent; import com.silverwrist.venice.ui.menus.MenuComponent;
import com.silverwrist.venice.ui.rpc.XmlRpcMethod;
import com.silverwrist.venice.util.*; import com.silverwrist.venice.util.*;
public class RootConfig implements LinkTypes, ColorSelectors public class RootConfig implements LinkTypes, ColorSelectors
@ -79,6 +80,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
private ButtonHolder buttons; // the button definitions private ButtonHolder buttons; // the button definitions
private String[] content_hdr; // the content header parts private String[] content_hdr; // the content header parts
private Remapper remapper; // the URL remapper private Remapper remapper; // the URL remapper
private List xmlrpc_methods; // the list of XML-RPC methods
private StockMessages stock_messages; // the stock messages private StockMessages stock_messages; // the stock messages
private Map menus; // the menus private Map menus; // the menus
private DialogManager dialogs; // the dialog manager private DialogManager dialogs; // the dialog manager
@ -324,7 +326,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
for (i=0; i<nl.getLength(); i++) for (i=0; i<nl.getLength(); i++)
{ // loop through the subelements { // loop through the subelements
Node n = nl.item(i); Node n = nl.item(i);
if ((n.getNodeType()==Node.ELEMENT_NODE)) if (n.getNodeType()==Node.ELEMENT_NODE)
{ // retrieve the font size and add it to our map { // retrieve the font size and add it to our map
DOMElementHelper h = new DOMElementHelper((Element)n); DOMElementHelper h = new DOMElementHelper((Element)n);
tmap.put(n.getNodeName(),h.getElementText()); tmap.put(n.getNodeName(),h.getElementText());
@ -367,6 +369,35 @@ public class RootConfig implements LinkTypes, ColorSelectors
// Initialize the remapper object. // Initialize the remapper object.
remapper = new Remapper(sect,this); remapper = new Remapper(sect,this);
// Get the <rpc/> section.
sect = loader.configGetSubSection(root_h,"rpc");
sect_h = new DOMElementHelper(sect);
// Get the <xmlrpc-methods/> section.
sect1 = loader.configGetSubSection(sect_h,"xmlrpc-methods");
nl = sect1.getChildNodes();
ArrayList tmp_alist = new ArrayList();
for (i=0; i<nl.getLength(); i++)
{ // look for methods
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // look for a <method/> element and use it to initialize a method
if (n.getNodeName().equals("method"))
tmp_alist.add(new XmlRpcMethod((Element)n));
} // end if
} // end for
if (tmp_alist.isEmpty())
xmlrpc_methods = Collections.EMPTY_LIST;
else
{ // save off the methods list
tmp_alist.trimToSize();
xmlrpc_methods = Collections.unmodifiableList(tmp_alist);
} // end else
// Get the <messages/> section. // Get the <messages/> section.
sect = loader.configGetSubSection(root_h,"messages"); sect = loader.configGetSubSection(root_h,"messages");
@ -718,6 +749,12 @@ public class RootConfig implements LinkTypes, ColorSelectors
} // end getDefaultServletAddress } // end getDefaultServletAddress
public final List getXmlRpcMethods()
{
return xmlrpc_methods;
} // end getXmlRpcMethods
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Static initializer * Static initializer
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------

View File

@ -0,0 +1,28 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.util.Map;
import com.silverwrist.venice.ui.RequestInput;
public interface XmlRpcDispatch
{
public abstract Object dispatch(RequestInput req, XmlRpcRequest xreq, Map environment)
throws Exception, XmlRpcFault;
} // end interface XmlRpcDispatch

View File

@ -0,0 +1,123 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.io.IOException;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.helpers.ThrowableContent;
public class XmlRpcFault extends ThrowableContent implements ContentExecute
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Some "standard" XML-RPC error codes.
public static final int INVALID_REQUEST = -32600;
public static final int METHOD_NOT_FOUND = -32601;
public static final int INVALID_PARAMS = -32602;
public static final int INTERNAL_ERROR = -32603;
public static final int APPLICATION_ERROR = -32500;
public static final int SERVER_ERROR = -32400;
public static final int TRANSPORT_ERROR = -32300;
public static final int DEFAULT_ERROR = 0;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private int fault_code = DEFAULT_ERROR;
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public XmlRpcFault(String msg)
{
super(msg);
} // end constructor
public XmlRpcFault(int code, String msg)
{
super(msg);
fault_code = code;
} // end constructor
public XmlRpcFault(Throwable t)
{
super(t);
} // end constructor
public XmlRpcFault(int code, Throwable t)
{
super(t);
fault_code = code;
} // end constructor
public XmlRpcFault(String msg, Throwable t)
{
super(msg,t);
} // end constructor
public XmlRpcFault(int code, String msg, Throwable t)
{
super(msg,t);
fault_code = code;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface ContentExecute
*--------------------------------------------------------------------------------
*/
public void execute(RequestExec req) throws IOException
{
StringBuffer b =
new StringBuffer("<?xml version=\"1.0\"?>\r\n<methodResponse><fault><value><struct>\r\n<member>\r\n"
+ "<name>faultCode</name>\r\n<value><int>");
b.append(fault_code);
b.append("</int></value>\r\n</member>\r\n<member>\r\n<name>faultString</name>\r\n<value><string>");
b.append(StringUtil.encodeHTML(getMessage()));
b.append("</string></value>\r\n</member>\r\n</struct></value></fault></methodResponse>\r\n");
byte[] raw = b.toString().getBytes("UTF-8");
req.sendBinary("text/xml",raw);
} // end execute
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public final int getFaultCode()
{
return fault_code;
} // end getFaultCode
} // end class XmlRpcFault

View File

@ -0,0 +1,172 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.util.*;
import org.apache.log4j.*;
import org.apache.regexp.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.util.XMLLoader;
public class XmlRpcMethod
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(XmlRpcMethod.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private REProgram method_pgm; // regular expression program to match method name
private String remap_value = null; // remap value
private Class obj_class = null; // "class" handler for object
private Map raw_env; // "raw" environment
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public XmlRpcMethod(Element cfg) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
String method_name = loader.configGetAttribute(cfg,"name");
try
{ // compile the method name into a regular expression program
RECompiler comp = new RECompiler();
method_pgm = comp.compile("^" + method_name + "$");
} // end try
catch (RESyntaxException rese)
{ // not a valid regular expression program
logger.error("not a valid RE expression: " + method_name,rese);
throw new ConfigException("method name \"" + method_name + "\" not valid regular expression",cfg);
} // end catch
DOMElementHelper cfg_h = new DOMElementHelper(cfg);
Element sub;
if ((sub = cfg_h.getSubElement("object"))!=null)
{ // object handler element is present
DOMElementHelper sub_h = new DOMElementHelper(sub);
if (sub_h.hasAttribute("class"))
{ // the class is valid - try and load it
try
{ // load the class referenced by the handler
obj_class = Class.forName(sub.getAttribute("class"));
if (!(XmlRpcDispatch.class.isAssignableFrom(obj_class)))
throw new ConfigException("object handler class \"" + sub.getAttribute("class")
+ "\" is not an XmlRpcDispatch class",sub);
} // end try
catch (ClassNotFoundException cnfe)
{ // class not found - bail out
throw new ConfigException("object handler class \"" + sub.getAttribute("class")
+ "\" not found",sub);
} // end catch
} // end if
else // no referent for object handler - bail out now
throw new ConfigException("object handler for method \"" + "\" not valid",sub);
} // end if
else // no handler - this is an error
throw new ConfigException("method \"" + method_name + "\" does not have a valid handler",cfg);
NodeList nl = sub.getChildNodes();
HashMap tmp_env = new HashMap();
for (int i=0; i<nl.getLength(); i++)
{ // look for specific nodes
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // process various elements
if (n.getNodeName().equals("env"))
tmp_env.put(loader.configGetAttribute((Element)n,"name"),
loader.configGetAttribute((Element)n,"value"));
} // end if
} // end for
if (tmp_env.isEmpty())
raw_env = Collections.EMPTY_MAP;
else
raw_env = Collections.unmodifiableMap(tmp_env);
} // end constructor
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public final void configureMatcher(RE re)
{
re.setProgram(method_pgm);
} // end configureMatcher
public final String getRemap()
{
return remap_value;
} // end getRemap
public final Object dispatch(RequestInput req, XmlRpcRequest xreq, Map sub_map) throws Exception, XmlRpcFault
{
// prepare the environment
HashMap env = new HashMap();
Iterator it = raw_env.entrySet().iterator();
while (it.hasNext())
{ // do replacements to make the environment
Map.Entry ntry = (Map.Entry)(it.next());
env.put(ntry.getKey().toString(),StringUtil.replaceAllVariables(ntry.getValue().toString(),sub_map));
} // end while
if (obj_class!=null)
{ // object class method call - look for a cached object first
Map cache = (Map)(req.getAppAttribute(XmlRpcServlet.OBJECT_CLASS_CACHE_ATTR));
XmlRpcDispatch disp = (XmlRpcDispatch)(cache.get(obj_class.getName()));
if (disp==null)
{ // create new instance and cache it
disp = (XmlRpcDispatch)(obj_class.newInstance());
cache.put(obj_class.getName(),disp);
} // end if
return disp.dispatch(req,xreq,env); // dispatch the call
} // end if
// unable to dispatch things
return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"dispatch failure");
} // end dispatch
} // end class XmlRpcMethod

View File

@ -0,0 +1,392 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.io.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.util.XMLLoader;
public class XmlRpcRequest
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC");
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
String method_name; // the method name
List method_params; // the method parameters
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
XmlRpcRequest(Document req_doc) throws XmlRpcFault
{
if (req_doc==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"no XML call structure found");
try
{
// load the initial structure and method name
XMLLoader loader = XMLLoader.get();
Element root = loader.postGetRootElement(req_doc,"methodCall");
DOMElementHelper root_h = new DOMElementHelper(root);
method_name = loader.postGetSubElementText(root_h,"methodName");
// parse the parameters
Element params = root_h.getSubElement("params");
ArrayList tmp_method_params = new ArrayList();
if (params!=null)
{ // look for <param/> children of the <params/> node
NodeList nl = params.getChildNodes();
for (int i=0; i<nl.getLength(); i++)
{ // look at the child node...
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // make sure it's a <param/> node
if (!(n.getNodeName().equals("param")))
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"non-param element found inside \"params\" element");
tmp_method_params.add(parseValue(loader.postGetSubSection((Element)n,"value")));
} // end if
// else ignore this node
} // end for
} // end if
// save the method parameters
if (tmp_method_params.isEmpty())
method_params = Collections.EMPTY_LIST;
else
{ // make it read-only before
tmp_method_params.trimToSize();
method_params = Collections.unmodifiableList(tmp_method_params);
} // end else
} // end try
catch (ValidationException ve)
{ // validation exceptions get translated to XML-RPC faults
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,ve);
} // end catch
} // end constructor
/*--------------------------------------------------------------------------------
* Internal static operations
*--------------------------------------------------------------------------------
*/
private static final Object parseValue(Element val) throws ValidationException, XmlRpcFault
{
XMLLoader loader = XMLLoader.get();
// see if the value has an embedded type...
NodeList nl = val.getChildNodes();
Element type = null;
for (int i=0; i<nl.getLength(); i++)
{ // look for any sub-element within a value
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // save off the type-specific element
if (type!=null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"more than one type-specific element within a \"value\" element");
type = (Element)n;
} // end if
} // end for
if (type!=null)
{ // look at the contents of the "type" element
DOMElementHelper h = new DOMElementHelper(type);
final String name = type.getTagName();
if (name.equals("i4") || name.equals("int"))
{ // parse an integer value
String s = h.getElementText();
if (s==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid null inside \"" + name + "\" value");
Integer rc = null;
try
{ // create the return value
rc = new Integer(s.trim());
} // end try
catch (NumberFormatException nfe)
{ // bogus number!
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid integer value inside \"" + name
+ "\" value");
} // end catch
return rc;
} // end if
else if (name.equals("boolean"))
{ // parse a boolean value
String s = h.getElementText();
if (s==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid null inside \"boolean\" value");
s = s.trim();
if (s.equals("1"))
return Boolean.TRUE;
else if (s.equals("0"))
return Boolean.FALSE;
else
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid value inside \"boolean\" value");
} // end else if
else if (name.equals("string"))
{ // parse a string value
String s = h.getElementText();
if (s==null)
s = "";
return s;
} // end else if
else if (name.equals("double"))
{ // parse a double-precision floating-point value
String s = h.getElementText();
if (s==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid null inside \"double\" value");
Double rc = null;
try
{ // create the return value
rc = new Double(s.trim());
} // end try
catch (NumberFormatException nfe)
{ // bogus number!
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"invalid floating-point value inside \"double\" value");
} // end catch
return rc;
} // end else if
else if (name.equals("dateTime.iso8601"))
{ // parse a date/time value
String dstr = h.getElementText();
if (dstr==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid null inside \"dateTime.iso8601\" value");
dstr = dstr.trim();
// run some validation checks on the string
if ((dstr.charAt(8)!='T') || (dstr.charAt(11)!=':') || (dstr.charAt(14)!=':'))
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"invalid ISO8601 date/time value inside \"dateTime.iso8601\" value");
try
{ // use a GregorianCalendar to convert the fields into the appropriate format
GregorianCalendar cal = new GregorianCalendar(utc);
cal.set(Calendar.YEAR,Integer.parseInt(dstr.substring(0,4)));
cal.set(Calendar.MONTH,Integer.parseInt(dstr.substring(4,6)) - 1 + Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(dstr.substring(6,8)));
cal.set(Calendar.HOUR_OF_DAY,Integer.parseInt(dstr.substring(9,11)));
cal.set(Calendar.MINUTE,Integer.parseInt(dstr.substring(12,14)));
cal.set(Calendar.SECOND,Integer.parseInt(dstr.substring(15,17)));
return cal.getTime();
} // end try
catch (NumberFormatException nfe)
{ // numeric conversion error!
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"invalid ISO8601 date/time value inside \"dateTime.iso8601\" value");
} // end catch
} // end else if
else if (name.equals("base64"))
{ // parse a binary value
String s = h.getElementText();
if (s==null)
return new byte[0];
byte[] encoded_data = null;
try
{ // get the encoded data
encoded_data = s.getBytes("US-ASCII");
} // end try
catch (UnsupportedEncodingException uee)
{ // this is bogus
throw new InternalStateError("US-ASCII reports as 'unsupported'...shouldn't happen");
} // end catch
byte[] rc = null;
try
{ // wrap the byte array in a stream and decode it
// note: we use JavaMail's MIME decoder here
ByteArrayInputStream encoded_stm = new ByteArrayInputStream(encoded_data);
InputStream decoded_stm = MimeUtility.decode(encoded_stm,"base64");
// copy the decoded information to a new stream
ByteArrayOutputStream out_stm = new ByteArrayOutputStream();
IOUtil.copy(decoded_stm,out_stm);
IOUtil.shutdown(decoded_stm);
IOUtil.shutdown(encoded_stm);
// save the byte array backing the new stream
rc = out_stm.toByteArray();
IOUtil.shutdown(out_stm);
} // end try
catch (IOException ioe)
{ // error schlepping all those bits around
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,
"unable to load binary data from \"base64\" value");
} // end catch
catch (MessagingException me)
{ // invalid format
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"invalid encoded data inside \"base64\" value");
} // end catch
return rc;
} // end else if
else if (name.equals("struct"))
return parseStruct(type);
else if (name.equals("array"))
return parseArray(type);
else // no dice here
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"invalid type element \"" + name + "\" specified inside a \"value\"");
} // end if
else
{ // if there's no type-specific element, treat it as a string
DOMElementHelper h = new DOMElementHelper(val);
String s = h.getElementText();
if (s==null)
s = "";
return s;
} // end else
} // end parseValue
private static final List parseArray(Element val) throws XmlRpcFault, ValidationException
{
XMLLoader loader = XMLLoader.get();
Element data = loader.postGetSubSection(val,"data");
NodeList nl = val.getChildNodes();
ArrayList rc = new ArrayList();
for (int i=0; i<nl.getLength(); i++)
{ // look for <value/> elements within the <data/> element
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // make sure we've got a value element here!
if (!(n.getNodeName().equals("value")))
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"non-value element found inside array \"data\" element");
rc.add(parseValue((Element)n));
} // end if
} // end for
if (rc.isEmpty())
return Collections.EMPTY_LIST;
else
{ // trim the result array and return the list
rc.trimToSize();
return Collections.unmodifiableList(rc);
} // end else
} // end parseArray
private static final Map parseStruct(Element val) throws XmlRpcFault, ValidationException
{
XMLLoader loader = XMLLoader.get();
NodeList nl = val.getChildNodes();
HashMap rc = new HashMap();
for (int i=0; i<nl.getLength(); i++)
{ // seek out all the <member/> elements within a <struct/> element
Node n = nl.item(i);
if (n.getNodeType()==Node.ELEMENT_NODE)
{ // make sure we've got a value element here!
if (!(n.getNodeName().equals("member")))
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,
"non-member element found inside \"struct\" element");
DOMElementHelper h = new DOMElementHelper((Element)n);
String my_name = loader.postGetSubElementText(h,"name").trim();
Element my_val = loader.postGetSubSection(h,"value");
rc.put(my_name,parseValue(my_val));
} // end if
} // end for
if (rc.isEmpty())
return Collections.EMPTY_MAP;
else
return Collections.unmodifiableMap(rc);
} // end parseStruct
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public final String getMethod()
{
return method_name;
} // end getMethod
public final int getParamCount()
{
return method_params.size();
} // end getParamCount
public final List getParams()
{
return method_params;
} // end getParams
public final Object getParam(int ndx)
{
return method_params.get(ndx);
} // end getParam
} // end class XmlRpcRequest

View File

@ -0,0 +1,24 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
public interface XmlRpcSelfSerializer
{
public abstract String serializeXmlRpc() throws XmlRpcFault;
} // end interface XmlRpcSelfSerializer

View File

@ -0,0 +1,471 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.beans.*;
import java.io.*;
import java.lang.ref.*;
import java.lang.reflect.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import org.apache.log4j.*;
import com.silverwrist.util.*;
public class XmlRpcSerializer
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(XmlRpcSerializer.class);
private static XmlRpcSerializer self = null;
private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC");
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
private XmlRpcSerializer()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public final String serialize(boolean b)
{
return "<boolean>" + (b ? "1" : "0") + "</boolean>";
} // end serialize
public final String serialize(byte b)
{
return this.serialize((int)b);
} // end serialize
public final String serialize(char c)
{
return "<string>" + c + "</string>";
} // end serialize
public final String serialize(double d)
{
return "<double>" + d + "</double>";
} // end serialize
public final String serialize(float f)
{
return this.serialize((double)f);
} // end serialize
public final String serialize(int i)
{
return "<int>" + i + "</int>";
} // end serialize
public final String serialize(long l)
{
return this.serialize((double)l);
} // end serialize
public final String serialize(short s)
{
return this.serialize((int)s);
} // end serialize
public final String serialize(Object obj) throws XmlRpcFault
{
if (obj==null)
return serializeString(null);
// self-serializing objects
if (obj instanceof XmlRpcSelfSerializer)
return ((XmlRpcSelfSerializer)obj).serializeXmlRpc();
// types from java.io.*
if (obj instanceof InputStream)
return serializeInputStream((InputStream)obj);
// types from java.sql.*
if (obj instanceof java.sql.Blob)
{ // serialize the blob as a binary stream
try
{ // just get its input stream
return serializeInputStream(((java.sql.Blob)obj).getBinaryStream());
} // end try
catch (java.sql.SQLException e)
{ // fault on error here
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to save binary data");
} // end catch
} // end if
// types from java.util.*
if (obj instanceof Calendar)
return serializeCalendar((Calendar)obj);
if (obj instanceof Collection)
return serializeCollection((Collection)obj);
if (obj instanceof java.util.Date)
return serializeDate((java.util.Date)obj);
if (obj instanceof Enumeration)
return serializeEnumeration((Enumeration)obj);
if (obj instanceof Iterator)
return serializeIterator((Iterator)obj);
if (obj instanceof Map)
return serializeMap((Map)obj);
// types from java.lang.ref.*
if (obj instanceof Reference) // for a reference, encode its referent
return this.serialize(((Reference)obj).get());
// types from java.lang.*
if (obj instanceof Boolean)
return this.serialize(((Boolean)obj).booleanValue());
if (obj instanceof Character)
return this.serialize(((Character)obj).charValue());
if ((obj instanceof Byte) || (obj instanceof Short) || (obj instanceof Integer))
return this.serialize(((Number)obj).intValue());
if ((obj instanceof Long) || (obj instanceof Float) || (obj instanceof Double))
return this.serialize(((Number)obj).doubleValue());
// String and StringBuffer are handled properly by the fallback mechanism below
// last-ditch fallback method - use toString, get the string, and encode it
return serializeString(obj.toString());
} // end serialize
public final String serialize(boolean[] ba)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<ba.length; i++)
b.append("<value>").append(this.serialize(ba[i])).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(byte[] ba) throws XmlRpcFault
{
return this.serializeInputStream(new ByteArrayInputStream(ba));
} // end serialize
public final String serialize(char[] ca)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<ca.length; i++)
b.append("<value>").append(this.serialize(ca[i])).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(double[] da)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<da.length; i++)
b.append("<value>").append(this.serialize(da[i])).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(float[] fa)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<fa.length; i++)
b.append("<value>").append(this.serialize((double)(fa[i]))).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(int[] ia)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<ia.length; i++)
b.append("<value>").append(this.serialize(ia[i])).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(long[] la)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<la.length; i++)
b.append("<value>").append(this.serialize((double)(la[i]))).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(short[] sa)
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<sa.length; i++)
b.append("<value>").append(this.serialize((int)(sa[i]))).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serialize(Object[] arr) throws XmlRpcFault
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
for (int i=0; i<arr.length; i++)
b.append("<value>").append(this.serialize(arr[i])).append("</value>\r\n");
b.append("</data>\r\n</array>");
return b.toString();
} // end serialize
public final String serializeBean(Object obj, BeanInfo binf) throws XmlRpcFault
{
PropertyDescriptor[] props = binf.getPropertyDescriptors();
StringBuffer b = new StringBuffer("<struct>\r\n");
final Object[] no_params = new Object[0];
for (int i=0; i<props.length; i++)
{ // get property names and values
Method mread = props[i].getReadMethod();
if (mread!=null)
{ // use the method to get the value associated with the name
try
{ // append the member data
b.append("<member>\r\n<name>").append(StringUtil.encodeHTML(props[i].getName()));
b.append("</name>\r\n<value>").append(this.serialize(mread.invoke(obj,no_params)));
b.append("</value>\r\n</member>\r\n");
} // end try
catch (IllegalAccessException iae)
{ // unable to access that method
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,iae);
} // end catch
catch (InvocationTargetException ite)
{ // the method we invoked threw an exception
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,ite.getTargetException());
} // end catch
} // end if
} // end for
b.append("</struct>\r\n");
return b.toString();
} // end serializeBean
public final String serializeBean(Object obj) throws XmlRpcFault
{
try
{ // get the BeanInfo via introspection
return serializeBean(obj,Introspector.getBeanInfo(obj.getClass()));
} // end try
catch (IntrospectionException e)
{ // introspection failed
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,e);
} // end catch
} // end serializeBean
public final String serializeCalendar(Calendar cal)
{
// Create the two string buffers converting the date.
StringBuffer rc = new StringBuffer("<dateTime.iso8601>");
StringBuffer conv = new StringBuffer();
String c;
// Encode the year first.
conv.append("0000").append(cal.get(Calendar.YEAR));
c = conv.toString();
rc.append(c.substring(c.length()-4));
// Now the month...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.MONTH) - Calendar.JANUARY + 1);
c = conv.toString();
rc.append(c.substring(c.length()-2));
// And the day...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.DAY_OF_MONTH));
c = conv.toString();
rc.append(c.substring(c.length()-2)).append('T');
// And the hour...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.HOUR_OF_DAY));
c = conv.toString();
rc.append(c.substring(c.length()-2)).append(':');
// And the minute...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.MINUTE));
c = conv.toString();
rc.append(c.substring(c.length()-2)).append(':');
// And the second...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.SECOND));
c = conv.toString();
rc.append(c.substring(c.length()-2)).append("</dateTime.iso8601>");
// This is the resulting date/time value.
return rc.toString();
} // end serializeCalendar
public final String serializeCollection(Collection coll) throws XmlRpcFault
{
return serializeIterator(coll.iterator());
} // end serializeCollection
public final String serializeDate(java.util.Date date) throws XmlRpcFault
{
GregorianCalendar cal = new GregorianCalendar(utc);
cal.setTime(date);
return serializeCalendar(cal);
} // end serializeDate
public final String serializeEnumeration(Enumeration enum) throws XmlRpcFault
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
while (enum.hasMoreElements())
b.append("<value>").append(this.serialize(enum.nextElement())).append("</value>");
b.append("</data>\r\n</array>");
return b.toString();
} // end serializeIterator
public final String serializeInputStream(InputStream stm) throws XmlRpcFault
{
String rc = null;
try
{ // convert the data bytes to encoded bytes first
ByteArrayOutputStream internal_stm = new ByteArrayOutputStream();
OutputStream encode_stm = MimeUtility.encode(internal_stm,"base64");
IOUtil.copy(stm,encode_stm);
encode_stm.flush();
// turn our encoded output into an InputStream
ByteArrayInputStream internal2_stm = new ByteArrayInputStream(internal_stm.toByteArray());
IOUtil.shutdown(encode_stm);
IOUtil.shutdown(internal_stm);
// build a StringWriter containing the converted contents
StringWriter wr = new StringWriter();
wr.write("<base64>");
InputStreamReader rd = new InputStreamReader(internal2_stm,"US-ASCII");
IOUtil.copy(rd,wr);
IOUtil.shutdown(rd);
IOUtil.shutdown(internal2_stm);
wr.write("</base64>");
// send out the complete string
rc = wr.toString();
IOUtil.shutdown(wr);
} // end try
catch (IOException ioe)
{ // this is an internal error
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to save binary data");
} // end catch
catch (MessagingException me)
{ // and so is this
throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to encode binary data");
} // end catch
return rc;
} // end serializeInputStream
public final String serializeIterator(Iterator it) throws XmlRpcFault
{
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
while (it.hasNext())
b.append("<value>").append(this.serialize(it.next())).append("</value>");
b.append("</data>\r\n</array>");
return b.toString();
} // end serializeIterator
public final String serializeMap(Map m) throws XmlRpcFault
{
StringBuffer b = new StringBuffer("<struct>\r\n");
Iterator it = m.entrySet().iterator();
while (it.hasNext())
{ // serialize each entry in turn
Map.Entry ntry = (Map.Entry)(it.next());
b.append("<member>\r\n<name>").append(StringUtil.encodeHTML(ntry.getKey().toString()));
b.append("</name>\r\n<value>").append(this.serialize(ntry.getValue()));
b.append("</value>\r\n</member>\r\n");
} // end while
b.append("</struct>\r\n");
return b.toString();
} // end serializeMap
public final String serializeString(String s)
{
if (s==null)
return "<string></string>";
return "<string>" + StringUtil.encodeHTML(s) + "</string>";
} // end serializeString
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static final synchronized XmlRpcSerializer get()
{
if (self==null)
self = new XmlRpcSerializer();
return self;
} // end get
} // end class XmlRpcSerializer

View File

@ -0,0 +1,198 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.regexp.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.config.RootConfig;
import com.silverwrist.venice.ui.servlet.BaseServlet;
import com.silverwrist.venice.ui.servlet.RequestImpl;
public class XmlRpcServlet extends BaseServlet
{
/*--------------------------------------------------------------------------------
* Inner class that implements the actual "normal" return value
*--------------------------------------------------------------------------------
*/
static class XmlRpcReturnValue implements ContentExecute
{
private Object obj;
XmlRpcReturnValue(Object obj)
{
this.obj = obj;
} // end constructor
public void execute(RequestExec req) throws IOException
{
StringBuffer b =
new StringBuffer("<?xml version=\"1.0\"?>\r\n<methodResponse><params><param>\r\n<value>");
try
{ // serialize the returned object
XmlRpcSerializer serializer = XmlRpcSerializer.get();
b.append(serializer.serialize(obj));
} // end try
catch (XmlRpcFault f)
{ // if we get a fault here, just execute THAT instead
f.execute(req);
return;
} // end catch
b.append("</value>\r\n</param></params></methodResponse>\r\n");
byte[] raw = b.toString().getBytes("UTF-8");
req.sendBinary("text/xml",raw);
} // end execute
} // end class XmlRpcReturnValue
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final String METHOD_LIST_ATTR = "ui.xmlrpc.MethodList";
public static final String OBJECT_CLASS_CACHE_ATTR = "ui.xmlrpc.class.ObjectCache";
/*--------------------------------------------------------------------------------
* Overrides from class BaseServlet
*--------------------------------------------------------------------------------
*/
protected void init(ServletConfig config, ServletContext ctxt, VeniceEngine engine, RootConfig root,
String root_file_path)
{
List methods = root.getXmlRpcMethods();
RequestImpl.setAppAttribute(ctxt,METHOD_LIST_ATTR,methods);
RequestImpl.setAppAttribute(ctxt,OBJECT_CLASS_CACHE_ATTR,Collections.synchronizedMap(new HashMap()));
} // end init
protected VeniceUISessionFactory getSessionFactory()
{
return NullSession.get(); // null session by default
} // end getSessionFactory
protected Object translateServletException(RequestInput ri, Exception e)
{
return null;
} // end translateServletException
public Object process(RequestInput req)
{
XmlRpcRequest xreq;
try
{ // get the XML-RPC request structure
xreq = new XmlRpcRequest(req.getRequestDocument());
} // end try
catch (XmlRpcFault f)
{ // return the fault structure
return f;
} // end catch
// Prepare the parameters map
int i;
HashMap param_repl_map = new HashMap();
for (i=0; i<xreq.getParamCount(); i++)
{ // fill in the parameters...
Object obj = xreq.getParam(i);
if ((obj instanceof String) || (obj instanceof Integer) || (obj instanceof Double))
param_repl_map.put("param." + i,obj.toString());
} // end for
// Find an appropriate method to handle this call.
List methods = (List)(req.getAppAttribute(METHOD_LIST_ATTR));
boolean rescan = false;
RE matcher = new RE();
String the_name = xreq.getMethod();
XmlRpcMethod meth = null;
HashMap sub_map;
do
{ // search for a method
rescan = false;
Iterator it = methods.iterator();
boolean found = false;
while (!found && it.hasNext())
{ // look for a match on the method name
meth = (XmlRpcMethod)(it.next());
meth.configureMatcher(matcher);
found = matcher.match(the_name);
} // end while
if (!found) // method not found
return new XmlRpcFault(XmlRpcFault.METHOD_NOT_FOUND,"Method not found: " + the_name);
// prepare the substitution map
sub_map = (HashMap)(param_repl_map.clone());
int ct = matcher.getParenCount();
for (i=0; i<=ct; i++)
sub_map.put("match." + i,matcher.getParen(i));
String remap = meth.getRemap();
if (remap!=null)
{ // substitute in variables and rescan
the_name = StringUtil.replaceAllVariables(remap,sub_map);
rescan = true;
} // end if
} while (rescan);
try
{ // dispatch the method call
Object rc = meth.dispatch(req,xreq,sub_map);
if (rc==null)
rc = new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"no return value");
else if (rc instanceof Exception)
rc = new XmlRpcFault((Exception)rc);
else if (!(rc instanceof XmlRpcFault))
rc = new XmlRpcReturnValue(rc);
return rc;
} // end try
catch (Exception e)
{ // if there's an exception, turn it into a "Fault" message
return new XmlRpcFault(e);
} // end catch
catch (XmlRpcFault f)
{ // pass faults right on up
return f;
} // end catch
} // end process
} // end class XmlRpcServlet

View File

@ -0,0 +1,70 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.rpc;
import java.util.*;
import com.silverwrist.venice.ui.*;
public class XmlRpcTestHandler implements XmlRpcDispatch
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public XmlRpcTestHandler()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatch
*--------------------------------------------------------------------------------
*/
public Object dispatch(RequestInput req, XmlRpcRequest xreq, Map environment) throws Exception, XmlRpcFault
{
if (xreq.getMethod().equals("venice:test.sumDifference"))
{ // do the sumdifference API
if (xreq.getParamCount()!=2)
throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter count mismatch");
Integer n1, n2;
try
{ // cast parameters to Integer
n1 = (Integer)(xreq.getParam(0));
n2 = (Integer)(xreq.getParam(1));
} // end try
catch (ClassCastException e)
{ // class cast exception!
throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch");
} // end catch
HashMap rc = new HashMap();
rc.put("sum",new Integer(n1.intValue() + n2.intValue()));
rc.put("difference",new Integer(n1.intValue() - n2.intValue()));
return rc;
} // end if
return null;
} // end dispatch
} // end class XmlRpcTestHandler

View File

@ -11,7 +11,7 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
*/ */
@ -34,6 +34,38 @@ import com.silverwrist.venice.ui.script.ScriptManagerContainer;
public abstract class BaseServlet extends HttpServlet public abstract class BaseServlet extends HttpServlet
{ {
/*--------------------------------------------------------------------------------
* Internal session factory object
*--------------------------------------------------------------------------------
*/
static class HttpSessionFactory implements VeniceUISessionFactory
{
private static final String ATTR_NAME = VeniceUISession.class.getName();
HttpSessionFactory()
{ // do nothing
} // end constructor
public VeniceUISession createSession(ServletContext ctxt, HttpServletRequest request,
HttpServletResponse response, VeniceEngine engine,
RootConfig config) throws ServletException
{
HttpSession session = request.getSession(true);
VeniceUISession rc = (VeniceUISession)(session.getAttribute(ATTR_NAME));
if (rc==null)
{ // return a new session
rc = new HttpVeniceUISession(request,session,engine);
session.setAttribute(ATTR_NAME,rc);
} // end if
return rc;
} // end createSession
} // end class HttpSessionFactory
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Static data members * Static data members
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -49,6 +81,8 @@ public abstract class BaseServlet extends HttpServlet
private static Category logger = Category.getInstance(BaseServlet.class); private static Category logger = Category.getInstance(BaseServlet.class);
private static VeniceUISessionFactory factory = new HttpSessionFactory();
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Internal operations * Internal operations
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -56,14 +90,16 @@ public abstract class BaseServlet extends HttpServlet
private Object translateException(RequestInput req, Exception e) private Object translateException(RequestInput req, Exception e)
{ {
// try the servlet first
Object rc = translateServletException(req,e);
if (rc!=null)
return rc;
// otherwise, go it alone
logger.info("BaseServlet.translateException translating exception",e); logger.info("BaseServlet.translateException translating exception",e);
if (e instanceof ScriptingException) if (e instanceof ScriptingException)
return new ErrorBox("Scripting Error",e,null); return new ErrorBox("Scripting Error",e,null);
// Last-ditch effort: get the specific servlet to translate the exception.
Object rc = translateServletException(req,e);
if (rc!=null)
return rc;
return new ErrorBox("Unhandled Exception Detected!",e.toString(),e,null); return new ErrorBox("Unhandled Exception Detected!",e.toString(),e,null);
} // end translateException } // end translateException
@ -77,13 +113,41 @@ public abstract class BaseServlet extends HttpServlet
try try
{ // create the actual request implementation { // create the actual request implementation
ServletContext ctxt = getServletContext(); ServletContext ctxt = getServletContext();
RequestImpl the_request = RequestImpl the_request = null;
new RequestImpl(ctxt,request,response,(VeniceEngine)(ctxt.getAttribute(ENGINE_ATTRIBUTE)), try
(RootConfig)(ctxt.getAttribute(UICONFIG_ATTRIBUTE))); { // create the request object
the_request = new RequestImpl(ctxt,request,response,
(VeniceEngine)(ctxt.getAttribute(ENGINE_ATTRIBUTE)),
(RootConfig)(ctxt.getAttribute(UICONFIG_ATTRIBUTE)),
getSessionFactory());
} // end try
catch (ValidationException ve)
{ // error in formatting of the request - bug out
response.sendError(HttpServletResponse.SC_BAD_REQUEST,ve.toString());
return;
} // end catch
String default_location = the_request.getLocation(); String default_location = the_request.getLocation();
// log the username with all log messages, if the user is logged in // log the username with all log messages, if the user is logged in
boolean record_user = the_request.getUser().isLoggedIn(); boolean record_user = false;
if (the_request.sessionBound())
{ // has the session been bound?
try
{ // find out whether they're logged in
record_user = the_request.getUser().isLoggedIn();
} // end try
catch (IllegalStateException e)
{ // if not, just forget about it
record_user = false;
} // end catch
} // end if
if (record_user) if (record_user)
NDC.push(the_request.getUser().getUserName()); NDC.push(the_request.getUser().getUserName());
@ -176,6 +240,12 @@ public abstract class BaseServlet extends HttpServlet
{ // default does nothing { // default does nothing
} // end init } // end init
protected VeniceUISessionFactory getSessionFactory()
{
return factory;
} // end getSessionFactory
protected Object translateServletException(RequestInput ri, Exception e) protected Object translateServletException(RequestInput ri, Exception e)
{ {
return null; // does nothing by default return null; // does nothing by default

View File

@ -0,0 +1,206 @@
/*
* 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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.ui.servlet;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*;
class HttpVeniceUISession implements VeniceUISession
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final String SESSION_ATTRIBUTE_STEM = "venice.vars.";
private static Category logger = Category.getInstance(HttpVeniceUISession.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private HttpSession session;
private UserContext user;
private Cookie venice_cookie = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
HttpVeniceUISession(HttpServletRequest request, HttpSession session, VeniceEngine engine)
throws ServletException
{
this.session = session; // save off the session variable
try
{ // tell the engine to create us a user context
user = engine.createUserContext(request.getRemoteAddr());
// Did the user send a Venice authentication cookie? If so, try to use it.
Cookie[] cookies = request.getCookies();
Cookie venice_cookie = null;
for (int i=0; (venice_cookie==null) && (i<cookies.length); i++)
{ // look for a Venice authentication cookie
if (RequestInput.LOGIN_COOKIE.equals(cookies[i].getName()))
venice_cookie = cookies[i];
} // end for
} // end try
catch (DataException e)
{ // context creation failed - remap the exception
logger.error("Session creation failed: " + e.getMessage(),e);
throw new ServletException("Session creation failed: " + e.getMessage(),e);
} // end catch
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceUISession
*--------------------------------------------------------------------------------
*/
public long getCreationTime()
{
return session.getCreationTime();
} // end getCreationTime
public String getID()
{
return session.getId();
} // end getID
public long getLastAccessedTime()
{
return session.getLastAccessedTime();
} // end getLastAccessedTime
public void setMaxInactiveInterval(int interval)
{
session.setMaxInactiveInterval(interval);
} // end setMaxInactiveInterval
public int getMaxInactiveInterval()
{
return session.getMaxInactiveInterval();
} // end getMaxInactiveInterval
public Object getAttribute(String name)
{
return session.getAttribute(SESSION_ATTRIBUTE_STEM + name);
} // end getAttribute
public Enumeration getAttributeNames()
{
Enumeration raw = session.getAttributeNames();
ArrayList rc = new ArrayList();
while (raw.hasMoreElements())
{ // look for attributes we've added
String tmp = (String)(raw.nextElement());
if (tmp.startsWith(SESSION_ATTRIBUTE_STEM))
rc.add(tmp.substring(SESSION_ATTRIBUTE_STEM.length()));
} // end while
return Collections.enumeration(rc);
} // end getAttributeNames
public void setAttribute(String name, Object o)
{
session.setAttribute(SESSION_ATTRIBUTE_STEM + name,o);
} // end setAttribute
public void removeAttribute(String name)
{
session.removeAttribute(SESSION_ATTRIBUTE_STEM + name);
} // end removeAttribute
public void invalidate()
{
session.invalidate();
} // end invalidate
public UserContext getUser()
{
return user;
} // end getUser
public void setUser(UserContext user)
{
this.user = user;
} // end setUser
public void preprocess(RequestInput ri)
{
if (venice_cookie!=null)
{ // try to log in with the cookie
try
{ // attempt authentication
if (!(user.authenticateWithToken(venice_cookie.getValue())))
ri.deleteCookie(RequestInput.LOGIN_COOKIE); // delete bogus cookie if it didn't work
} // end try
catch (DataException de)
{ // it didn't work...
ri.deleteCookie(RequestInput.LOGIN_COOKIE);
} // end catch
venice_cookie = null;
} // end if
} // end preprocess
/*--------------------------------------------------------------------------------
* Implementations from interface HttpSessionBindingListener
*--------------------------------------------------------------------------------
*/
public void valueBound(HttpSessionBindingEvent event)
{ // do nothing
} // end valueBound
public void valueUnbound(HttpSessionBindingEvent event)
{
this.session = null;
this.user = null;
} // end valueUnbound
} // end class HttpVeniceUISession

View File

@ -11,7 +11,7 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
*/ */
@ -39,6 +39,7 @@ import com.silverwrist.venice.ui.menus.CommunityMenu;
import com.silverwrist.venice.ui.menus.Menu; import com.silverwrist.venice.ui.menus.Menu;
import com.silverwrist.venice.ui.menus.MenuComponent; import com.silverwrist.venice.ui.menus.MenuComponent;
import com.silverwrist.venice.ui.script.*; import com.silverwrist.venice.ui.script.*;
import com.silverwrist.venice.util.XMLLoader;
public class RequestImpl implements RequestInput public class RequestImpl implements RequestInput
{ {
@ -553,9 +554,6 @@ public class RequestImpl implements RequestInput
private static final String STYLESHEET_ATTRIBUTE = "com.silverwrist.venice.rendering.StyleSheet"; private static final String STYLESHEET_ATTRIBUTE = "com.silverwrist.venice.rendering.StyleSheet";
private static final String APP_ATTRIBUTE_STEM = "com.silverwrist.venice.ui.variables."; private static final String APP_ATTRIBUTE_STEM = "com.silverwrist.venice.ui.variables.";
private static final String USERCTXT_ATTRIBUTE = "user.context";
private static final String SESSION_ATTRIBUTE_STEM = "venice.vars.";
public static final String REQUEST_CONTENT = "com.silverwrist.venice.ui.Content"; 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_INPUT = "com.silverwrist.venice.ui.RequestInput";
public static final String REQUEST_OUTPUT = "com.silverwrist.venice.ui.RequestOutput"; public static final String REQUEST_OUTPUT = "com.silverwrist.venice.ui.RequestOutput";
@ -569,10 +567,9 @@ public class RequestImpl implements RequestInput
private ServletContext ctxt; // the servlet context private ServletContext ctxt; // the servlet context
private HttpServletRequest request; // the servlet request data private HttpServletRequest request; // the servlet request data
private HttpServletResponse response; // the servlet response data private HttpServletResponse response; // the servlet response data
private HttpSession session; // the current HTTP session private VeniceUISession session; // the current HTTP session
private VeniceEngine engine; // the Venice engine context private VeniceEngine engine; // the Venice engine context
private RootConfig config; // the UI configuration data private RootConfig config; // the UI configuration data
private UserContext user; // the current user context
private ServletMultipartHandler mphandler = null; // if this is a multipart/form-data POST private ServletMultipartHandler mphandler = null; // if this is a multipart/form-data POST
private ArrayList new_cookies = null; // cookies to be added to the response private ArrayList new_cookies = null; // cookies to be added to the response
private boolean end_response = true; // do we need to properly end the response? private boolean end_response = true; // do we need to properly end the response?
@ -585,6 +582,7 @@ public class RequestImpl implements RequestInput
private DateFormat activity_time = null; // format to use for activity string times private DateFormat activity_time = null; // format to use for activity string times
private CommunityContext community = null; // the current community private CommunityContext community = null; // the current community
private LinkedList auto_cleanup = null; // auto-cleanup callbacks private LinkedList auto_cleanup = null; // auto-cleanup callbacks
private Document request_doc = null; // request parsed as an XML document
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructor * Constructor
@ -592,56 +590,35 @@ public class RequestImpl implements RequestInput
*/ */
RequestImpl(ServletContext ctxt, HttpServletRequest request, HttpServletResponse response, RequestImpl(ServletContext ctxt, HttpServletRequest request, HttpServletResponse response,
VeniceEngine engine, RootConfig config) throws ServletException VeniceEngine engine, RootConfig config, VeniceUISessionFactory factory)
throws ServletException, ValidationException
{ {
// Set up the basic variables. // Set up the basic variables.
this.ctxt = ctxt; this.ctxt = ctxt;
this.request = request; this.request = request;
this.response = response; this.response = response;
this.session = request.getSession(true);
this.engine = engine; this.engine = engine;
this.config = config; this.config = config;
// Create or retrieve the user context. if (request.getMethod().equals("POST"))
user = (UserContext)(session.getAttribute(USERCTXT_ATTRIBUTE)); { // POSTs can have special handling for the request data
if (user==null) if (request.getContentType().startsWith("text/xml"))
{ // the user context isn't present yet { // this is some sort of XML-based request - parse it into a DOM tree
XMLLoader loader = XMLLoader.get();
try try
{ // tell the engine to create us a user context { // load the document
user = engine.createUserContext(request.getRemoteAddr()); request_doc = loader.loadPostData(request.getInputStream()); // may throw ValidationException
// Did the user send a Venice authentication cookie? If so, try to use it.
Cookie[] cookies = request.getCookies();
Cookie venice_cookie = null;
for (int i=0; (venice_cookie==null) && (i<cookies.length); i++)
{ // look for a Venice authentication cookie
if (LOGIN_COOKIE.equals(cookies[i].getName()))
venice_cookie = cookies[i];
} // end for
if (venice_cookie!=null)
{ // attempt to authenticate with this cookie
if (!(user.authenticateWithToken(venice_cookie.getValue())))
deleteCookie(LOGIN_COOKIE); // delete bogus cookie if it didn't work
} // end if
// else don't authenticate, stay in the "anonymous" state
// Save the user context.
session.setAttribute(USERCTXT_ATTRIBUTE,user);
} // end try } // end try
catch (DataException e) catch (IOException ioe)
{ // context creation failed - remap the exception { // IO exception...sigh
logger.error("Session creation failed: " + e.getMessage(),e); logger.error("IO error loading request document",ioe);
throw new ServletException("Session creation failed: " + e.getMessage(),e); throw new ServletException("IO error loading request document: " + ioe.toString(),ioe);
} // end catch } // end catch
} // end if } // end if
else if (ServletMultipartHandler.canHandle(request))
if (request.getMethod().equals("POST") && ServletMultipartHandler.canHandle(request))
{ // if this is a multipart/form-data POST, create the handler object { // if this is a multipart/form-data POST, create the handler object
try try
{ // use the multipart handler and get something { // use the multipart handler and get something
@ -651,16 +628,23 @@ public class RequestImpl implements RequestInput
catch (ServletMultipartException smpe) catch (ServletMultipartException smpe)
{ // unable to parse POST data for some reason { // unable to parse POST data for some reason
logger.error("Multipart data acquisition failed: " + smpe.getMessage(),smpe); logger.error("Multipart data acquisition failed: " + smpe.getMessage(),smpe);
throw new ServletException("Unable to retrieve parameters: " + smpe.getMessage(),smpe); throw new ValidationException("invalid multipart request: " + smpe.getMessage(),smpe);
} // end catch } // end catch
} // end else if
} // end if } // end if
// read the user's preferred locale // Create the UI session.
session = factory.createSession(ctxt,request,response,engine,config);
session.preprocess(this);
if (!(session instanceof NullSession))
{ // read the user's preferred locale
try try
{ // get the user default locale { // get the user default locale
my_locale = user.getLocale(); my_locale = session.getUser().getLocale();
} // end try } // end try
catch (DataException de) catch (DataException de)
@ -672,7 +656,7 @@ public class RequestImpl implements RequestInput
// read the user's preferred time zone // read the user's preferred time zone
try try
{ // get the user default timezone { // get the user default timezone
my_timezone = user.getTimeZone(); my_timezone = session.getUser().getTimeZone();
} // end try } // end try
catch (DataException de) catch (DataException de)
@ -681,6 +665,14 @@ public class RequestImpl implements RequestInput
} // end catch } // end catch
} // end if
else
{ // just default locale/timezone
my_locale = Locale.getDefault();
my_timezone = TimeZone.getDefault();
} // end else
// Come up with a "first guess" at the location. // Come up with a "first guess" at the location.
StringBuffer loc_buf = new StringBuffer(request.getServletPath()); StringBuffer loc_buf = new StringBuffer(request.getServletPath());
if (loc_buf.charAt(0)=='/') if (loc_buf.charAt(0)=='/')
@ -865,8 +857,17 @@ public class RequestImpl implements RequestInput
} // end getSourceAddress } // end getSourceAddress
public void endSession()
{
session.invalidate();
session = null;
} // end endSession
public boolean hasParameter(String name) public boolean hasParameter(String name)
{ {
if (request_doc!=null)
return false;
if (mphandler!=null) if (mphandler!=null)
return mphandler.hasParameter(name); return mphandler.hasParameter(name);
else else
@ -876,6 +877,8 @@ public class RequestImpl implements RequestInput
public String getParameter(String name) public String getParameter(String name)
{ {
if (request_doc!=null)
return null;
if (mphandler!=null) if (mphandler!=null)
return mphandler.getValue(name); return mphandler.getValue(name);
else else
@ -942,6 +945,8 @@ public class RequestImpl implements RequestInput
public Enumeration getParameterNames() public Enumeration getParameterNames()
{ {
if (request_doc!=null)
return Collections.enumeration(Collections.EMPTY_LIST);
if (mphandler!=null) if (mphandler!=null)
return mphandler.getNames(); return mphandler.getNames();
else else
@ -951,6 +956,8 @@ public class RequestImpl implements RequestInput
public String[] getParameterValues(String name) public String[] getParameterValues(String name)
{ {
if (request_doc!=null)
return new String[0];
if (mphandler!=null) if (mphandler!=null)
return mphandler.getParamValues(name); return mphandler.getParamValues(name);
else else
@ -960,6 +967,8 @@ public class RequestImpl implements RequestInput
public boolean isFileParam(String name) public boolean isFileParam(String name)
{ {
if (request_doc!=null)
return false;
if (mphandler!=null) if (mphandler!=null)
return mphandler.isFileParam(name); return mphandler.isFileParam(name);
else else
@ -969,6 +978,8 @@ public class RequestImpl implements RequestInput
public String getParameterType(String name) public String getParameterType(String name)
{ {
if (request_doc!=null)
return null;
if (mphandler!=null) if (mphandler!=null)
return mphandler.getContentType(name); return mphandler.getContentType(name);
else else
@ -978,6 +989,8 @@ public class RequestImpl implements RequestInput
public int getParameterSize(String name) public int getParameterSize(String name)
{ {
if (request_doc!=null)
return -1;
if (mphandler!=null) if (mphandler!=null)
return mphandler.getContentSize(name); return mphandler.getContentSize(name);
else else
@ -998,6 +1011,18 @@ public class RequestImpl implements RequestInput
} // end getParameterDataStream } // end getParameterDataStream
public Document getRequestDocument()
{
return request_doc;
} // end getRequestDocument
public boolean sessionBound()
{
return ((session!=null) && !(session instanceof NullSession));
} // end sessionBound
public boolean isImageButtonClicked(String name) public boolean isImageButtonClicked(String name)
{ {
return this.hasParameter(name + ".x"); return this.hasParameter(name + ".x");
@ -1018,13 +1043,16 @@ public class RequestImpl implements RequestInput
public Object getSessionAttribute(String name) public Object getSessionAttribute(String name)
{ {
return getSessionAttribute(session,name); return session.getAttribute(name);
} // end getSessionAttribute } // end getSessionAttribute
public void setSessionAttribute(String name, Object o) public void setSessionAttribute(String name, Object o)
{ {
setSessionAttribute(session,name,o); if (o==null)
session.removeAttribute(name);
else
session.setAttribute(name,o);
} // end setSessionAttribute } // end setSessionAttribute
@ -1075,17 +1103,13 @@ public class RequestImpl implements RequestInput
public UserContext getUser() public UserContext getUser()
{ {
return user; return session.getUser();
} // end getUser } // end getUser
public void replaceUser(UserContext new_user) public void replaceUser(UserContext new_user)
{ {
if (new_user==null) session.setUser(new_user);
session.removeAttribute(USERCTXT_ATTRIBUTE);
else
session.setAttribute(USERCTXT_ATTRIBUTE,new_user);
user = new_user;
} // end replaceUser } // end replaceUser
@ -1332,6 +1356,7 @@ public class RequestImpl implements RequestInput
public Content[] getSideBoxes() throws AccessError, DataException public Content[] getSideBoxes() throws AccessError, DataException
{ {
UserContext user = session.getUser();
SideBoxManager sbmgr = config.getSideBoxManager(); SideBoxManager sbmgr = config.getSideBoxManager();
List descrs = user.getSideBoxList(); List descrs = user.getSideBoxList();
Content[] rc = new Content[descrs.size()]; Content[] rc = new Content[descrs.size()];
@ -1399,7 +1424,7 @@ public class RequestImpl implements RequestInput
try try
{ // turn the string into a community ID, and thence to a CommunityContext { // turn the string into a community ID, and thence to a CommunityContext
int tmp_id = Integer.parseInt(parm); int tmp_id = Integer.parseInt(parm);
community = user.getCommunityContext(tmp_id); community = session.getUser().getCommunityContext(tmp_id);
if (community==null) if (community==null)
{ // trap any null results (may not be possible with communities, but you never know) { // trap any null results (may not be possible with communities, but you never know)
logger.error("Community #" + tmp_id + " was not found!"); logger.error("Community #" + tmp_id + " was not found!");
@ -1532,36 +1557,6 @@ public class RequestImpl implements RequestInput
} // end setAppAttribute } // end setAppAttribute
public final static Object getSessionAttribute(HttpSession session, String name)
{
return session.getAttribute(SESSION_ATTRIBUTE_STEM + name);
} // end getSessionAttribute
public final static void setSessionAttribute(HttpSession session, String name, Object o)
{
if (o==null)
session.removeAttribute(SESSION_ATTRIBUTE_STEM + name);
else
session.setAttribute(SESSION_ATTRIBUTE_STEM + name,o);
} // end setSessionAttribute
public final static Object getSessionAttribute(HttpServletRequest request, String name)
{
HttpSession session = request.getSession(true);
return ((session!=null) ? getSessionAttribute(session,name) : null);
} // end getSessionAttribute
public final static void setSessionAttribute(HttpServletRequest request, String name, Object o)
{
HttpSession session = request.getSession(true);
if (session!=null)
setSessionAttribute(session,name,o);
} // end setSessionAttribute
public final static Object getRequestAttribute(ServletRequest request, String name) public final static Object getRequestAttribute(ServletRequest request, String name)
{ {
return request.getAttribute(REQUEST_ATTRIBUTE_STEM + name); return request.getAttribute(REQUEST_ATTRIBUTE_STEM + name);

View File

@ -181,6 +181,17 @@ public class XMLLoader
} // end configGetRootElement } // end configGetRootElement
public final Element postGetRootElement(Document doc, String expected_name) throws ValidationException
{
Element rc = doc.getDocumentElement();
if (rc.getTagName().equals(expected_name))
return rc; // we're OK
logger.fatal("posted document is not a <" + expected_name + "/> document (actual root tag: <"
+ rc.getTagName() + "/>)");
throw new ValidationException("root element is not \"" + expected_name + "\"");
} // end postGetRootElement
public final String configGetText(DOMElementHelper h) throws ConfigException public final String configGetText(DOMElementHelper h) throws ConfigException
{ {
String rc = h.getElementText(); String rc = h.getElementText();
@ -189,7 +200,7 @@ public class XMLLoader
logger.fatal("<" + h.getElement().getTagName() + "/> has no value"); logger.fatal("<" + h.getElement().getTagName() + "/> has no value");
throw new ConfigException("no data value found in <" + h.getElement().getTagName() + "/>",h.getElement()); throw new ConfigException("no data value found in <" + h.getElement().getTagName() + "/>",h.getElement());
} // end configGetSubElementText } // end configGetText
public final String configGetText(Element elt) throws ConfigException public final String configGetText(Element elt) throws ConfigException
{ {
@ -208,12 +219,29 @@ public class XMLLoader
} // end configGetSubElementText } // end configGetSubElementText
public final String postGetSubElementText(DOMElementHelper h, String elt_name) throws ValidationException
{
String rc = h.getSubElementText(elt_name);
if (rc!=null)
return rc; // we're OK
logger.fatal("<" + h.getElement().getTagName() + "/> has no <" + elt_name + "/> element");
throw new ValidationException("no \"" + elt_name + "\" element found in \""
+ h.getElement().getTagName() + "\"");
} // end postGetSubElementText
public final String configGetSubElementText(Element elt, String subelt_name) throws ConfigException public final String configGetSubElementText(Element elt, String subelt_name) throws ConfigException
{ {
return configGetSubElementText(new DOMElementHelper(elt),subelt_name); return configGetSubElementText(new DOMElementHelper(elt),subelt_name);
} // end configGetSubElementText } // end configGetSubElementText
public final String postGetSubElementText(Element elt, String subelt_name) throws ValidationException
{
return postGetSubElementText(new DOMElementHelper(elt),subelt_name);
} // end postGetSubElementText
public final Element configGetSubSection(DOMElementHelper h, String sect_name) throws ConfigException public final Element configGetSubSection(DOMElementHelper h, String sect_name) throws ConfigException
{ {
Element rc = h.getSubElement(sect_name); Element rc = h.getSubElement(sect_name);
@ -225,12 +253,29 @@ public class XMLLoader
} // end configGetSubElementText } // end configGetSubElementText
public final Element postGetSubSection(DOMElementHelper h, String sect_name) throws ValidationException
{
Element rc = h.getSubElement(sect_name);
if (rc!=null)
return rc; // we're OK
logger.fatal("<" + h.getElement().getTagName() + "/> has no <" + sect_name + "/> element");
throw new ValidationException("no \"" + sect_name + "\" element found in \""
+ h.getElement().getTagName() + "\"");
} // end postGetSubSection
public final Element configGetSubSection(Element sect, String subsect_name) throws ConfigException public final Element configGetSubSection(Element sect, String subsect_name) throws ConfigException
{ {
return configGetSubSection(new DOMElementHelper(sect),subsect_name); return configGetSubSection(new DOMElementHelper(sect),subsect_name);
} // end configGetSubSection } // end configGetSubSection
public final Element postGetSubSection(Element sect, String subsect_name) throws ValidationException
{
return postGetSubSection(new DOMElementHelper(sect),subsect_name);
} // end postGetSubSection
public final void configVerifyNodeName(Node n, String name, Element enclosing_sect) throws ConfigException public final void configVerifyNodeName(Node n, String name, Element enclosing_sect) throws ConfigException
{ {
if (n.getNodeName().equals(name)) if (n.getNodeName().equals(name))