How to build a Scripting Runtime?
Contents
How to build a Scripting Runtime?
What the Scripting Framework Provides
What a new Runtime needs to provide:
Loading and running the script
Passing Useful data to the Script
Parameters passed to the Script
Current Runtimes invocation Parameter support
Framework invocation Parameter support
Reference
Developer's Guide:
Scripting Framework Online API documentation:
http://framework.openoffice.org/scripting/EDR-IDLDocs/drafts/com/sun/star/script/framework
Scripting Framework Website:
http://framework.openoffice.org/scripting
Introduction
By creating a new Scripting Runtime a developer can add support for the scripting language of their choice to OpenOffice.org. The Scripting Framework provides all the required plumbing needed to facilitate the deployment, binding and invocation of scripts for an runtime. The runtime just has to provide the language specific execution environment for the script and execute it. The framework takes care of the rest.
What the Scripting Framework Provides
-
Package and deployment - standard way to package and deploy scripts in a document or Office installation. The script parcel is just a zip file containing the script, supporting resources and a parcel-descriptor.xml file, which contains the script specific deployment information including name, language, and other script language specific properties.
-
This packaging and deployment support for the currently supported Runtimes (Java and BeanShell) is provided through NetBeans IDE integration module shipped with the framework.
-
For other Runtimes not shipped with the framework and with no integrated IDE support, developers can use the command line tools which have been provided [ allows a user to create a script parcel and deploy it, regardless of the language used].
-
Binding – allows users to bind a deployed script [installation or document] to a menu, key or event using the supplied Assign dialogs. These are installed as part of the framework under the Tools/ “Script add on's”/ Assign ...
-
Invocation – once an action that has an associated script binding occurs, the framework handles the script invocation. It does the following:
-
Parse URI - Parses the script URI
-
Check Permissions - Checks to see if the script is stored in a document and if it has appropriate permissions to run [for details refer to the relevent section on Security in the User Guide on the Scripting Framework Website].
-
Load Script Info - Locates and loads up the information which describes the script and any language dependencies it might have from the script's parcel-descriptor.xml file stored in the application or document.
-
Load language Runtime - From this deployment information the framework can access the appropriate language runtime singleton to run the script.
-
Invoke on Runtime - The framework calls this language runtime's invoke method, passing the original script URI and all of the extracted script deployment information. This includes any language specific information, such as Classpath for Java and BeanShell scripts.
-
Runtime - Once the execution has been handed over to the language specific Runtime by the invoke( ) function call, it is the runtime's responsibility to provide the appropriate execution environment for the script, load it and run it using the information passed into it by the framework. Once the script has run the Runtime will pass back the return value and any errors to the framework, which will pass them back to the script caller.
-
What a new Runtime needs to provide:
-
Runtime – an implementation of a Runtime execution environment for your scripting language, described in detail below.
Category |
Name |
Origin |
Description |
Comment |
---|---|---|---|---|
Interface |
Implemented by Runtime |
Runtime is an UNO Component |
Required by UNO when creating an UNO component. |
|
Interface |
Implemented by Runtime |
Runtime is an UNO Component |
Required by UNO when creating an UNO component. |
|
Singleton |
|
Implemented by Runtime |
Runtime must be a Singleton |
Need to modify the _writeRegistryServiceInfo() of the XServiceInfo service to register the Runtime programatically as a Singleton [refer to Singleton Support] |
Interface |
drafts.com.sun.star.script.framework.runtime.XScriptInvocation |
Implemented by Runtime |
XScriptInvocation interface supports the invoke() method that is called when invoking scripts for a language. |
Key interface which allows the Scripting Framework to invoke scripts in a language independent manner |
Invoke() |
||||
Method |
XscriptInvocation: |
Implemented by Runtime |
Returns an Any Invoke method of the XscriptInvocation interface |
Runtime implements this method in it's own language. It must setup the script runtime environment, load up the script, pass any required parameters to it and execute the script. |
Parameter |
Invoke(): |
Provided by Caller – Used by SF |
Is an OUString Consists of: |
Information only – Runtime does not need to do anything with it. SF will have already resolved the scriptURI to an actual script and loaded up all the relevant script information the Runtime needs to invoke the script in the invocationCtx parameter passed to invoke(). The script URI can be used by the Runtime for logging or as a key to cache script related information. |
Parameter |
Invoke(): |
Provided by SF – Used by Runtime |
Is a XPropertySet |
Provides Runtime with information on the invocation context of the script as a set of property name/value pairs. The key ones are described below. |
Key InvocationCtx Properties |
||||
Property |
InvocationCtx: |
Provided by SF – Used by Runtime |
Is a XModel |
XModel of the current document against which the script was invoked. Must be passed to the Script by the Runtime so the script can interact with the current document. |
Property |
InvocationCtx: |
Provided by SF – Used by Runtime |
Is a XScriptInfo |
Contains all of the information the Runtime needs to setup the script runtime environment and to load the script to execute it. |
|
||||
Key XscriptInfo methods |
||||
Method |
XScriptInfo: |
Provided by SF – Used by Runtime |
Returns OUString |
Provides the function name of the script you
are trying to invoke. |
Method |
XScriptInfo: |
Provided by SF – Used by Runtime |
Returns OUString |
Provides the Path to the script the Runtime
needs to invoke. |
Method |
XScriptInfo: |
Provided by SF – Used by Runtime |
Returns XpropertySet |
Use this property set to access language
specific name/ value pairs setup for the specific language Runtime
during script deployment. |
Invoke Parameters |
||||
Input Parameter |
Invoke(): |
Provided by Caller - Optional |
Is a Sequence of Any |
Up to the Runtime to pass the input parameter
sequence onto the script if input parameters are supported. |
Output Parameter |
Invoke(): |
Provided by Caller - Optional |
Is a Sequence of short |
Up to the Runtime to pass this output
parameter index information back to the Caller from the script. |
Output Parameter |
Invoke(): |
Provided by Caller - Optional |
Is a Sequence of Any Not supported by Java or BeanShell Runtimes. |
Up to the Runtime to pass the output
parameter sequence back to the Caller from the script. |
Return |
Invoke(): |
Provided by Script, passed back by Runtime - Optional |
Is an Any |
A script can return whatever it likes to the
Runtime, but it is up to the Runtime to package this script
return up into a type that is supported by the UNO language
bridge that is being used by the Runtime [must be a primitive
type or an UNO type] |
UNO Language Bridge
There must be a supported UNO bridge for the scripting language to allow the framework to make calls against this new scripting runtime. The bridge will take care of all the parameter marshaling that needs to occur as the framework makes the call to the invoke method written in the new language.
The Java and BeanShell Runtimes are supported by the existing Java UNO bridge. Any scripting language with a Java implementation could use the Java UNO bridge, such as Jython [Python], Jacl [Tcl/TK] andRhino [Javascript]. As other bridges become available native support could be added, for instance with the new PyUNO bridge, a Python Runtime could be written in Python.
The Runtime
Required Interfaces
The Runtime is a normal UNO component, so it needs to support the following interfaces [Refer to the Developer's Guide for details on creating UNO Components].
Interface: com.sun.star.lang.XTypeProvider
Interface: com.sun.star.lang.XServiceInfo
In addition to the normal component interfaces above the Runtime must support the following interface to allow the framework to invoke the scripts in a language independent fashion:
Interface: drafts.com.sun.star.script.framework.XScriptInvocation
This interface supports one method, invoke( ), whose parameters and types are described below.
Invoke ( )
Returns: Any
Throws: IllegalArgumentException, CannotConvertException,
Parameter Types |
Parameters |
Description |
[in] string |
scriptURI |
Original URI passed to the framework |
[in] any |
invocationCtx |
Information on where the script was run from |
[in] sequence< any > |
aParams |
Input parameters |
[out] sequence< short > |
aOutParamIndex |
Output parameter index |
[out] sequence< any > |
aOutParam |
Output parameters |
The following sections describe the parameters to the invoke ( ) method call and how they can be used by a Runtime to setup an execution environment for a script and then load and run the script.
ScriptURI
The scriptURI is the original script URI that was passed during the invoke.
This information should not be required by a runtime as the framework will have already resolved the script to a specific script and loaded up the detailed script information by the time the Runtime's invoke method is called [ refer to Appendix I for details on the framework's current resolution strategy].
If a runtime needs to parse the script URI, to perform it's own processing the scriptURI is provided to allow it to do so. The syntax of the script URI is:
script://<logical_name>['?'<query_element>('&'<query_element>)*]]
where : query_element = <word>'='<name>
Script URI Parameter |
Description |
---|---|
logical_name |
Logical Name of the script – this is the
name displayed to the user in the Assign dialogs. It allows the
script writer to specify a more user friendly name for the
script, rather than displaying the actual function name to the
user. |
language |
Language the script is written in, must be a
supported runtime. |
function |
Actual language specific function name. |
location |
Location where script is stored –
application area [user or share] or document. |
Example of Script URI:
script://Tools.Convert.ToEuro?
language=Java&
function=com.sun.star.beans.tools.Standard.Convert.toEuro&
location=user
Maybe better above/below if we use an example from the framework
installation.
In the assign dialogs the user will see the Tools.Convert.ToEuro script name in the list of available scripts when Java is the selected language and user the selected location. Selecting this script will assign the above script URI to the menu, key or event binding as appropriate for the assign dialog invoked. It will be stored in the matching configuration file for later retrieval when the binding is invoked.
InvocationCtx
The invocationCtx is an implementation of XPropertySet setup by the framework to give a Runtime access both to the context from which the script was invoked (the current document) and the detailed information on the script itself which a Runtime will need to load and run the script (SCRIPT_INFO).
InvocationCtx Property Set
Property Key |
Type |
Description |
---|---|---|
DOC_REF |
XModel |
The XModel of the current document |
DOC_URI |
OUString |
The document URI of the current document |
SCRIPT_INFO |
XScriptInfo |
XScriptInfo for the resolved script, containing all of the data in the scripts parcel-descriptor.xml and the physical path of the script directory. |
DOC_STORAGE_ID |
sal_Int32 |
Used by the framework - The internal storage id of the script storage created for this document |
RESOLVED_STORAGE_ID |
sal_Int32 |
Used by the framework - The resolved script storage for this script, will be the same as the DOC_STORAGE_ID if the script is in the document, otherwise it will point to the User or Share storage areas. |
Accesing properties from the invocationCtx property set [examples in Java]:
First get the property set from the invocationCtx:
XPropertySet invocationCtxPropSet =
( XPropertySet ) UnoRuntime.queryInterface( XPropertySet.class, invocationCtx );
Then get the required property [use one of the property keys above]:
Object propObject = invocationCtxPropSet.getPropertyValue( <Property Key> );
Query the returned object for the required object type:
typedPropObject = ( <Property Type> ) UnoRuntime.queryInterface( <Property Type>.class,
propObject );
For example to access the SCRIPT_INFO property:
Object propObject = invocationCtxPropSet.getPropertyValue( “SCRIPT_INFO” );
scriptInfoPropObject = ( XScriptInfo ) UnoRuntime.queryInterface( XScriptInfo.class, propObject );
Loading and running the script
The framework will resolve the script URI to a specific script and load up the script information into a XScriptInfo object. This is then set as a property of the invocationCtx which is passed onto the Runtime in the Runtime's invoke ( ) method call.
This contains the key information required by the Runtime to execute the script, it gives the Runtime access to all of the information about this specific script, including physical location and any language specific information that the Runtime requires to run the script, such as Classpath in the case of the Java and BeanShell runtimes.
The Runtime can access the SCRIPT_INFO property of the invocationCtx as described above. Once it has the XScriptInfo it can use methods to get all the information it needs to load and run the script.
Obtain the XScriptInfo as described above and use the following XScriptInfo interface methods to access the required data:
XscriptInfo Method |
Return |
Description |
---|---|---|
getLogicalName() |
OUString |
Logical name – displayed in the Assign dialogs |
getDescription() |
OUString |
Description of the script, provided during deployment of the script – not currently displayed in the Assign dialogs. |
getLanguage() |
OUString |
Language script is written in. |
getFunctionName() |
OUString |
Function name of the script [only displayed in the Assign dialogs if t the details checkbox is selected]. |
getParcelURI() |
OUString |
Path to the script parcel – needed to load in the script source to the runtime. Scripts stored in the application are file
based URI's [file://]. Document scripts have their own protocol [vnd.sun.star.pkg] |
getLanguageProperties() |
XPropertySet |
Language specific properties of the Script: Access name value pairs of this property set using the appropriate property keys for the script language [Specified by the Runtime developer and setup during deployment of a script]. For Java and BeanShell classpath is the only available property key. |
getFileSetNames() |
Sequence of OUString |
Get a sequence of file set names from the script parcel. The file set allows the script developer to group a set of related files together which either the Runtime or the script can use. For instance this may be useful in specifying a set of related resources for a script. Currently these methods are not used by the Java or BeanShell runtimes [related files/ resources are generally in jar files that can be specified on the language property - Classpath] |
getFilesInFileSet( const ::rtl::OUString & fileSetName ) |
Sequence of OUString |
Get a list of the files for the given fileset.
|
Typically the information in the invocationCtx and ScriptInfo information is used as follows by a Runtime [Note: though specific to the Java and BeanShell Runtimes, the general logical flow will be the same for most Runtimes]
Runtime Invocation
-
Obtain the XScriptInfo from the invocationCtx's SCRIPT_INFO property
-
Access the language properties using the XScriptInfo->getLanguageProperties( ) method and setup what ever language specific features are required for this runtime. For Java and BeanShell this is the Classpath.
-
For Java and BeanShell you must also add the location of the script to the Classpath. Obtained from the XScriptInfo getParcelURI( ) method.
-
-
Setup the ScriptContext to pass to the script. In Java and BeanShell the ScriptContext is setup as a convenience for the script developer [refer to “Passing useful data to the Script” below].
-
Get the XComponentContext from the component context passed into the Runtime's constructor by UNO [refer to Developer's Guide].
-
Get the desktop using this component context's service factory to create an instance of the desktop service (“com.sun.star.frame.desktop”) [ refer to Developer's Guide].
-
Get the XModel for the current document from the invocationCtx's DOC_REF property.
-
-
Setup the Input Parameters to pass to the script.
-
Currently this is only done in Java, they are ignored in the BeanShell Runtime.
-
-
Load up the script into the Runtime environment.
-
In Java this is done by loading up the appropriate Java Class with a matching method signature from the Classpath setup above using a custom URLClassLoader [this handles loading both from the file system class files, jar files and OpenOffice.org documents using a custom UCB stream handler – refer to Accessing Document Scripts below ].
-
In BeanShell the script is loaded from the location given by combining the output of the XscriptInfo's getParcelURI() and the getFunctionName() methods. If the script is in a document then it is loaded using the custom UCBStreamHandler to create a suitable URL input stream for the eval() method of the BeanShell interpreter. Otherwise it is loaded into the BeanShell interpreter from the file system using the source() method.
-
-
Invoke the Script – having setup the appropriate environment for the script, assembled some useful information for the script and obtained access to the script source, either on the file system or in a document, the Runtime can now invoke the script in whatever language dependent way appropriate.
-
In Java invoke the method setup in the Script Proxy object, generated using the custom Classloader.
-
In BeanShell invoke using the interpreter's eval method for a document script or interpreter method if dealing with a script stored on the file system.
-
Passing Useful data to the Script
It is up to the Runtime to decide what information to pass to a running script. It makes sense to pass information to the script which makes the script writer's job easier, such as a reference to the current document (available from the invocationCtx), reference to the service manager (available from the component context passed into the Runtime component's constructor by UNO) and a reference to the desktop (available from UNO using this service manager).
In both the Java Runtime and the BeanShell runtime this context information is made available to the running script in the form of a XScriptContext. This provides accessor methods to get the current document, the current desktop and the component context. In the Java Runtime it's passed as the first parameter to the script and in the Beanshell Runtime it's setup in the runtime environment variable, “context”.
Interface: drafts.com.sun.star.script.framework.runtime.XScriptContext
XscriptContext Method |
Returns |
Description |
---|---|---|
getDocument |
XModel |
Access to the current document. |
getDesktop |
XDesktop |
Access to the current desktop. |
getComponentContext |
XComponentContext |
Can be used by the script to get the default multi component factory to create other UNO services. |
Loading Scripts
Scripts can be loaded from the user or share application directories or from a document. The parcelURI which provides the path to the script to load is in the form of an encoded URI. When the Runtime is using the parcelURI to load a script the Runtime needs to take account of this fact and process the parcelURI appropriately before it it is used.
If you use the UNO UCB API, such as the XSimpleFileAccess, then you do not need to alter the encoded URI at all. If you want to use it to load the script just append a forward slash before appending the appropriate script filename and pass it to the appropriate XSimpleFileAccess methods.
The Java and BeanShell Runtimes use XSimpleFileAccess [openFileRead(), getSize()] and XInputStream [readBytes() and closeInput()] to read in the script and setup a byte array input stream to the document script. This in turn is used to create a custom stream handler that can then be used with both the ClassLoader and URL classes, to allow the Runtimes to load up classes and scripts from the document. Any Java based Runtime can use the helper classes in UCBStreamHandler.java and PathUtils.java.
The parcelURI is in an encoded URL format.. The specification for URLs, RFC 1738 : http://www.rfc-editor.org/rfc/rfc1738.txt, limits the use of allowed characters in URLs to a subset of the US-ASCII character set. For a URL to be a well formed URL conformant with the URL specification it must encode any characters in the URL which fall outside this limited set. URL encoding of a character consists of a "%" symbol, followed by the two-digit hexadecimal representation (case-insensitive) of the ISO-Latin code point for the character. Characters which need to be encoded include; ASCII control characters, non ASCII characters, reserved characters [specific to URL syntax including Backslash (%5C) ] and unsafe characters [optional but may cause problems in a URL, including Space (%20) and Forward slash (%2F)].
The following table outlines what is passed to the Runtime for a given application or document script. It shows the type of processing that needs to be carried out before using the parcelURI to create a full path to access the application script from the file system or the document script from the document [The example uses the BeanShell Runtime, but the principal's are the same for any Runtime].
ParcelURI: Application Script |
|
ScriptURI – processed by the SF |
script://MemoryUsage.BeanShell?language=BeanShell&function=memusage.bsh&location=user |
ParcelURI – passed into the Runtime |
Unix: file:///apps%20and%20utilities/staroffice/user/Scripts/java/MemoryUsage Windows: file:///C:/apps%20and%20utilities/staroffice/user/Scripts/java/MemoryUsageThe ParcelURI is passed into the Runtime in the invocationCtx's SCRIPT_INFO property set and accessed using the XScriptInfo getParcelURI() method. |
Full path of Script to Load – using UCB XSimpleFileAccess |
Unix: file:///apps%20and%20utilities/staroffice/user/Scripts/java/MemoryUsage/memusage.bsh Windows: file:///C:/apps%20and%20utilities/staroffice/user/Scripts/java/MemoryUsage/memusage.bsh < ParcelURI>/< Function Name> |
|
|
ScriptURI |
script://MemoryUsage.BeanShell?language=BeanShell&function=memusage.bsh&location=document |
ParcelURI – passed into the Runtime |
Unix: vnd.sun.star.pkg://file:%2F%2F%2Fscriptdev%2Fjohnr%2Fstaroffice644m5%2Fuser%2FScripts%2Fjava%2FMemoryUsage%2FExampleSpreadSheet.sxc/Scripts/java/MemoryUsage Windows: vnd.sun.star.pkg://file:%2F%2F%2FC:%2Fscriptdev%2Fjohnr%2Fstaroffice644m5%2F
Document URI protocol is vnd.sun.star.pkg The Runtime should check for this string to see if it
should be handled as an embedded document script. |
Full UCB path of Script to Load – created by the Runtime |
vnd.sun.star.pkg://file:%2F%2F%2Fscriptdev%2Fjohnr%2Fstaroffice644m5%2Fuser%2FScripts%2Fjava%2FMemoryUsage%2FExampleSpreadSheet.sxc/Scripts/java/MemoryUsage/memusage.bsh <Processed ParcelURI>/< Function
Name> |
Parameters passed to the Script
Java Runtime
To run a Java script in OpenOffice.org, you must create a public Java class with at least one public Java method that takes an XScriptContext as it's first parameter. If no such method exists the Runtime will throw an exception.
BeanShell Runtime
BeanShell scripts are single .bsh files, there are no parameter requirements when running BeanShell scripts. The Runtime does make the XScriptContext available in the BeanShell environment, but the script can use or ignore it as it sees fit.
Current Runtimes invocation Parameter support
Runtime |
Input Parameters |
Output Parameters |
Return |
---|---|---|---|
Java |
Supported |
Ignored |
Supported |
BeanShell |
Ignored |
Ignored |
Supported |
Framework invocation Parameter support
The framework scripts can be invoked either directly using a call to XFunction, obtained from a suitably constructed XFunctionProvider or indirectly using one of the XFispatch methods.
Interface: com::sun::star::frame::XDispatch
Interface: drafts::com::sun::star::script::framework::provider::XFunctionProvider
The appropriate dispatch handler will be invoked for the framework, based on the protocol of the scriptURI passed in [The Script Framework protocol handler, com.sun.star.comp.ScriptProtocolHandler, is registered in the ProtocolHandler.xcu configuration file when the framework is installed and handles URI's for the “script://” protocol].
Interface / Method |
Input Parameters |
Output Parameters |
Return |
---|---|---|---|
XDispatch: dispatch( ) |
Supported |
Ignored |
Ignored |
XDispatch: dispatchWithNotification( ) |
Ignored |
Supported via XDispatchResultListener |
|
XFunction: invoke( ) |
Supported |
Supported |
Supported |
Input Params
If a script is invoked from a menu, key or event binding setup using the Assign dialogs, there is no way to pass an input parameter to the script . However, it is possible to pass input parameters to a script if you invoke it from another script using either the XDispatch [asynchronous] or XFunction [synchronous] interfaces as shown below:
Example using XFunction to Invoke a Script. with several input parameters
Sub DisplayEuroConversionRates ( conversionRatesRile as String, numConversions as integer)
dim args(0)
args(0) = ThisComponent
' Create your FunctionProvider and obtain a Script Function from it.
FuncProvider = createUnoService(“drafts.com.sun.star.script.framework.provider.FunctionProvider”)
FuncProvider.initialize( args() )
Func = FuncProvider.getFunction( “script://Tools.Convert.DisplayEuroRates?_
language=Java&function=com.sun.star.beans.tools.Standard.Convert.displayEuro&location=user”)
Dim inArgs(1)
Dim outArgs()
Dim outIndex()
' Setup Input Param arguments
inArgs(0) = conversionRatesFile
inArgs(1) = numConversions
result = Func.invoke( inArgs(), outIndex(), outArgs() ) // Out params not handled by Java or BeanShell
End Sub
Example using XDispatch to Invoke a Script with several input parameters
sub DisplayEuroConversionRates( conversionRatesFile as String, numConversions as integer)
dim url as new com.sun.star.util.URL
document = ThisComponent.CurrentController.Frame
parser = createUnoService(“com.sun.star.util.URLTransformer”)
dim args1(1) as new com.sun.star.beans.PropertyValue
' Setup Input Param arguments
' Note: args1(x).Name can be left blank
' Set argsl(x).Name to “Referrer” if you do not want it added as an input param
args1(0).Value = conversionRatesFile
args1(1).Value = numConversions
url.Complete = “script://Tools.Convert.DisplayEuroRates?_
language=Java&function=com.sun.star.beans.tools.Standard.Convert.displayEuro&location=user”
parser.parseStrict(url)
disp = document.queryDispatch(url,“”,0)
disp.dispatch(url, args1()) 'No access to Out params
End Sub
Output Params
Are currently not supported in the Java and BeanShell Runtimes. If you do implement them in your Runtime, the XDispatch script protocol handler has no way to process them [supports one way call only]. You would only be able to process them if you use the XFunction interface above in the calling script.
Returns
The script runtime can return the result of the script in an Any if it makes sense to do so. The return result must be a type that is supported by the UNO language bridge being used by the Runtime [generally a primitive type or an UNO type]. If an unsupported type is passed back by the script the UNO bridge will cause an assert. Both the Java and BeanShell runtimes pass back the return value of scripts they invoke, it is the responsibility of the script writers to return types supported by the UNO bridge [refer to the Developer's Guide].
If there is no return value or the Runtime chooses not to support return values from scripts, it must always return a void Any [created as follows in Java: new Any(new Type(), null);]
Errors
If any problems arise in the Runtime the following exceptions can be thrown by the invoke call. The Runtime should make sure the errors raised match the meaning of the the exceptions given below.
Exception |
Description |
---|---|
IllegalArgumentException |
If there is no matching script name. |
CannotConvertException |
If arguments do not match or cannot be converted the those of the invokee |
InvocationTargetException |
If the running script throws an exception, this information is captured and re thrown as this exception type. |
Runtime Singleton
The Runtime must be setup as a Singleton. The name of the singleton must follow the following scheme:
theScriptRuntimeFor<Runtime Language>
For example for Java the singleton is named theScriptRuntimeForJava and for BeanShell it is named theScriptRuntimeForBeanShell.
This needs to be done programmatically in the _writeRegistryServiceInfo( ) method of the XServiceInfo service. In this method you need to create the appropriate singleton registry key under the UNO/Singletons key in the Office registration database in the [refer to example below for BeanShell].
[Note: this is an undocumented feature of 643 builds and above and is not covered in the Developer's Guide].
Singleton Registry Entry:
[Implementation Name]+ "/UNO/SINGLETONS/” + [Service Module] + “.theScriptRuntimeFor<Runtime Language>”
BeanShell Example
public static boolean __writeRegistryServiceInfo( XRegistryKey regKey ) {
String impl = "com.sun.star.scripting.runtime.beanshell.ScriptRuntimeForBeanShell$_ScriptRuntimeForBeanShell";
String serviceModule = "drafts.com.sun.star.script.framework";
String service = serviceModule + ".ScriptRuntimeForBeanShell";
if (FactoryHelper.writeRegistryServiceInfo(impl, service, regKey)) {
try {
XRegistryKey newKey = regKey.createKey(
impl + "/UNO/SINGLETONS/”+ serviceModule + “.theScriptRuntimeForBeanShell");
newKey.setStringValue(service);
return true;
} catch (Exception ex) {
System.err.println("Error registering ScriptRuntimeForBeanShell: " + ex);
}
}
return false;
}
Configuration Changes
As of release 0.3, runtime developers also need to make a change to the OpenOffice registry. The file <Officeinstall>/share/registry/schema/org/openoffice/Office/Scripting.xcs defines the schema used to determine the relationship between a runtime, eg. BeanShell, and the file extensions supported by that runtime, eg. .bsh. Thus developes need to bundle a Scripting.xcu file along with their UNO package (see following section). The file used for the BeanShell runtime which follows could be used as a template:<?xml version="1.0" encoding="UTF-8"?>
<oor:node xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Scripting" oor:package="org.openoffice.Office">
<node oor:name="ScriptRuntimes">
<node oor:name="BeanShell" oor:op="replace">
<prop oor:name="SupportedFileExtensions">
<value xml:lang="en-US">bsh</value>
</prop>
</node>
</node>
</oor:node>
Packaging
The new Runtime must be packaged as an UNO Component. Refer to the Developer's Guide on instructions on how to use the pkgchk tool to package the Runtime and any additional resources it may require.
Creating Scripts
If you want to allow your users to create script parcels for the new language Runtime, you can create a tool to create a script parcel, or you can use the existing command line tools to do so.
The script parcel is just a zip file containing the script and any associated resources and a parcel-descriptor.xml file, which gives the details of the script, including language specific information that may be needed to run the script.
You could write your own tools to create the parcel-descriptor.xml file. Refer to Appendix I for the parcel-descriptor.xml DTD.
Binding to Scripts
If a Runtime has been installed the Assign dialogs will automatically detect the new language Scripting Runtime singleton. The language will then be available as a choice in the language drop down combo of all of the assign dialogs. Choosing it the user will be presented with a list of any scripts for this language, deployed into the specified location [installation – user/ share; document].
The Runtime developer has nothing to do other than make sure the Runtime is registered as a singleton using the above naming scheme.
Appendix I
Scripting Framework Resolution
If a Script URI has all of the key fields filled out [logical name, language, function and location] then the Script URI will be unambiguously matched to only one physically deployed script. If no match is found then a Runtime exception is raised by the framework.
What happens if you omit some or all of the optional fields? The framework will attempt to resolve the Script URI to one of the deployed scripts as follows.
Omitted Script URI Parameter |
Resolution Strategy |
---|---|
function |
Will search for the first match from the list of all available function implementations for a given logical name by alphabetical order of the functions. |
location |
Will search for the first matching script from all the available storage locations in the order of document, user and share. |
language |
Will search for the first match in the available supported language Runtimes by alphabetical order of the Runtimes. |
In the future it may be possible to configure the framework's resolution strategies if the Script URI is not fully qualified.
Runtime Specific Resolution
In some Runtime's it may
be necessary to do further resolution checks, based not just on the
function name, but also on the Parameter list passed down to the script.
For instance, the Java Runtime will check that the script which the
framework has resolved also matches a method with the appropriate
signature on the available Classpath for this script and if it does not
will throw an exception.
Appendix II
Parcel Descriptor DTD and sample XML
Each script must contain a parcel-descriptor.xml file which provides all the necessary metadata for the script. The DTD for the parcel-descriptor.xml follows
<?xml version="1.0" encoding="UTF-8"?>
<!-- DTD for Parcel Meta data for use in the OpenOffice.org Scripting Framework Project -->
<!ELEMENT logicalname EMPTY>
<!ELEMENT description (#PCDATA)>
<!ELEMENT displayname EMPTY>
<!ELEMENT locale (displayname?, description?)>
<!ELEMENT functionname EMPTY>
<!ELEMENT prop EMPTY>
<!ELEMENT languagedepprops (prop+)>
<!ELEMENT file (prop*)>
<!ELEMENT fileset (file+)>
<!ELEMENT script (locale+, functionname, logicalname, languagedepprops*, fileset*)>
<!ELEMENT parcel (script+)>
<!ATTLIST logicalname
value CDATA #REQUIRED
>
<!ATTLIST displayname
value CDATA #REQUIRED
>
<!ATTLIST locale
lang CDATA #REQUIRED
>
<!ATTLIST functionname
value CDATA #REQUIRED
>
<!ATTLIST logicalname
value CDATA #REQUIRED
>
<!ATTLIST prop
name CDATA #REQUIRED
value CDATA #REQUIRED
>
<!ATTLIST file
name CDATA #REQUIRED
>
<!ATTLIST fileset
name CDATA #IMPLIED
>
<!ATTLIST script
language CDATA #REQUIRED
>
<!ATTLIST parcel
language CDATA #REQUIRED
>
The following is an example of a parcel-descriptor.xml file that defines a script, implemented in Java. The languagedepprops element is used to extend the JVM's classpath.
<?xml version="1.0" encoding="UTF-8"?>
<!--Sample Meta Data for use with the Scripting Framework Project in OpenOffice.org -->
<!DOCTYPE parcel SYSTEM "parcel.dtd">
<parcel language="Java">
<script language="Java">
<locale lang="english">
<displayname value="Memory.usage"/>
<description>
Displays the memory current memory usage
</description>
</locale>
<functionname value="memoryUtils.memoryUsage"/>
<logicalname value="MemoryUtils.MemUsage"/>
<languagedepprops>
<prop name="classpath" value="/opt/foo.jar:/usr/java/src.jar"/>
</languagedepprops>
<fileset>
<file name="mems.txt">
<prop name="type" value="resource"/>
</file>
</fileset>
</script>
</parcel>