the XML-RPC endpoint can now invoke scripts as handlers, in addition to
objects of a specified class
This commit is contained in:
parent
6ea41dc619
commit
e3717ca62c
|
@ -32,6 +32,7 @@
|
|||
<mkdir dir="${deploy.home}"/>
|
||||
<mkdir dir="${deploy.home}/WEB-INF"/>
|
||||
<mkdir dir="${deploy.home}/WEB-INF/scripts"/>
|
||||
<mkdir dir="${deploy.home}/WEB-INF/rpcscripts"/>
|
||||
</target>
|
||||
|
||||
<!-- 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 -->
|
||||
<fileset dir="scripts"/>
|
||||
</copy>
|
||||
<copy todir="${deploy.home}/WEB-INF/rpcscripts"> <!-- this copies all the RPC scripts -->
|
||||
<fileset dir="rpcscripts"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- Prepare directory for build (copy everything that requires a restart to take effect) -->
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
<!-- The location of the scripts directory, relative to the application root. -->
|
||||
<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. -->
|
||||
<temp-dir>WEB-INF/temp</temp-dir>
|
||||
|
||||
|
@ -275,7 +278,8 @@
|
|||
<rpc>
|
||||
<xmlrpc-methods>
|
||||
<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="p1" value="${param.0}"/>
|
||||
</method>
|
||||
|
|
24
rpcscripts/test/test1.js
Normal file
24
rpcscripts/test/test1.js
Normal 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
|
|
@ -162,6 +162,10 @@ public interface RequestInput extends LinkTypes
|
|||
|
||||
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 Content[] getSideBoxes() throws AccessError, DataException;
|
||||
|
|
|
@ -56,6 +56,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
|
|||
*/
|
||||
|
||||
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 image_path; // the images path
|
||||
private String static_path; // the static files path
|
||||
|
@ -131,6 +132,23 @@ public class RootConfig implements LinkTypes, ColorSelectors
|
|||
|
||||
} // 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.
|
||||
temp_directory = loader.configGetSubElementText(sect_h,"temp-dir");
|
||||
if (!(temp_directory.startsWith("/")))
|
||||
|
@ -383,7 +401,7 @@ public class RootConfig implements LinkTypes, ColorSelectors
|
|||
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));
|
||||
tmp_alist.add(new XmlRpcMethod(this,(Element)n));
|
||||
|
||||
} // end if
|
||||
|
||||
|
@ -505,7 +523,13 @@ public class RootConfig implements LinkTypes, ColorSelectors
|
|||
{
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package com.silverwrist.venice.ui.rpc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.apache.log4j.*;
|
||||
import org.apache.regexp.*;
|
||||
|
@ -24,6 +25,9 @@ import org.w3c.dom.*;
|
|||
import com.silverwrist.util.*;
|
||||
import com.silverwrist.venice.except.*;
|
||||
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;
|
||||
|
||||
public class XmlRpcMethod
|
||||
|
@ -43,6 +47,7 @@ public class XmlRpcMethod
|
|||
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 String script_name = null; // script name to use as a handler
|
||||
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();
|
||||
String method_name = loader.configGetAttribute(cfg,"name");
|
||||
|
@ -95,6 +100,22 @@ public class XmlRpcMethod
|
|||
throw new ConfigException("object handler for method \"" + "\" not valid",sub);
|
||||
|
||||
} // 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
|
||||
throw new ConfigException("method \"" + method_name + "\" does not have a valid handler",cfg);
|
||||
|
||||
|
@ -164,6 +185,40 @@ public class XmlRpcMethod
|
|||
|
||||
} // 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
|
||||
return new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"dispatch failure");
|
||||
|
||||
|
|
|
@ -389,4 +389,61 @@ public class XmlRpcRequest
|
|||
|
||||
} // 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
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ScriptLibrary
|
|||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public ConferenceContext castConferenceContext(Object o)
|
||||
public final ConferenceContext castConferenceContext(Object o)
|
||||
{
|
||||
if (o instanceof ConferenceContext)
|
||||
return (ConferenceContext)o;
|
||||
|
@ -39,7 +39,7 @@ public class ScriptLibrary
|
|||
|
||||
} // end castConferenceContext
|
||||
|
||||
public ConferenceHotlistEntry castConferenceHotlistEntry(Object o)
|
||||
public final ConferenceHotlistEntry castConferenceHotlistEntry(Object o)
|
||||
{
|
||||
if (o instanceof ConferenceHotlistEntry)
|
||||
return (ConferenceHotlistEntry)o;
|
||||
|
@ -47,7 +47,31 @@ public class ScriptLibrary
|
|||
|
||||
} // 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)
|
||||
return (SideBoxDescriptor)o;
|
||||
|
@ -55,7 +79,7 @@ public class ScriptLibrary
|
|||
|
||||
} // end castSideBoxDescriptor
|
||||
|
||||
public TopicMessageContext castTopicMessageContext(Object o)
|
||||
public final TopicMessageContext castTopicMessageContext(Object o)
|
||||
{
|
||||
if (o instanceof TopicMessageContext)
|
||||
return (TopicMessageContext)o;
|
||||
|
@ -63,7 +87,7 @@ public class ScriptLibrary
|
|||
|
||||
} // end castTopicMessageContext
|
||||
|
||||
public UserFound castUserFound(Object o)
|
||||
public final UserFound castUserFound(Object o)
|
||||
{
|
||||
if (o instanceof UserFound)
|
||||
return (UserFound)o;
|
||||
|
@ -71,7 +95,7 @@ public class ScriptLibrary
|
|||
|
||||
} // end castUserSideBoxDescriptor
|
||||
|
||||
public UserSideBoxDescriptor castUserSideBoxDescriptor(Object o)
|
||||
public final UserSideBoxDescriptor castUserSideBoxDescriptor(Object o)
|
||||
{
|
||||
if (o instanceof UserSideBoxDescriptor)
|
||||
return (UserSideBoxDescriptor)o;
|
||||
|
@ -79,43 +103,61 @@ public class ScriptLibrary
|
|||
|
||||
} // end castUserSideBoxDescriptor
|
||||
|
||||
public boolean[] createBooleanArray(int len)
|
||||
public final boolean[] createBooleanArray(int len)
|
||||
{
|
||||
return new boolean[len];
|
||||
|
||||
} // end createBooleanArray
|
||||
|
||||
public int[] createIntArray(int len)
|
||||
public final int[] createIntArray(int len)
|
||||
{
|
||||
return new int[len];
|
||||
|
||||
} // 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();
|
||||
|
||||
} // end done
|
||||
|
||||
public boolean emptyString(String s)
|
||||
public final boolean emptyString(String s)
|
||||
{
|
||||
return StringUtil.isStringEmpty(s);
|
||||
|
||||
} // end emptyString
|
||||
|
||||
public String encodeHTML(String s)
|
||||
public final String encodeHTML(String s)
|
||||
{
|
||||
return StringUtil.encodeHTML(s);
|
||||
|
||||
} // end encodeHTML
|
||||
|
||||
public String encodeURL(String s)
|
||||
public final String encodeURL(String s)
|
||||
{
|
||||
return URLEncoder.encode(s);
|
||||
|
||||
} // end encodeURL
|
||||
|
||||
public String exceptionType(Object o) throws ScriptExit
|
||||
public final String exceptionType(Object o) throws ScriptExit
|
||||
{
|
||||
if (o instanceof ScriptExit)
|
||||
throw (ScriptExit)o; // rethrow ScriptExit exceptions
|
||||
|
@ -126,19 +168,19 @@ public class ScriptLibrary
|
|||
|
||||
} // end exceptionType
|
||||
|
||||
public String join(List l, String separator)
|
||||
public final String join(List l, String separator)
|
||||
{
|
||||
return StringUtil.join(l,separator);
|
||||
|
||||
} // end join
|
||||
|
||||
public List splitList(String data, String delims)
|
||||
public final List splitList(String data, String delims)
|
||||
{
|
||||
return StringUtil.splitList(data,delims);
|
||||
|
||||
} // end splitList
|
||||
|
||||
public boolean validVeniceID(String s)
|
||||
public final boolean validVeniceID(String s)
|
||||
{
|
||||
return IDUtils.isValidVeniceID(s);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (new_cookies==null)
|
||||
|
@ -1310,31 +1340,7 @@ public class RequestImpl implements RequestInput
|
|||
|
||||
public String getScriptLoggerName(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("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();
|
||||
return createLoggerName("SCRIPT.",raw_name);
|
||||
|
||||
} // end getScriptLoggerName
|
||||
|
||||
|
@ -1348,6 +1354,18 @@ public class RequestImpl implements RequestInput
|
|||
|
||||
} // 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)
|
||||
{
|
||||
return config.getDialog(name);
|
||||
|
|
Loading…
Reference in New Issue
Block a user