diff --git a/etc/ui-config.xml b/etc/ui-config.xml
index a2cb493..d192f1e 100644
--- a/etc/ui-config.xml
+++ b/etc/ui-config.xml
@@ -271,6 +271,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/web.xml b/etc/web.xml
index 87396f9..8f6afb8 100644
--- a/etc/web.xml
+++ b/etc/web.xml
@@ -119,6 +119,12 @@
com.silverwrist.venice.ui.servlet.RemapperServlet
+
+ XmlRpc
+ Handles XML-RPC calls for the application.
+ com.silverwrist.venice.ui.rpc.XmlRpcServlet
+
+
@@ -182,6 +188,11 @@
/verifyemail
+
+ XmlRpc
+ /RPC2
+
+
60
diff --git a/lib/.gitignore b/lib/.gitignore
index 8bc3108..a93d63b 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -1,7 +1,8 @@
bsf.jar
jacl.jar
+jakarta-regexp*.jar
js.jar
log4j.jar
mysql.jar
mm.mysql*.jar
-tcljava.jar
\ No newline at end of file
+tcljava.jar
diff --git a/lib/README.lib b/lib/README.lib
index 4b392a9..1382f87 100644
--- a/lib/README.lib
+++ b/lib/README.lib
@@ -6,6 +6,7 @@ compatible with the versions specified here.
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
Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory
Jacl (Tcl interpreter) 1.3(CVS) jacl.jar, tcljava.jar Venice "lib" subdirectory
diff --git a/scripts/logout.js b/scripts/logout.js
index 391828d..536496b 100644
--- a/scripts/logout.js
+++ b/scripts/logout.js
@@ -31,8 +31,7 @@ if (user.isLoggedIn())
{ // user is logged in - we want to log out
// TODO: only remove the login cookie if it was actually set!
rinput.deleteCookie(RequestInput.LOGIN_COOKIE); // remove the login cookie
- rinput.replaceUser(null); // no more user context
- rinput.setSessionAttribute(RequestInput.LEFT_MENU_SESSION_ATTR,null); // and clear menus too
+ rinput.endSession();
target = "top.js.vs"; // take 'em back to the top
diff --git a/src/com/silverwrist/venice/ui/NullSession.java b/src/com/silverwrist/venice/ui/NullSession.java
new file mode 100644
index 0000000..a1e8ec3
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/NullSession.java
@@ -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 .
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/RequestInput.java b/src/com/silverwrist/venice/ui/RequestInput.java
index 3c8ec2f..81df735 100644
--- a/src/com/silverwrist/venice/ui/RequestInput.java
+++ b/src/com/silverwrist/venice/ui/RequestInput.java
@@ -11,7 +11,7 @@
*
* The Initial Developer of the Original Code is Eric J. Bowersox ,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
- * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
+import org.w3c.dom.Document;
import com.silverwrist.util.ServletMultipartException;
import com.silverwrist.venice.core.CommunityContext;
import com.silverwrist.venice.core.UserContext;
@@ -53,6 +54,8 @@ public interface RequestInput extends LinkTypes
public abstract String getSourceAddress();
+ public abstract void endSession();
+
public abstract boolean hasParameter(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 Document getRequestDocument();
+
+ public abstract boolean sessionBound();
+
public abstract boolean isImageButtonClicked(String name);
public abstract Object getAppAttribute(String name);
diff --git a/src/com/silverwrist/venice/ui/VeniceUISession.java b/src/com/silverwrist/venice/ui/VeniceUISession.java
new file mode 100644
index 0000000..d06908f
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/VeniceUISession.java
@@ -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 .
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/VeniceUISessionFactory.java b/src/com/silverwrist/venice/ui/VeniceUISessionFactory.java
new file mode 100644
index 0000000..fdf998d
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/VeniceUISessionFactory.java
@@ -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 .
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/config/RootConfig.java b/src/com/silverwrist/venice/ui/config/RootConfig.java
index e5452ba..972898f 100644
--- a/src/com/silverwrist/venice/ui/config/RootConfig.java
+++ b/src/com/silverwrist/venice/ui/config/RootConfig.java
@@ -11,7 +11,7 @@
*
* The Initial Developer of the Original Code is Eric J. Bowersox ,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
- * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* 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.Menu;
import com.silverwrist.venice.ui.menus.MenuComponent;
+import com.silverwrist.venice.ui.rpc.XmlRpcMethod;
import com.silverwrist.venice.util.*;
public class RootConfig implements LinkTypes, ColorSelectors
@@ -79,6 +80,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
private ButtonHolder buttons; // the button definitions
private String[] content_hdr; // the content header parts
private Remapper remapper; // the URL remapper
+ private List xmlrpc_methods; // the list of XML-RPC methods
private StockMessages stock_messages; // the stock messages
private Map menus; // the menus
private DialogManager dialogs; // the dialog manager
@@ -324,7 +326,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
for (i=0; i section.
+ sect = loader.configGetSubSection(root_h,"rpc");
+ sect_h = new DOMElementHelper(sect);
+
+ // Get the section.
+ sect1 = loader.configGetSubSection(sect_h,"xmlrpc-methods");
+ nl = sect1.getChildNodes();
+ ArrayList tmp_alist = new ArrayList();
+ for (i=0; i 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 section.
sect = loader.configGetSubSection(root_h,"messages");
@@ -718,6 +749,12 @@ public class RootConfig implements LinkTypes, ColorSelectors
} // end getDefaultServletAddress
+ public final List getXmlRpcMethods()
+ {
+ return xmlrpc_methods;
+
+ } // end getXmlRpcMethods
+
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcDispatch.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcDispatch.java
new file mode 100644
index 0000000..4935d19
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcDispatch.java
@@ -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 .
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcFault.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcFault.java
new file mode 100644
index 0000000..2da3e61
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcFault.java
@@ -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 .
+ *
+ * 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) 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("\r\n\r\n\r\n"
+ + "faultCode\r\n");
+ b.append(fault_code);
+ b.append("\r\n\r\n\r\nfaultString\r\n");
+ b.append(StringUtil.encodeHTML(getMessage()));
+ b.append("\r\n\r\n\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
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcMethod.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcMethod.java
new file mode 100644
index 0000000..1855063
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcMethod.java
@@ -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 .
+ *
+ * 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) 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.
+ *
+ * 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) 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 children of the node
+ NodeList nl = params.getChildNodes();
+ for (int i=0; i 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 elements within the 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 elements within a 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
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcSelfSerializer.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcSelfSerializer.java
new file mode 100644
index 0000000..c4194b9
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcSelfSerializer.java
@@ -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 .
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java
new file mode 100644
index 0000000..2169bbd
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java
@@ -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 .
+ *
+ * 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) 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 "" + (b ? "1" : "0") + "";
+
+ } // end serialize
+
+ public final String serialize(byte b)
+ {
+ return this.serialize((int)b);
+
+ } // end serialize
+
+ public final String serialize(char c)
+ {
+ return "" + c + "";
+
+ } // end serialize
+
+ public final String serialize(double d)
+ {
+ return "" + d + "";
+
+ } // end serialize
+
+ public final String serialize(float f)
+ {
+ return this.serialize((double)f);
+
+ } // end serialize
+
+ public final String serialize(int i)
+ {
+ return "" + i + "";
+
+ } // 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("\r\n\r\n");
+ for (int i=0; i").append(this.serialize(ba[i])).append("\r\n");
+ b.append("\r\n");
+ 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("\r\n\r\n");
+ for (int i=0; i").append(this.serialize(ca[i])).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(double[] da)
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize(da[i])).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(float[] fa)
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize((double)(fa[i]))).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(int[] ia)
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize(ia[i])).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(long[] la)
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize((double)(la[i]))).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(short[] sa)
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize((int)(sa[i]))).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serialize(Object[] arr) throws XmlRpcFault
+ {
+ StringBuffer b = new StringBuffer("\r\n\r\n");
+ for (int i=0; i").append(this.serialize(arr[i])).append("\r\n");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serialize
+
+ public final String serializeBean(Object obj, BeanInfo binf) throws XmlRpcFault
+ {
+ PropertyDescriptor[] props = binf.getPropertyDescriptors();
+ StringBuffer b = new StringBuffer("\r\n");
+ final Object[] no_params = new Object[0];
+ for (int i=0; i\r\n").append(StringUtil.encodeHTML(props[i].getName()));
+ b.append("\r\n").append(this.serialize(mread.invoke(obj,no_params)));
+ b.append("\r\n\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("\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("");
+ 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("");
+
+ // 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("\r\n\r\n");
+ while (enum.hasMoreElements())
+ b.append("").append(this.serialize(enum.nextElement())).append("");
+ b.append("\r\n");
+ 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("");
+ InputStreamReader rd = new InputStreamReader(internal2_stm,"US-ASCII");
+ IOUtil.copy(rd,wr);
+ IOUtil.shutdown(rd);
+ IOUtil.shutdown(internal2_stm);
+ wr.write("");
+
+ // 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("\r\n\r\n");
+ while (it.hasNext())
+ b.append("").append(this.serialize(it.next())).append("");
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serializeIterator
+
+ public final String serializeMap(Map m) throws XmlRpcFault
+ {
+ StringBuffer b = new StringBuffer("\r\n");
+ Iterator it = m.entrySet().iterator();
+ while (it.hasNext())
+ { // serialize each entry in turn
+ Map.Entry ntry = (Map.Entry)(it.next());
+ b.append("\r\n").append(StringUtil.encodeHTML(ntry.getKey().toString()));
+ b.append("\r\n").append(this.serialize(ntry.getValue()));
+ b.append("\r\n\r\n");
+
+ } // end while
+
+ b.append("\r\n");
+ return b.toString();
+
+ } // end serializeMap
+
+ public final String serializeString(String s)
+ {
+ if (s==null)
+ return "";
+ return "" + StringUtil.encodeHTML(s) + "";
+
+ } // end serializeString
+
+ /*--------------------------------------------------------------------------------
+ * External static operations
+ *--------------------------------------------------------------------------------
+ */
+
+ public static final synchronized XmlRpcSerializer get()
+ {
+ if (self==null)
+ self = new XmlRpcSerializer();
+ return self;
+
+ } // end get
+
+} // end class XmlRpcSerializer
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java
new file mode 100644
index 0000000..a5ceae1
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java
@@ -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 .
+ *
+ * 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) 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("\r\n\r\n");
+ 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("\r\n\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.
+ *
+ * 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) 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
diff --git a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java
index 1d00e7c..4cd2f54 100644
--- a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java
+++ b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java
@@ -11,7 +11,7 @@
*
* The Initial Developer of the Original Code is Eric J. Bowersox ,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
- * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@@ -34,6 +34,38 @@ import com.silverwrist.venice.ui.script.ScriptManagerContainer;
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
*--------------------------------------------------------------------------------
@@ -49,6 +81,8 @@ public abstract class BaseServlet extends HttpServlet
private static Category logger = Category.getInstance(BaseServlet.class);
+ private static VeniceUISessionFactory factory = new HttpSessionFactory();
+
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
@@ -56,14 +90,16 @@ public abstract class BaseServlet extends HttpServlet
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);
if (e instanceof ScriptingException)
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);
} // end translateException
@@ -77,13 +113,41 @@ public abstract class BaseServlet extends HttpServlet
try
{ // create the actual request implementation
ServletContext ctxt = getServletContext();
- RequestImpl the_request =
- new RequestImpl(ctxt,request,response,(VeniceEngine)(ctxt.getAttribute(ENGINE_ATTRIBUTE)),
- (RootConfig)(ctxt.getAttribute(UICONFIG_ATTRIBUTE)));
+ RequestImpl the_request = null;
+ try
+ { // 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();
// 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)
NDC.push(the_request.getUser().getUserName());
@@ -176,6 +240,12 @@ public abstract class BaseServlet extends HttpServlet
{ // default does nothing
} // end init
+ protected VeniceUISessionFactory getSessionFactory()
+ {
+ return factory;
+
+ } // end getSessionFactory
+
protected Object translateServletException(RequestInput ri, Exception e)
{
return null; // does nothing by default
diff --git a/src/com/silverwrist/venice/ui/servlet/HttpVeniceUISession.java b/src/com/silverwrist/venice/ui/servlet/HttpVeniceUISession.java
new file mode 100644
index 0000000..51c8b34
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/servlet/HttpVeniceUISession.java
@@ -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 .
+ *
+ * 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) 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,
* 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):
*/
@@ -39,6 +39,7 @@ 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
{
@@ -553,9 +554,6 @@ public class RequestImpl implements RequestInput
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 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_INPUT = "com.silverwrist.venice.ui.RequestInput";
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 HttpServletRequest request; // the servlet request 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 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 ArrayList new_cookies = null; // cookies to be added to 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 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
/*--------------------------------------------------------------------------------
* Constructor
@@ -592,94 +590,88 @@ public class RequestImpl implements RequestInput
*/
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.
this.ctxt = ctxt;
this.request = request;
this.response = response;
- this.session = request.getSession(true);
this.engine = engine;
this.config = config;
- // Create or retrieve the user context.
- user = (UserContext)(session.getAttribute(USERCTXT_ATTRIBUTE));
- if (user==null)
- { // the user context isn't present yet
+ 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
+
+ // 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
- { // 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 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
{
String rc = h.getElementText();
@@ -189,7 +200,7 @@ public class XMLLoader
logger.fatal("<" + h.getElement().getTagName() + "/> has no value");
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
{
@@ -208,12 +219,29 @@ public class XMLLoader
} // 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
{
return configGetSubElementText(new DOMElementHelper(elt),subelt_name);
} // 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
{
Element rc = h.getSubElement(sect_name);
@@ -225,12 +253,29 @@ public class XMLLoader
} // 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
{
return configGetSubSection(new DOMElementHelper(sect),subsect_name);
} // 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
{
if (n.getNodeName().equals(name))