NAME
Scripting - Language independent framework for enabling application scripting.
SYNOPSIS
package MyApp;
use Scripting::Expose as => "Application";
sub println : Function {
print @_, "\n";
}
package main;
use Scripting;
Scripting->init( with => "scripts/", allow => "js", signed => "/var/db/AppFoo.sign.db");
Scripting->invoke("Script-Foo");
DESCRIPTION
Scripting is a framwork for exposing bits and pieces of your Perl application to various scripting engines.
WHY?
Altho there are many languages that can be embedded and called from Perl, they all have different features and different APIs. The Scripting module unifies them into a single, sleek but yet powerfull API that hids all the differences from the programmer.
FEATURES
- Simple attributes based API
- Support for different script environments
- Support for different languages
- Signed scripts
- Event system to invoke scripts
SIMPLE API
Scripting uses a attributes based API, if you don't know what that is, read perlsub.
Script environments
In some applications, there might be a need to provide different kinds of APIs to scripts. These are referred to as script enviroments in this documentation. They are optional to use, and there is a global environment that is used if the target environment is ommited.
Defining packages
To make a package accessibly from scripts. Import Scripting::Expose into your namespace by using the module. It's very important that this is done during compile-time, so using require Scripting::Expose
and call Scripting::Expose->import
is not recommended.
In its simpliest form, it can look like this.
package MyApp;
use Scripting::Expose;
Scripting::Expose will use the callers package name by default. However, in some cases this does not work because valid symbols in the Scripting module are only those that matches /^[A-Za-z][A-Za-z0-9_]*$/. Therefor, MyApp::Document would not be supported. To provide another name, pass as => 'Another_Name'
on usage.
package MyApp::Document;
use Scripting::Expose as => "Document";
This package will now become available to all script environments. If we only like to expose it to a single or multiple environments, we pass to => "Foo"
or to => [qw(Bar Baz)]
.
package MyApp::Document;
use Scripting::Expose as => "Document", to => "WordProc";
Attribute handlers
The four attribute handlers Function, Constructor, ClassMethod and InstanceMethod all uses the name of the symbol (with package removed) by default. If another name is preferred one can be supplied with as => "Another_Name"
Exposing a function
use Scripting::Expose;
sub print_line : Function {
print @_, "\n";
}
Exposing a class that is instanciable
package MyApp::Document;
use Storable qw(store retrieve);
use Scripting::Expose as => "Document";
sub new : Constructor {
my $self = bless {}, __PACKAGE__;
return $self;
}
sub set_title : InstanceMethod(as => "setTitle") {
my ($self, $title) = @_;
$self->{title} = $title;
}
# more methods here
sub save : InstanceMethod(as => 'saveDocument', Secure => 'arguments') {
my $is_signed = pop;
my ($self) = @_;
return 0 unless($is_signed);
store $self, $self->{path};
}
sub load : ClassMethod(as => 'loadDocument') {
my ($pkg, $path) = @_;
return retrieve($path);
}
Script security
Scripting supports a basic mechanism for signing scripts. Signing is optional and only affects functions and methods that are exposed with the Secure argument.
To "secure" a function or method, pass Secure => "arguments"
to the attribute handler. This will tell Scripting to pass an extra argument to the subroutine when it is invoked. The value of the argument will be 1 (true) if the calling script is signed, and 0 (false) if it's not.
Signing a script is done by using the tool sign_script.pl which is available in the tools directory in the module distribution. ./sign_script -d /path/to/sign.database -f /path/to/script
.
All paths are stored as absolute paths, so if you move a signed script it must be resigned.
Issue ./sign_script --help
for more options.
Initializing and loading scripts
Upon initialization, all scripts found in the supplied directory paths are loaded. To initialize Scripting, call Scripting->init
.
- Scripting->init( with => $dirs, allow => $langs, signfile => $db);
-
The argument with is mandatory, the others are optional.
allow is either a scalar containg a whitespace separeted list of file extensions, for example "js tcl" or an array reference with each allowed file extension, for exmaple [qw(js tcl)].
signfile is the path to the database with script signatures. If signfile is ommited, script signing is disabled.
with is a scalar containg a path to the directory from which it should load the scripts. It is also possible to load from several paths by passing an array reference.
Loading scripts works in a special way. If the name of directory in which the script is found in is a environment, it will be loaded into that. Otherwize, the script will be loaded in the global environment. The name of the file without the extension becomes the name of the event that is used to invoke the script. This table should make it a bit clearer.
# Environment : Event name # _Global : test scripts/test.js # Foo : bar scripts/Foo/bar.js
Invoking scripts
To invoke a script call Scripting->invoke($name_of_event)
. If the event doesn't exist, nothing there won't be an exception or error. Calling the invoke method with only one argument looks for the event in the global environment, to invoke a script in another environment, pass the name of the environment as the first argument. For example Scripting->invoke(WordDoc =
$name_of_event>. Future versions of Scripting may support an attribute handler to automaticlly invoke events upon a subroutine call.
FUTURE DEVELOPMENTS
- More security options (don't run an unsigned script at all etc.)
- More languages (Tcl, Java, C)
- Function named based event invokation (have multiple event handlers in one script)
- Things I can't think of right now
SEE ALSO
http://developer.surfar.nu/Scripting/
COPYRIGHT
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Copyright 2003 Claes Jacobsson
AUTHOR
Claes Jacobsson, claesjac@cpan.org
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 190:
'=item' outside of any '=over'
- Around line 210:
You forgot a '=back' before '=head2'