the XML-RPC endpoint can now invoke scripts as handlers, in addition to

objects of a specified class
This commit is contained in:
Eric J. Bowersox 2002-01-16 17:39:09 +00:00
parent 6ea41dc619
commit e3717ca62c
9 changed files with 277 additions and 45 deletions

View File

@ -32,6 +32,7 @@
<mkdir dir="${deploy.home}"/> <mkdir dir="${deploy.home}"/>
<mkdir dir="${deploy.home}/WEB-INF"/> <mkdir dir="${deploy.home}/WEB-INF"/>
<mkdir dir="${deploy.home}/WEB-INF/scripts"/> <mkdir dir="${deploy.home}/WEB-INF/scripts"/>
<mkdir dir="${deploy.home}/WEB-INF/rpcscripts"/>
</target> </target>
<!-- Copy everything to the application directory that can be updated without a restart. --> <!-- Copy everything to the application directory that can be updated without a restart. -->
@ -42,6 +43,9 @@
<copy todir="${deploy.home}/WEB-INF/scripts"> <!-- this copies all the scripts --> <copy todir="${deploy.home}/WEB-INF/scripts"> <!-- this copies all the scripts -->
<fileset dir="scripts"/> <fileset dir="scripts"/>
</copy> </copy>
<copy todir="${deploy.home}/WEB-INF/rpcscripts"> <!-- this copies all the RPC scripts -->
<fileset dir="rpcscripts"/>
</copy>
</target> </target>
<!-- Prepare directory for build (copy everything that requires a restart to take effect) --> <!-- Prepare directory for build (copy everything that requires a restart to take effect) -->

View File

@ -28,6 +28,9 @@
<!-- The location of the scripts directory, relative to the application root. --> <!-- The location of the scripts directory, relative to the application root. -->
<script-dir>WEB-INF/scripts</script-dir> <script-dir>WEB-INF/scripts</script-dir>
<!-- The location of the RPC scripts directory, relative to the application root. -->
<rpc-script-dir>WEB-INF/rpcscripts</rpc-script-dir>
<!-- The temporary directory for script compilation, relative to the application root. --> <!-- The temporary directory for script compilation, relative to the application root. -->
<temp-dir>WEB-INF/temp</temp-dir> <temp-dir>WEB-INF/temp</temp-dir>
@ -275,7 +278,8 @@
<rpc> <rpc>
<xmlrpc-methods> <xmlrpc-methods>
<method name="venice:test\.sumDifference"> <method name="venice:test\.sumDifference">
<object class="com.silverwrist.venice.ui.rpc.XmlRpcTestHandler"/> <!-- <object class="com.silverwrist.venice.ui.rpc.XmlRpcTestHandler"/> -->
<script name="test/test1.js"/>
<env name="e1" value="foo"/> <env name="e1" value="foo"/>
<env name="p1" value="${param.0}"/> <env name="p1" value="${param.0}"/>
</method> </method>

24
rpcscripts/test/test1.js Normal file
View File

@ -0,0 +1,24 @@
// test of RPC code
importPackage(java.util);
importPackage(Packages.com.silverwrist.venice.ui.rpc);
xreq = bsf.lookupBean("xmlrpc");
if ("venice:test.sumDifference"==xreq.method)
{ // implement the sumDifference API function call
if (xreq.paramCount!=2)
vlib.output(new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter count mismatch"));
else
{ // get the parameters and convert them
v1 = xreq.getParamInt(0);
v2 = xreq.getParamInt(1);
// return the result
rc = vlib.createMap();
rc.put("sum",vlib.createInteger(v1 + v2));
rc.put("difference",vlib.createInteger(v1 - v2));
vlib.output(rc);
} // end else
vlib.done();
} // end if

View File

@ -162,6 +162,10 @@ public interface RequestInput extends LinkTypes
public abstract String getScriptLoggerName(); public abstract String getScriptLoggerName();
public abstract String getRPCScriptName(String raw_name);
public abstract String getRPCScriptLoggerName(String raw_name);
public abstract Dialog getDialog(String name); public abstract Dialog getDialog(String name);
public abstract Content[] getSideBoxes() throws AccessError, DataException; public abstract Content[] getSideBoxes() throws AccessError, DataException;

View File

@ -56,6 +56,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
*/ */
private String script_directory; // the scripts directory private String script_directory; // the scripts directory
private String rpc_script_directory; // the RPC scripts directory
private String temp_directory; // the temporary directory private String temp_directory; // the temporary directory
private String image_path; // the images path private String image_path; // the images path
private String static_path; // the static files path private String static_path; // the static files path
@ -131,6 +132,23 @@ public class RootConfig implements LinkTypes, ColorSelectors
} // end if } // end if
// Get the full pathname of the RPC script directory.
rpc_script_directory = loader.configGetSubElementText(sect_h,"rpc-script-dir");
if (!(rpc_script_directory.startsWith("/")))
rpc_script_directory = root_file_path + rpc_script_directory;
if (!(rpc_script_directory.endsWith("/")))
rpc_script_directory = rpc_script_directory + "/";
// Test to make sure the RPC script directory exists.
t_file = new File(rpc_script_directory);
if (!(t_file.isDirectory()))
{ // script directory does not exist - throw exception
logger.fatal("<rpc-script-dir/> directory \"" + rpc_script_directory + "\" is not a directory");
throw new ConfigException("specified <rpc-script-dir/> is not a directory",
sect_h.getSubElement("rpc-script-dir"));
} // end if
// Get the full pathname of the temporary directory. // Get the full pathname of the temporary directory.
temp_directory = loader.configGetSubElementText(sect_h,"temp-dir"); temp_directory = loader.configGetSubElementText(sect_h,"temp-dir");
if (!(temp_directory.startsWith("/"))) if (!(temp_directory.startsWith("/")))
@ -383,7 +401,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
if (n.getNodeType()==Node.ELEMENT_NODE) if (n.getNodeType()==Node.ELEMENT_NODE)
{ // look for a <method/> element and use it to initialize a method { // look for a <method/> element and use it to initialize a method
if (n.getNodeName().equals("method")) if (n.getNodeName().equals("method"))
tmp_alist.add(new XmlRpcMethod((Element)n)); tmp_alist.add(new XmlRpcMethod(this,(Element)n));
} // end if } // end if
@ -505,7 +523,13 @@ public class RootConfig implements LinkTypes, ColorSelectors
{ {
return script_directory + sname; return script_directory + sname;
} // end script_directory } // end getScriptPath
public final String getRPCScriptPath(String sname)
{
return rpc_script_directory + sname;
} // end getRPCScriptPath
public final String getFrameJSPName() public final String getFrameJSPName()
{ {

View File

@ -17,6 +17,7 @@
*/ */
package com.silverwrist.venice.ui.rpc; package com.silverwrist.venice.ui.rpc;
import java.io.*;
import java.util.*; import java.util.*;
import org.apache.log4j.*; import org.apache.log4j.*;
import org.apache.regexp.*; import org.apache.regexp.*;
@ -24,6 +25,9 @@ import org.w3c.dom.*;
import com.silverwrist.util.*; import com.silverwrist.util.*;
import com.silverwrist.venice.except.*; import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*; import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.config.RootConfig;
import com.silverwrist.venice.ui.helpers.ThrowableContent;
import com.silverwrist.venice.ui.script.*;
import com.silverwrist.venice.util.XMLLoader; import com.silverwrist.venice.util.XMLLoader;
public class XmlRpcMethod public class XmlRpcMethod
@ -43,6 +47,7 @@ public class XmlRpcMethod
private REProgram method_pgm; // regular expression program to match method name private REProgram method_pgm; // regular expression program to match method name
private String remap_value = null; // remap value private String remap_value = null; // remap value
private Class obj_class = null; // "class" handler for object private Class obj_class = null; // "class" handler for object
private String script_name = null; // script name to use as a handler
private Map raw_env; // "raw" environment private Map raw_env; // "raw" environment
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
@ -50,7 +55,7 @@ public class XmlRpcMethod
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
public XmlRpcMethod(Element cfg) throws ConfigException public XmlRpcMethod(RootConfig root, Element cfg) throws ConfigException
{ {
XMLLoader loader = XMLLoader.get(); XMLLoader loader = XMLLoader.get();
String method_name = loader.configGetAttribute(cfg,"name"); String method_name = loader.configGetAttribute(cfg,"name");
@ -95,6 +100,22 @@ public class XmlRpcMethod
throw new ConfigException("object handler for method \"" + "\" not valid",sub); throw new ConfigException("object handler for method \"" + "\" not valid",sub);
} // end if } // end if
else if ((sub = cfg_h.getSubElement("script"))!=null)
{ // we're trying to use a script - make sure it has a valid attribute
DOMElementHelper sub_h = new DOMElementHelper(sub);
if (sub_h.hasAttribute("name"))
{ // valid namwe - now verify that the script exists
script_name = sub.getAttribute("name");
File test = new File(root.getRPCScriptPath(script_name));
if (!(test.canRead()))
throw new ConfigException("object handler script \"" + script_name
+ "\" is not a valid script file",sub);
} // end if
else // no referent for object handler - bail out now
throw new ConfigException("object handler for method \"" + "\" not valid",sub);
} // end else if
else // no handler - this is an error else // no handler - this is an error
throw new ConfigException("method \"" + method_name + "\" does not have a valid handler",cfg); throw new ConfigException("method \"" + method_name + "\" does not have a valid handler",cfg);
@ -164,6 +185,40 @@ public class XmlRpcMethod
} // end if } // end if
if (script_name!=null)
{ // script method call - prepare the script and execute it
String full_name = req.getRPCScriptName(script_name);
String logger_name = req.getRPCScriptLoggerName(script_name);
if (logger.isDebugEnabled())
logger.debug("EXECUTING " + full_name);
try
{ // execute the script!
ScriptManager smgr = req.getScriptManager();
smgr.pushContext();
smgr.register("xmlrpc",xreq);
smgr.register("environment",env);
ScriptReturn sro = new ScriptReturn();
smgr.exec(new File(full_name),logger_name,sro);
smgr.popContext();
return sro.get();
} // end try
catch (ScriptingException se)
{ // script error! we are not amused...
return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"scripting error: " + se.toString());
} // end catch
catch (ThrowableContent tc)
{ // this could be an XmlRpcFault, but maybe not
if (tc instanceof XmlRpcFault)
return tc;
else
return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"application error: " + tc.toString());
} // end catch
} // end if
// unable to dispatch things // unable to dispatch things
return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"dispatch failure"); return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"dispatch failure");

View File

@ -389,4 +389,61 @@ public class XmlRpcRequest
} // end getParam } // end getParam
public final String getParamType(int ndx)
{
Object foo = method_params.get(ndx);
if (foo instanceof Integer)
return "int";
if (foo instanceof Boolean)
return "boolean";
if (foo instanceof String)
return "string";
if (foo instanceof Double)
return "double";
if (foo instanceof Date)
return "dateTime.iso8601";
if (foo instanceof byte[])
return "base64";
if (foo instanceof Map)
return "struct";
if (foo instanceof List)
return "array";
return "(unknown)";
} // end getParamType
public final int getParamInt(int ndx) throws XmlRpcFault
{
Object foo = method_params.get(ndx);
if (foo instanceof Integer)
return ((Integer)foo).intValue();
else if (foo instanceof Boolean)
return ((Boolean)foo).booleanValue() ? 1 : 0;
else
throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch");
} // end getParamInt
public final double getParamDouble(int ndx) throws XmlRpcFault
{
Object foo = method_params.get(ndx);
if ((foo instanceof Integer) || (foo instanceof Double))
return ((Number)foo).doubleValue();
else if (foo instanceof Boolean)
return ((Boolean)foo).booleanValue() ? 1 : 0;
else
throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch");
} // end getParamDouble
public final String getParamString(int ndx) throws XmlRpcFault
{
Object foo = method_params.get(ndx);
if ((foo instanceof byte[]) || (foo instanceof List) || (foo instanceof Map))
throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch");
return foo.toString();
} // end getParamString
} // end class XmlRpcRequest } // end class XmlRpcRequest

View File

@ -31,7 +31,7 @@ public class ScriptLibrary
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
public ConferenceContext castConferenceContext(Object o) public final ConferenceContext castConferenceContext(Object o)
{ {
if (o instanceof ConferenceContext) if (o instanceof ConferenceContext)
return (ConferenceContext)o; return (ConferenceContext)o;
@ -39,7 +39,7 @@ public class ScriptLibrary
} // end castConferenceContext } // end castConferenceContext
public ConferenceHotlistEntry castConferenceHotlistEntry(Object o) public final ConferenceHotlistEntry castConferenceHotlistEntry(Object o)
{ {
if (o instanceof ConferenceHotlistEntry) if (o instanceof ConferenceHotlistEntry)
return (ConferenceHotlistEntry)o; return (ConferenceHotlistEntry)o;
@ -47,7 +47,31 @@ public class ScriptLibrary
} // end castConferenceHotlistEntry } // end castConferenceHotlistEntry
public SideBoxDescriptor castSideBoxDescriptor(Object o) public final Date castDate(Object o)
{
if (o instanceof Date)
return (Date)o;
throw new ClassCastException("ScriptLibrary.castDate: invalid cast");
} // end castDate
public final List castList(Object o)
{
if (o instanceof List)
return (List)o;
throw new ClassCastException("ScriptLibrary.castList: invalid cast");
} // end castList
public final Map castMap(Object o)
{
if (o instanceof Map)
return (Map)o;
throw new ClassCastException("ScriptLibrary.castMap: invalid cast");
} // end castMap
public final SideBoxDescriptor castSideBoxDescriptor(Object o)
{ {
if (o instanceof SideBoxDescriptor) if (o instanceof SideBoxDescriptor)
return (SideBoxDescriptor)o; return (SideBoxDescriptor)o;
@ -55,7 +79,7 @@ public class ScriptLibrary
} // end castSideBoxDescriptor } // end castSideBoxDescriptor
public TopicMessageContext castTopicMessageContext(Object o) public final TopicMessageContext castTopicMessageContext(Object o)
{ {
if (o instanceof TopicMessageContext) if (o instanceof TopicMessageContext)
return (TopicMessageContext)o; return (TopicMessageContext)o;
@ -63,7 +87,7 @@ public class ScriptLibrary
} // end castTopicMessageContext } // end castTopicMessageContext
public UserFound castUserFound(Object o) public final UserFound castUserFound(Object o)
{ {
if (o instanceof UserFound) if (o instanceof UserFound)
return (UserFound)o; return (UserFound)o;
@ -71,7 +95,7 @@ public class ScriptLibrary
} // end castUserSideBoxDescriptor } // end castUserSideBoxDescriptor
public UserSideBoxDescriptor castUserSideBoxDescriptor(Object o) public final UserSideBoxDescriptor castUserSideBoxDescriptor(Object o)
{ {
if (o instanceof UserSideBoxDescriptor) if (o instanceof UserSideBoxDescriptor)
return (UserSideBoxDescriptor)o; return (UserSideBoxDescriptor)o;
@ -79,43 +103,61 @@ public class ScriptLibrary
} // end castUserSideBoxDescriptor } // end castUserSideBoxDescriptor
public boolean[] createBooleanArray(int len) public final boolean[] createBooleanArray(int len)
{ {
return new boolean[len]; return new boolean[len];
} // end createBooleanArray } // end createBooleanArray
public int[] createIntArray(int len) public final int[] createIntArray(int len)
{ {
return new int[len]; return new int[len];
} // end createIntArray } // end createIntArray
public void done() throws ScriptExit public final Integer createInteger(int value)
{
return new Integer(value);
} // end createInteger
public final List createList()
{
return new ArrayList();
} // end createList
public final Map createMap()
{
return new HashMap();
} // end createMap
public final void done() throws ScriptExit
{ {
throw new ScriptExit(); throw new ScriptExit();
} // end done } // end done
public boolean emptyString(String s) public final boolean emptyString(String s)
{ {
return StringUtil.isStringEmpty(s); return StringUtil.isStringEmpty(s);
} // end emptyString } // end emptyString
public String encodeHTML(String s) public final String encodeHTML(String s)
{ {
return StringUtil.encodeHTML(s); return StringUtil.encodeHTML(s);
} // end encodeHTML } // end encodeHTML
public String encodeURL(String s) public final String encodeURL(String s)
{ {
return URLEncoder.encode(s); return URLEncoder.encode(s);
} // end encodeURL } // end encodeURL
public String exceptionType(Object o) throws ScriptExit public final String exceptionType(Object o) throws ScriptExit
{ {
if (o instanceof ScriptExit) if (o instanceof ScriptExit)
throw (ScriptExit)o; // rethrow ScriptExit exceptions throw (ScriptExit)o; // rethrow ScriptExit exceptions
@ -126,19 +168,19 @@ public class ScriptLibrary
} // end exceptionType } // end exceptionType
public String join(List l, String separator) public final String join(List l, String separator)
{ {
return StringUtil.join(l,separator); return StringUtil.join(l,separator);
} // end join } // end join
public List splitList(String data, String delims) public final List splitList(String data, String delims)
{ {
return StringUtil.splitList(data,delims); return StringUtil.splitList(data,delims);
} // end splitList } // end splitList
public boolean validVeniceID(String s) public final boolean validVeniceID(String s)
{ {
return IDUtils.isValidVeniceID(s); return IDUtils.isValidVeniceID(s);

View File

@ -711,6 +711,36 @@ public class RequestImpl implements RequestInput
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
private static final String createLoggerName(String prefix, String raw_name)
{
// Strip all extensions from the end of the file.
int limit = raw_name.lastIndexOf('/');
int x = raw_name.lastIndexOf('.');
while (x>limit)
{ // remove all extensions from the end
raw_name = raw_name.substring(0,x);
x = raw_name.lastIndexOf('.');
} // end while
// convert the name to a logger name
StringBuffer rc = new StringBuffer(prefix);
for (x=0; x<raw_name.length(); x++)
{ // process all the characters
char c = raw_name.charAt(x);
if (c=='/')
rc.append('.');
else if (c=='.')
rc.append('_');
else
rc.append(c);
} // end for
return rc.toString();
} // end createLoggerName
private final void putCookie(Cookie cookie) private final void putCookie(Cookie cookie)
{ {
if (new_cookies==null) if (new_cookies==null)
@ -1310,31 +1340,7 @@ public class RequestImpl implements RequestInput
public String getScriptLoggerName(String raw_name) public String getScriptLoggerName(String raw_name)
{ {
// Strip all extensions from the end of the file. return createLoggerName("SCRIPT.",raw_name);
int limit = raw_name.lastIndexOf('/');
int x = raw_name.lastIndexOf('.');
while (x>limit)
{ // remove all extensions from the end
raw_name = raw_name.substring(0,x);
x = raw_name.lastIndexOf('.');
} // end while
// convert the name to a logger name
StringBuffer rc = new StringBuffer("SCRIPT.");
for (x=0; x<raw_name.length(); x++)
{ // process all the characters
char c = raw_name.charAt(x);
if (c=='/')
rc.append('.');
else if (c=='.')
rc.append('_');
else
rc.append(c);
} // end for
return rc.toString();
} // end getScriptLoggerName } // end getScriptLoggerName
@ -1348,6 +1354,18 @@ public class RequestImpl implements RequestInput
} // end getScriptLoggerName } // end getScriptLoggerName
public String getRPCScriptName(String raw_name)
{
return config.getRPCScriptPath(raw_name);
} // end getScriptName
public String getRPCScriptLoggerName(String raw_name)
{
return createLoggerName("RPCSCRIPT.",raw_name);
} // end getScriptLoggerName
public Dialog getDialog(String name) public Dialog getDialog(String name)
{ {
return config.getDialog(name); return config.getDialog(name);