Index: openacs-4/packages/soap-gateway/soap-gateway.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/soap-gateway.info,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/soap-gateway.info 17 Oct 2004 05:51:39 -0000 1.1
@@ -0,0 +1,29 @@
+
+
+
+
+ SOAP Gateway
+ SOAP Gateway
+ f
+ t
+ soap
+
+
+ William Byrne
+ Nick Carroll
+ SOAP Gateway marshalls SOAP/HTTP to user defined services
+ 2004-10-04
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: openacs-4/packages/soap-gateway/lib/demo-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/lib/demo-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/lib/demo-procs.tcl 17 Oct 2004 05:51:51 -0000 1.1
@@ -0,0 +1,83 @@
+ad_library {
+
+ soap-gateway demo routines
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+
+}
+
+# create namespace
+namespace eval sg::demo {
+
+ # remove old procs
+ foreach p [info commands ::sg::demo::*] {
+
+ # remove
+ rename $p {}
+ }
+
+ # If there are any authentication requirements for a method in a service, add login
+ # and logout wrappers for soap::login and soap::logout methods.
+ #
+ # This will prevent the SOAP client transport from having to maintain session cookies
+ # across multiple client SOAP stubs. For example, a SOAP client can log into OpenACS using
+ # the 'workspace' service. Typically, the SOAP client will fetch the WSDL for the service
+ # and expose methods to the developer for calling upon methods specified in the WSDL.
+ # In the case of the 'workspace' service, the user would call the 'login' method. If
+ # successful, a session cookie is returned to the client and is maintained by the HTTP
+ # transport. If the user wishes to use the 'demo' service, another client SOAP stub
+ # would be created referencing the WSDL for the 'demo' service. Since the 'demo' SOAP
+ # stub is new, it won't have the session data maintained by the 'workspace' stub. There
+ # are certainly ways to share the session data; however, the process of doing so often
+ # turns into a science project.
+
+ # workspace login wrapper
+ ad_proc -public login {
+ user
+ password
+ } {
+ @author William Byrnec
+ @idl void Login(string user, string password)
+ } {
+
+ # call sg library
+ return [soap::login $user $password]
+ }
+
+
+ # workspace logout wrapper
+ ad_proc -public logout {
+ } {
+ @author William Byrne
+ @idl void Logout()
+ } {
+ # call sg logout
+ return [soap::logout]
+ }
+
+
+ # define calculate method
+ ad_proc -public calculate {
+ expr
+ } {
+
+ Performs an evaluation of the expression argument. The method attemps to provide some
+ safety by scanning for procedure notation. If detected, an exception is thrown.
+
+ @author William Byrne
+ @idl string Calculate(string expr)
+ } {
+
+ # detect proc bracket
+ if { [sting first \[ $expr] >= 0 } {
+ # throw
+ soap::fault::raise "procedure calls within expression are not allowed!"
+ }
+
+ # calculate
+ return [expr $expr]
+
+ }
+
+
+}
Index: openacs-4/packages/soap-gateway/lib/interop-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/lib/interop-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/lib/interop-procs.tcl 17 Oct 2004 05:51:51 -0000 1.1
@@ -0,0 +1,116 @@
+ad_library {
+
+ soap-gateway interop routines
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+
+}
+
+# set up interop namespace
+namespace eval sg::interop {
+
+ # remove old procs
+ foreach p [info commands ::sg::interop::*] {
+
+ # remove
+ rename $p {}
+ }
+
+ ad_proc -public login {
+ user
+ password
+ } {
+ Logs the user into OpenACS. The user and password arguments
+ correspond to the user/password values specified during user registration. The
+ HTTP transport used for the SOAP Envelope must support cookies for session based
+ RPC; otherwise, the user will be limited WSDL functions that expose 'invoke'
+ privileges to 'public'.
+
+ @author William Byrne
+ @idl void Login(string user, string password)
+ } {
+
+ # call sg library
+ return [soap::login $user $password]
+ }
+
+ ad_proc -public logout {
+ } {
+ Logs the current user session out of OpenACS.
+
+ @author William Byrne
+ @idl void Logout()
+ } {
+ # call sg library
+ return [soap::logout]
+ }
+
+ ad_proc -public echo_string {
+ data
+ } {
+ @author William Byrne
+ @idl string EchoString(string data)
+ } {
+
+ # return test data
+ return $data
+
+ }
+
+ ad_proc -public echo_integer {
+ data
+ } {
+ @author William Byrne
+ @idl int EchoInteger(int data)
+ } {
+
+ # return test data
+ return $data
+
+ }
+
+ ad_proc -public echo_float {
+ data
+ } {
+ @author William Byrne
+ @idl float EchoFloat(float data)
+ } {
+
+ # return test data
+ return $data
+
+ }
+
+ ad_proc -public echo_long {
+ data
+ } {
+ @author William Byrne
+ @idl long EchoLong(long data)
+ } {
+ # return test data
+ return $data
+
+ }
+
+ ad_proc -public echo_int64 {
+ data
+ } {
+ @author William Byrne
+ @idl __int64 EchoInt64(__int64 data)
+ } {
+ # return test data
+ return $data
+
+ }
+
+ ad_proc -public echo_void {
+ } {
+ @author William Byrne
+ @idl void EchoVoid()
+ } {
+
+ # return nothing
+
+ }
+
+}
Index: openacs-4/packages/soap-gateway/lib/workspace-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/lib/workspace-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/lib/workspace-procs.tcl 17 Oct 2004 05:51:51 -0000 1.1
@@ -0,0 +1,220 @@
+ad_library {
+
+ The workspace service provides a set of user workspace functions that
+ include the ability to log in and out of the OpenACS system. In order to take
+ advantage of session based SOAP RPC, the HTTP transport used by the client must
+ support cookies; otherwise, the user will be limited to methods that have
+ invoke privileges on the Public user.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+
+}
+
+# set up workspace namespace and exports
+namespace eval sg::workspace {
+
+ # remove old procs
+ foreach p [info commands ::sg::workspace::*] {
+
+ # remove
+ rename $p {}
+ }
+
+
+ ad_proc -public login {
+ user
+ password
+ } {
+ Logs the user into OpenACS. The user and password arguments
+ correspond to the user/password values specified during user registration. The
+ HTTP transport used for the SOAP Envelope must support cookies for session based
+ RPC; otherwise, the user will be limited WSDL functions that expose 'invoke'
+ privileges to 'public'.
+
+ @author William Byrne
+ @idl void Login(string user, string password)
+ } {
+
+ # call soap::login procedure
+ return [soap::login $user $password]
+ }
+
+ ad_proc -public logout {
+ } {
+ Logs the current user session out of OpenACS.
+
+ @author William Byrne
+ @idl void Logout()
+ } {
+
+ # call sg logout
+ return [soap::logout]
+ }
+
+ ad_proc -public set_name {
+ firstname
+ lastname
+ } {
+ Changes the firstname and lastname of the user specified during the 'login' operation.
+
+ @author William Byrne
+ @idl void SetName(string firstname, string lastname)
+ } {
+
+ # get user
+ set user_id [ad_conn user_id]
+
+ # require write permission on user
+ soap::server::require_permission $user_id write
+
+ # verify args ???
+
+ db_dml {} "update persons
+ set first_names = :firstname,
+ last_name = :lastname
+ where person_id = :user_id"
+
+ }
+
+ ad_proc -public get_name {
+ } {
+ Returns the first and last name of the user currently logged in.
+
+ @author William Byrne
+ @idl string GetName()
+ } {
+
+ # get user
+ set user_id [ad_conn user_id]
+
+ # require write permission on user
+ soap::server::require_permission $user_id read
+
+ db_1row {} {
+ select first_names, last_name, email,
+ case when url is null then 'http://' else url end as url,
+ screen_name
+ from cc_users
+ where user_id=:user_id
+ }
+
+ # return name
+ return [string trim "$first_names $last_name"]
+
+ }
+
+ ad_proc -private has_bio {
+ user_id
+ {data {}}
+ } {
+ Utility procedure that returns whether user has bio record
+
+ @author William Byrne
+ } {
+
+ # grafted from subsite
+ set retval [db_0or1row grab_bio "select attr_value as bio_old
+ from acs_attribute_values
+ where object_id = :user_id
+ and attribute_id =
+ (select attribute_id
+ from acs_attributes
+ where object_type = 'person'
+ and attribute_name = 'bio')"]
+
+ # test
+ if { $data != {} } {
+
+ # go up one frame
+ upvar $data bio
+
+ if [soap::server::lib::true $retval] {
+
+ # set it
+ set bio $grab_bio
+
+ } else {
+
+ # clear it
+ set bio {}
+
+ }
+
+ }
+
+ # return status
+ return $retval
+ }
+
+ ad_proc -public get_bio {
+ } {
+ Returns the users biography.
+
+ @author William Byrne
+ @idl string GetBio()
+
+ } {
+
+ # get user
+ set user_id [ad_conn user_id]
+
+ # require write permission on user
+ soap::server::require_permission $user_id read
+
+ # has bio will fill optional data arg with biography
+ has_bio $user_id bio
+
+ # return bio
+ return $bio
+
+ }
+
+ ad_proc -public set_bio {
+ bio
+ } {
+ Updates the users biography.
+
+ @author William Byrne
+ @idl void SetBio(string bio)
+
+ } {
+
+ # get user
+ set user_id [ad_conn user_id]
+
+ # require write permission on user
+ soap::server::require_permission $user_id read
+
+ # verify length
+ soap::check_str_len $bio 4000 "Your biography is too long. Please limit it to 4000 characters"
+
+ # has bio ?
+ if [has_bio $user_id] {
+
+ # grafted from subsite - update
+ db_dml update_bio "update acs_attribute_values
+ set attr_value = :bio
+ where object_id = :user_id
+ and attribute_id =
+ (select attribute_id
+ from acs_attributes
+ where object_type = 'person'
+ and attribute_name = 'bio')"
+
+
+ } else {
+
+ # grafted from subsite - insert
+ db_dml insert_bio "insert into acs_attribute_values
+ (object_id, attribute_id, attr_value)
+ values
+ (:user_id, (select attribute_id
+ from acs_attributes
+ where object_type = 'person'
+ and attribute_name = 'bio'), :bio)"
+
+ }
+
+ }
+
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-create.sql 17 Oct 2004 05:51:52 -0000 1.1
@@ -0,0 +1,571 @@
+-- packages/soap-gateway/sql/postgresql/soap-gateway-create.sql
+--
+-- @author WilliamB@ByrneLitho.com
+-- @creation-date 2002-12-22
+-- @cvs-id $Id: soap-gateway-create.sql,v 1.1 2004/10/17 05:51:52 ncarroll Exp $
+--
+--
+
+-- clear existing
+--\i soap-gateway-drop.sql
+--\q
+create function inline_0 ()
+returns integer as '
+begin
+ PERFORM acs_object_type__create_type (
+ ''wsdl_namespace'', -- object_type
+ ''WSDL Namespace'', -- pretty_name
+ ''WSDL Namespaces'', -- pretty_plural
+ ''acs_object'', -- supertype
+ ''sg_namespaces'', -- table_name
+ ''namespace_id'', -- id_column
+ null, -- package_name
+ ''f'', -- abstract_p
+ null, -- type_extension_table
+ ''sg_namespaces__name'' -- name_method
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+create function inline_1 ()
+returns integer as '
+begin
+ PERFORM acs_object_type__create_type (
+ ''wsdl_method'', -- object_type
+ ''WSDL Method'', -- pretty_name
+ ''WSDL Methods'', -- pretty_plural
+ ''acs_object'', -- supertype
+ ''sg_methods'', -- table_name
+ ''method_id'', -- id_column
+ null, -- package_name
+ ''f'', -- abstract_p
+ null, -- type_extension_table
+ ''sg_methods__name'' -- name_method
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_1 ();
+
+drop function inline_1 ();
+
+-- define invoke moniker
+create view sg_invoke_moniker as
+ select 'invoke' as invoke from dual;
+
+create function inline_2 ()
+returns integer as '
+declare
+ v_invoke varchar;
+begin
+ select invoke into v_invoke from sg_invoke_moniker;
+
+ -- create privileges
+ perform acs_privilege__create_privilege(v_invoke);
+
+ -- bind privileges to global names
+ perform acs_privilege__add_child(''admin'',v_invoke);
+
+ return 0;
+end;' language 'plpgsql';
+select inline_2();
+drop function inline_2();
+
+
+
+create table sg_namespaces (
+ namespace_id integer
+ constraint sg_namespaces_namespace_id_fk
+ references acs_objects(object_id)
+ constraint sg_namespaces_namespace_id_pk
+ primary key,
+ service varchar(255)
+ constraint sg_namespaces_service_nn
+ not null unique check(trim(service) <> ''),
+ uri varchar(255)
+ constraint sg_namespaces_uri_nn
+ not null,
+ dirty boolean
+ default 't'
+ constraint sg_namespaces_dirty_nn
+ not null,
+ notes varchar(1024)
+);
+
+create index sg_namespaces_idx1 on sg_namespaces(service);
+
+create table sg_methods (
+ method_id integer
+ constraint sg_methods_method_id_fk
+ references acs_objects(object_id)
+ constraint sg_methods_namespace_id_pk
+ primary key,
+ namespace_id integer
+ constraint sg_methods_namespace_id_fk
+ references sg_namespaces(namespace_id),
+ method varchar(255)
+ constraint sg_methods_method_nn
+ not null check(trim(method) <> ''),
+ idl varchar(255)
+ constraint sg_methods_idl_nn
+ not null,
+ idl_style varchar(32)
+ constraint sg_methods_idl_style_nn
+ not null,
+ proc varchar(255)
+ constraint sg_methods_proc_nn
+ not null,
+ notes varchar(1024)
+);
+
+-- oddity fixup for lower case on index
+create function sg_unique(integer,varchar)
+returns text as '
+begin
+ return '''' || $1 || ''-'' || lower($2);
+end;' language 'plpgsql' with(iscachable);;
+
+
+create unique index sg_methods_idx1 on sg_methods(sg_unique(namespace_id, method));
+
+
+create table sg_libraries (
+ library_id integer not null primary key,
+ path varchar(255) not null unique
+);
+
+--
+-- sequences
+--
+
+create sequence sg_library_id_seq start 1000;
+
+--
+-- functions
+--
+
+-- get namespace id
+create function sg_namespace__get_id(varchar)
+returns integer as '
+declare
+ p_service alias for $1;
+
+ v_namespace_id sg_namespaces.namespace_id%type;
+begin
+
+ -- nullify
+ v_namespace_id = null;
+
+ -- get namespace count for id
+ select into v_namespace_id namespace_id
+ from sg_namespaces
+ where service = p_service;
+
+ -- fix up
+ if v_namespace_id is null then
+ v_namespace_id = -1;
+ end if;
+
+ -- return object id
+ return v_namespace_id;
+
+end;' language 'plpgsql';
+
+-- create new namespace
+create function sg_namespace__new(varchar, varchar, varchar, timestamptz, integer, varchar, integer)
+returns integer as '
+declare
+ p_service alias for $1;
+ p_uri alias for $2;
+ p_notes alias for $3;
+
+ p_creation_date alias for $4; -- default now()
+ p_creation_user alias for $5;
+ p_creation_ip alias for $6;
+ p_context_id alias for $7;
+
+ v_namespace_id sg_namespaces.namespace_id%type;
+begin
+
+ -- create new base object
+ v_namespace_id := acs_object__new (
+ null,
+ ''wsdl_namespace'',
+ p_creation_date,
+ p_creation_user,
+ p_creation_ip,
+ p_context_id
+ );
+
+ -- add to namespace table
+ insert into sg_namespaces
+ (namespace_id, service, uri, dirty, notes)
+ values
+ (v_namespace_id, p_service, p_uri, ''t'', p_notes);
+
+ -- create admin permission
+ PERFORM acs_permission__grant_permission(
+ v_namespace_id,
+ p_creation_user,
+ ''admin''
+ );
+
+ -- return new object id
+ return v_namespace_id;
+
+end;' language 'plpgsql';
+
+create function sg_namespace__update(integer, varchar, varchar, varchar)
+returns integer as '
+declare
+ p_namespace_id alias for $1;
+ p_service alias for $2;
+ p_uri alias for $3;
+ p_notes alias for $4;
+
+begin
+
+ -- update row values
+ update sg_namespaces
+ set
+ service = p_service,
+ uri = p_uri,
+ dirty = ''t'',
+ notes = p_notes
+ where
+ namespace_id = p_namespace_id;
+
+ -- return something
+ return 0;
+
+end;' language 'plpgsql';
+
+-- check namespace id
+create function sg_namespace__exists(integer)
+returns integer as '
+declare
+ p_namespace_id alias for $1;
+ v_record record;
+begin
+
+ -- get namespace count for id
+ select into v_record count(*)
+ from sg_namespaces
+ where namespace_id = p_namespace_id;
+
+ -- test
+ return v_record.count;
+
+end;' language 'plpgsql';
+
+-- remove namespace and child methods
+create function sg_namespace__delete (integer)
+returns integer as '
+declare
+ p_namespace_id alias for $1;
+ v_object_rec record;
+begin
+
+ -- verify id
+ if sg_namespace__exists(p_namespace_id) = 0 then
+ raise EXCEPTION ''Invalid namespace id: %'', p_namespace_id;
+ end if;
+
+ -- clean up permissions for namespace methods
+ delete from acs_permissions
+ where object_id in (
+ select method_id from sg_methods
+ where namespace_id = p_namespace_id
+ );
+
+ -- clean up permissions for namespace
+ delete from acs_permissions
+ where object_id = p_namespace_id;
+
+ -- remove method objects
+ for v_object_rec in select method_id from sg_methods where namespace_id = p_namespace_id
+ loop
+ perform acs_object__delete( v_object_rec.method_id );
+ end loop;
+
+ PERFORM acs_object__delete(p_namespace_id);
+
+ -- remove methods
+ delete from sg_methods
+ where namespace_id = p_namespace_id;
+
+ -- remove namespace
+ delete from sg_namespaces
+ where namespace_id = p_namespace_id;
+
+ return 0;
+
+end;' language 'plpgsql';
+
+
+-- create new method
+create function sg_method__new(integer, varchar, varchar, varchar, varchar, varchar, timestamptz, integer, varchar, integer)
+returns integer as '
+declare
+ p_namespace_id alias for $1;
+ p_method alias for $2;
+ p_idl alias for $3;
+ p_idl_style alias for $4;
+ p_proc alias for $5;
+ p_notes alias for $6;
+
+ p_creation_date alias for $7; -- default now()
+ p_creation_user alias for $8;
+ p_creation_ip alias for $9;
+ p_context_id alias for $10;
+
+ v_method_id integer;
+begin
+
+ -- create new base object
+ v_method_id := acs_object__new (
+ null,
+ ''wsdl_method'',
+ p_creation_date,
+ p_creation_user,
+ p_creation_ip,
+ p_context_id
+ );
+
+ -- add to method table
+ insert into sg_methods
+ (method_id, namespace_id, method, idl, idl_style, proc, notes)
+ values
+ (v_method_id, p_namespace_id, p_method, p_idl, p_idl_style, p_proc, p_notes);
+
+ -- create admin permission
+ PERFORM acs_permission__grant_permission(
+ v_method_id,
+ p_creation_user,
+ ''admin''
+ );
+
+ -- return new object id
+ return v_method_id;
+
+end;' language 'plpgsql';
+
+-- update method
+create function sg_method__update(integer, varchar, varchar, varchar, varchar, varchar)
+returns integer as '
+declare
+ p_method_id alias for $1;
+ p_method alias for $2;
+ p_idl alias for $3;
+ p_idl_style alias for $4;
+ p_proc alias for $5;
+ p_notes alias for $6;
+
+begin
+
+ -- update row values
+ update sg_methods
+ set
+ method = p_method,
+ idl = p_idl,
+ idl_style = p_idl_style,
+ proc = p_proc,
+ notes = p_notes
+ where
+ method_id = p_method_id;
+
+ -- return something
+ return 0;
+
+end;' language 'plpgsql';
+
+-- check method id
+create function sg_method__exists(integer)
+returns integer as '
+declare
+ p_method_id alias for $1;
+ v_record record;
+begin
+
+ -- get method count for id
+ select into v_record count(*)
+ from sg_methods
+ where method_id = p_method_id;
+
+ -- test
+ return v_record.count;
+
+end;' language 'plpgsql';
+
+-- remove method
+create function sg_method__delete (integer)
+returns integer as '
+declare
+ p_method_id alias for $1;
+begin
+
+ -- verify id
+ if sg_method__exists(p_method_id) = 0 then
+ raise EXCEPTION ''Invalid method id: %'', p_method_id;
+ end if;
+
+
+ -- clean up permissions for method
+ delete from acs_permissions
+ where object_id = p_method_id;
+
+ -- remove method object
+ perform acs_object__delete(p_method_id);
+
+ -- remove methods
+ delete from sg_methods
+ where method_id = p_method_id;
+
+ return 0;
+
+end;' language 'plpgsql';
+
+-- create new library
+create function sg_library__new(varchar)
+returns integer as '
+declare
+ p_path alias for $1;
+
+ v_library_id sg_libraries.library_id%type;
+begin
+
+ -- create next val
+ v_library_id = nextval(''sg_library_id_seq'');
+
+ -- add to library table
+ insert into sg_libraries
+ (library_id, path)
+ values
+ (v_library_id, p_path);
+
+ -- return id
+ return v_library_id;
+
+end;' language 'plpgsql';
+
+-- update library
+create function sg_library__update(integer, varchar)
+returns integer as '
+declare
+ p_library_id alias for $1;
+ p_path alias for $2;
+begin
+
+ -- update row values
+ update sg_libraries
+ set
+ path = p_service
+ where
+ library_id = p_library_id;
+
+ -- return something
+ return 0;
+
+end;' language 'plpgsql';
+
+-- remove library
+create function sg_library__delete (integer)
+returns integer as '
+declare
+ p_library_id alias for $1;
+begin
+
+ -- remove
+ delete from sg_libraries
+ where library_id = p_library_id;
+
+ return 0;
+
+end;' language 'plpgsql';
+
+-- returns namespace name
+create function sg_namespaces__name (integer)
+returns varchar as '
+declare
+ id alias for $1;
+ v_name sg_namespaces.service%TYPE;
+begin
+ select service into v_name
+ from sg_namespaces
+ where namespace_id = id;
+
+ return v_name;
+end;' language 'plpgsql';
+
+-- returns method name
+create function sg_methods__name (integer)
+returns varchar as '
+declare
+ id alias for $1;
+ v_name sg_methods.method%TYPE;
+begin
+ select method into v_name
+ from sg_methods
+ where method_id = id;
+
+ return v_name;
+end;' language 'plpgsql';
+
+-- forces namespace to dirty state for WSDL regen
+create function sg_namespaces__dirty(integer)
+returns integer as '
+declare
+ id alias for $1;
+begin
+ update sg_namespaces
+ set dirty = ''t''
+ where namespace_id = id;
+ return 0;
+end;' language 'plpgsql';
+
+-- trigger functions
+create function sg_methods__itrg ()
+returns opaque as '
+begin
+ perform sg_namespaces__dirty(new.namespace_id);
+ return new;
+end;' language 'plpgsql';
+
+create function sg_methods__dtrg ()
+returns opaque as '
+begin
+ perform sg_namespaces__dirty(old.namespace_id);
+ return old;
+end;' language 'plpgsql';
+
+create function sg_methods__utrg ()
+returns opaque as '
+begin
+ perform sg_namespaces__dirty(new.namespace_id);
+ if new.namespace_id <> old.namespace_id then
+ perform sg_namespacs__dirty(old.namespace_id);
+ end if;
+ return old;
+end;' language 'plpgsql';
+
+-- create triggers
+create trigger sg_methods__itrg after insert on sg_methods
+for each row execute procedure sg_methods__itrg ();
+
+create trigger sg_methods__dtrg after delete on sg_methods
+for each row execute procedure sg_methods__dtrg ();
+
+create trigger sg_methods__utrg after update on sg_methods
+for each row execute procedure sg_methods__utrg ();
+
+-- post intallation configuration
+select sg_library__new('packages/soap-gateway/lib/workspace-procs.tcl') from dual;
+select sg_library__new('packages/soap-gateway/lib/interop-procs.tcl') from dual;
+
+
Index: openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/sql/postgresql/soap-gateway-drop.sql 17 Oct 2004 05:51:52 -0000 1.1
@@ -0,0 +1,100 @@
+-- packages/soap-gateway/sql/postgresql/soap-gateway-drop.sql
+--
+-- @author WilliamB@ByrneLitho.com
+-- @creation-date 2002-12-22
+-- @cvs-id $Id: soap-gateway-drop.sql,v 1.1 2004/10/17 05:51:52 ncarroll Exp $
+--
+--
+
+--drop permissions
+delete from acs_permissions where object_id in (select method_id from sg_methods);
+delete from acs_permissions where object_id in (select namespace_id from sg_namespaces);
+delete from acs_permissions where object_id in (select object_id from acs_objects where object_type in ('wsdl_namespace','wsdl_method'));
+delete from acs_permissions where object_id in (select package_id from apm_packages where package_key in ('soap-gateway'));
+
+-- clear objects
+create function inline_0 ()
+returns integer as '
+declare
+ object_rec record;
+begin
+ for object_rec in select object_id from acs_objects where object_type in (''wsdl_namespace'',''wsdl_method'')
+ loop
+ perform acs_object__delete( object_rec.object_id );
+ end loop;
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+
+create function inline_2 ()
+returns integer as '
+declare
+ v_invoke varchar;
+begin
+ select invoke into v_invoke from sg_invoke_moniker;
+
+ -- unbind privileges to global names
+ perform acs_privilege__remove_child(''admin'', v_invoke);
+
+ -- drop privileges
+ perform acs_privilege__drop_privilege(v_invoke);
+
+
+ return 0;
+end;' language 'plpgsql';
+select inline_2();
+drop function inline_2();
+
+
+-- drop triggers
+drop trigger sg_methods__itrg on sg_methods;
+drop trigger sg_methods__dtrg on sg_methods;
+drop trigger sg_methods__utrg on sg_methods;
+
+-- drop functions
+drop function sg_namespace__get_id(varchar);
+drop function sg_namespace__new(varchar, varchar, varchar, timestamptz, integer, varchar, integer);
+drop function sg_namespace__update(integer, varchar, varchar, varchar);
+drop function sg_namespace__exists(integer);
+drop function sg_namespace__delete (integer);
+drop function sg_method__new(integer, varchar, varchar, varchar, varchar, varchar, timestamptz, integer, varchar, integer);
+drop function sg_method__update(integer, varchar, varchar, varchar, varchar, varchar);
+drop function sg_method__exists(integer);
+drop function sg_method__delete (integer);
+drop function sg_namespaces__name (integer);
+drop function sg_methods__name (integer);
+drop function sg_namespaces__dirty(integer);
+drop function sg_methods__itrg();
+drop function sg_methods__dtrg();
+drop function sg_methods__utrg();
+drop function sg_library__new(varchar);
+drop function sg_library__update(integer, varchar);
+drop function sg_library__delete(integer);
+drop function sg_unique(integer,varchar);
+
+-- drop tables
+drop table sg_methods;
+drop table sg_namespaces;
+drop table sg_libraries;
+
+-- drop sequences
+drop sequence sg_library_id_seq;
+
+-- drop views
+drop view sg_invoke_moniker;
+
+-- drop attributes
+
+-- drop type
+select acs_object_type__drop_type(
+ 'wsdl_namespace',
+ 't'
+ );
+select acs_object_type__drop_type(
+ 'wsdl_method',
+ 't'
+ );
+
Index: openacs-4/packages/soap-gateway/tcl/soap-fault-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-fault-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-fault-procs.tcl 17 Oct 2004 05:51:52 -0000 1.1
@@ -0,0 +1,239 @@
+ad_library {
+ Tcl API for SOAP Faults.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+ @author Nick Carroll (ncarroll@ee.usyd.edu.au)
+ @creation-date 2004-09-24
+ @cvs-id $Id: soap-fault-procs.tcl,v 1.1 2004/10/17 05:51:52 ncarroll Exp $
+}
+
+
+namespace eval soap::fault {}
+
+
+ad_proc -public soap::fault::assert {
+ test
+ msg
+} {
+ @param test
+ @param msg
+} {
+ # calculate
+ if [catch {set test [uplevel expr $test] } ] {
+ # throw
+ soap::fault::raise "Assertion\ntest: $test\n$msg"
+ }
+
+ # test
+ if { [string is integer -strict $test] == 0 || $test == 0 } {
+ # throw
+ soap::fault::raise "Assertion\ntest: $test\n$msg"
+ }
+}
+
+
+ad_proc -public soap::fault::raise {
+ msg
+ {code 500}
+} {
+ @param msg
+ @param code Default code set to 500.
+} {
+
+ # throw
+ error "SOAP Gateway Error\n$msg" {} $code
+}
+
+
+ad_proc -public soap::fault::unauthorized {
+ {msg "Access Denied"}
+} {
+ @param msg
+} {
+
+ # throw
+ soap::fault::raise "$msg" 401
+}
+
+
+ad_proc -public soap::fault::unsupported {
+ msg
+} {
+ @param msg
+} {
+
+ # throw
+ soap::fault::raise "$msg" 501
+}
+
+
+ad_proc -private soap::fault::generate_fault {
+ msg
+ {ver 1.1}
+} {
+ Generates a fault response based on the specified message.
+
+ @param msg The message to be sent back to the client.
+ @param ver The version of SOAP that the message should be based on.
+ @return Returns a fault response SOAP message.
+} {
+ # get version namespace
+ set version [soap::server::get_version_namespace $ver]
+
+ # construct xml doc object
+ set doc [dom createDocument env:Envelope]
+
+ # create root node: "env:Envelope"
+ set env [$doc documentElement]
+
+ # define namespace atts into node
+ $env setAttribute xmlns:env $version
+
+ # create Body node - "env:Envelope/env:Body"
+ set body [$env appendChild [$doc createElement env:Body]]
+
+ # create Fault node - "env:Envelope/env:Body/env:Fault"
+ set fault [$body appendChild [$doc createElement env:Fault]]
+
+ # test version
+ if { $ver == "1.1" } {
+
+ # create faultcode node
+ # env:Envelope/env:Body/env:Fault/env:faultcode
+ $fault appendXML "env:Client"
+
+ # create faultstring node
+ # env:Envelope/env:Body/env:Fault/env:faultstring
+ $fault appendXML "$msg"
+
+ } else {
+
+ # do v1.2
+
+ # create Code node and Value as a sub node of Code
+ # env:Envelope/env:Body/env:Fault/env:Code
+ # env:Envelope/env:Body/env:Fault/env:Code/env:Value
+ $fault appendXML "
+
+ env:Sender
+ "
+
+ # create Reason node
+ # env:Envelope/env:Body/env:Fault/env:Reason
+ # define lang attr into Reason node
+ $fault appendFromList [list env:Reason {xml:lang en-US} {}]
+ }
+
+ # render xml into result string
+ return [$env asXML]
+}
+
+ad_proc -private soap::fault::generate_misunderstood {
+ namespaces
+ {ver 1.1}
+} {
+ Generates a misunderstood fault response based on the
+ specified namespaces.
+
+ @param namespaces The message to be sent back to the client.
+ @param ver The version of SOAP that the message should be based on.
+ @return Returns a misunderstood fault response SOAP message.
+} {
+ # set envelope version
+ set version [soap::server::get_version_namespace $ver]
+
+ # construct xml doc object
+ set doc [dom createDocument env:Envelope]
+
+ # create root node: "env:Envelope"
+ set env [$doc documentElement]
+
+ # define namespace atts into node
+ $env setAttribute xmlns:env $version
+ $env setAttribute xmlns:flt http://www.w3.org/2003/05/soap-faults
+
+ # create Header node - "env:Envelope/env:Header"
+ set header [$env appendChild [$doc createElement env:Header]]
+
+ # loop through namespaces and add
+ foreach ns $namespaces {
+ # safety
+ if { [llength $ns] > 1 } {
+ # add child
+ set mu [$header appendChild [$doc createElement flt:Misunderstood]]
+
+ # get qname
+ set qname [lindex $ns 0]
+
+ # split off namespace prefix
+ set parts [split $qname :]
+
+ # test
+ if { [llength $parts] > 1 } {
+ # get prefix
+ set prefix [lindex $parts 0]
+
+ # get name
+ set name [lindex $parts 1]
+ } else {
+ # generate prefix
+ append auto x
+
+ # set prefix to auto
+ set prefix $auto
+
+ # set name to qname
+ set name $qname
+ }
+
+ # add name attr
+ $mu setAttribute qname "$prefix:$name"
+
+ # add namespace
+ $mu setAttribute "xmlns:$prefix" [lindex $ns 1]
+ }
+ }
+
+ # create Body node - "env:Envelope/env:Body"
+ set body [$env appendChild [$doc createElement env:Body]]
+
+ # create Fault node - "env:Envelope/env:Body/env:Fault"
+ set fault [$body appendChild [$doc createElement env:Fault]]
+
+ # test version
+ if { $ver == "1.1" } {
+
+ # create faaultcode node
+ #env:Envelope/env:Body/env:Fault/env:faultcode
+ $fault appendXML "env:MustUnderstand"
+
+ # create faultstring node
+ # env:Envelope/env:Body/env:Fault/env:faultstring
+ $fault appendXML "One or more mandatory headers not understood"
+
+ } else {
+
+ # do v1.2
+
+ # create Code node
+ # env:Envelope/env:Body/env:Fault/env:Code
+ # env:Envelope/env:Body/env:Fault/env:Code/env:Value
+ $fault appendXML "
+
+ env:MustUnderstand
+ "
+
+ # create Reason node
+ # env:Envelope/env:Body/env:Fault/env:Reason
+ set reason [$fault appendChild [$doc createElement env:Reason]]
+
+ # define lang attr into Reason node
+ $reason setAttribute xml:lang "en-US"
+
+ # set message for env:Reason.
+ $reason appendChild [$doc createTextNode "One or more mandatory headers not understood"]
+ }
+
+ # render xml into result string
+ return [$env asXML]
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-init.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-init.tcl 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,10 @@
+ad_library {
+
+ soap-gateway init library routines
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+
+}
+
+# schedule a one time directory scan for service source files
+ad_schedule_proc -thread t -once t 5 soap::server::lib::boot_libraries
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-procs-postgresql.xql 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,51 @@
+
+
+
+ postgresql7.1
+
+
+
+ select proc
+ from sg_methods
+ where namespace_id = :namespace_id
+ order by method_id
+
+
+
+
+
+ select service from sg_namespaces;
+
+
+
+
+
+ select package_id from apm_packages where package_key = 'soap-gateway'
+
+
+
+
+
+ select sg_namespace__exists(:namespace_id);
+
+
+
+
+
+ select sg_method__exists(:method_id)
+
+
+
+
+
+ select 0 + sg_namespace__delete(:namespace_id);
+
+
+
+
+
+ select 0 + sg_method__delete(:method_id);
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-procs.tcl 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,852 @@
+ad_library {
+ SOAP utils API.
+
+ Based on William Byrne's soap-gateway implementation.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+ @author Nick Carroll (ncarroll@ee.usyd.edu.au)
+ @creation-date 2004-09-24
+ @cvs-id $Id: soap-procs.tcl,v 1.1 2004/10/17 05:51:53 ncarroll Exp $
+}
+
+
+namespace eval soap {}
+
+# Libraries in the lib directory must run in the sg namespace.
+namespace eval sg {}
+
+
+ad_proc -public soap::check_str_len {
+ string
+ length
+ {warning {string is too long}}
+} {
+ Verifies the string does not exceed length
+
+ @param string
+ @param length
+ @param warning
+} {
+ if { [string length $string] > $length } {
+ # throw
+ soap::fault::raise $warning
+ }
+}
+
+
+# create login wrapper for sg services
+ad_proc -public soap::login {
+ user
+ password
+} {
+ @param user
+ @param password
+} {
+ # normalize id
+ set email [string tolower $user]
+
+ # search for
+ set result [db_0or1row user_login_user_id_from_email {
+ select user_id, member_state, email_verified_p
+ from cc_users
+ where email = :email}]
+
+ # good house keeping
+ db_release_unused_handles
+
+ # verify
+ if { $result == 0 } {
+ # rejected
+ soap::fault::unauthorized "Access Denied\n$email not registered"
+ }
+
+ # again
+ if { $member_state != "approved" || $email_verified_p == "f" } {
+ # rejected
+ soap::fault::unauthorized "Access Denied\nMember: $member_state\ne-mail: $email_verified_p"
+ }
+
+ # and again
+ if { ![ad_check_password $user_id $password] } {
+ # rejected
+ soap::fault::unauthorized "Access Denied\nInvalid user or password"
+ }
+
+ # is this necessary ???
+ ad_user_logout
+
+ # log user
+ ad_user_login -forever=1 $user_id
+
+ # return 0
+ return 0
+}
+
+
+# create logout wrapper for sg services
+ad_proc -public soap::logout {
+} {
+ @author William Byrne
+} {
+ # clear cookies
+ ad_user_logout
+}
+
+
+ad_proc -private soap::method_check {
+ method_id
+} {
+ @param method_id
+} {
+ # exec db
+ set exists [db_string method_exists {} -default 0]
+
+ # test result
+ if { $exists == 0 || [string is integer $exists] != 1 } {
+ # failed, throw
+ soap::fault::raise "invalid method id: $namespace_id"
+ }
+ # valid
+}
+
+
+ad_proc -public soap::namespace_delete {
+ namespace_id
+} {
+ @param namespace_id
+} {
+ db_exec_plsql namespace_delete {}
+}
+
+
+ad_proc -public soap::method_delete {
+ method_id
+} {
+ @param method_id
+} {
+ # db update
+ db_exec_plsql delete_method {}
+}
+
+
+ad_proc -public soap::package_id {
+ {-throw 1}
+} {
+ @author William Byrne
+} {
+ # try and get id
+ set pid [apm_package_id_from_key soap-gateway]
+
+ # test
+ if { $pid != 0 } {
+ # done
+ return $pid
+ }
+
+ # memoize got fed bad stuff - clear it
+ util_memoize_flush_regexp "apm_package_id_from_key_mem soap-gateway"
+
+ # try again
+ set pid [apm_package_id_from_key soap-gateway]
+
+ # test
+ if { $pid != 0 } {
+ # done
+ return $pid
+ }
+
+ # crap - get connection
+ set pid [ad_conn package_id]
+
+ # verify
+ if [string equal [apm_package_key_from_id $pid] soap-gateway] {
+ #done
+ return $pid
+ }
+
+ # how 'bout the db
+ set pid [db_string select_pid {} -default 0]
+
+ # test
+ if { $pid != 0 } {
+ # done
+ return $pid
+ }
+
+ # throw
+ if [soap::server::lib::true $throw] {
+ soap::fault::raise "Cannot get package id for soap-gateway"
+ }
+
+ # return error
+ return 0
+}
+
+
+ad_proc -private soap::get {
+ {-set sg_properties}
+ property
+} {
+ @param property
+} {
+ # check set
+ if ![nsv_exists $set $property] {
+ # return empty
+ return {}
+ }
+
+ # get em
+ return [nsv_get $set $property]
+}
+
+
+ad_proc -private soap::namespace_get_names {
+} {
+ @author William Byrne
+} {
+ # init
+ set names [list]
+
+ # loop through namespaces
+ db_foreach select_services {} {
+ # append name
+ lappend names $service
+ }
+
+ # return names
+ return $names
+}
+
+
+ad_proc -private soap::query_services {
+ {-unpublished 0}
+ {-published 1}
+
+} {
+ @author William Byrne
+} {
+
+ # get active services
+ set services [soap::namespace_get_names]
+
+ # test for request
+ if $unpublished {
+ # decl unpublished list
+ set unpub [list]
+
+ # create lower case services
+ set lowercase_services [string tolower $services]
+
+ # get all namespaces under ::sg
+ foreach service [namespace children ::sg] {
+ # get child portion of namespace only - skip
+ # '::sg::' portion of string
+ set child [namespace tail $service]
+
+ # search for existing
+ if { [lsearch $lowercase_services [string tolower $child]] < 0 } {
+ # add to unpublished list
+ lappend unpub $child
+ }
+ }
+
+ # want all
+ if $published {
+ # add to services
+ return [concat $services $unpub]
+ } else {
+ # return list
+ return $unpub
+ }
+ }
+
+ # return services list
+ return $services
+}
+
+
+ad_proc -private soap::get_idl_help {
+} {
+ @author William Byrne
+} {
+
+ # return simple instructions
+ set help {
+
+ Use "C" style function syntax. Data type map:
+
+ Data Type | XML Schema |
+ char, char[], string | xsd:string |
+ int, long | xsd:int |
+ float, double | xsd:double |
+ __int64 | xsd:long |
+ void | - |
+
+
+ }
+}
+
+
+ad_proc -private soap::check_symbol {
+ symbol
+} {
+ @param symbol
+} {
+
+ # setup reg expr
+ set r {(^[^a-zA-Z]*)([a-zA-Z][a-zA-Z0-9_]*)([^a-zA-Z0-9_]*$)}
+
+ # call
+ set e [regexp $r $symbol {} a b c]
+
+ # test - requiring symbol not to exceed 64 characters ???
+ if {
+ $e == 0 ||
+ [string length $a] > 0 ||
+ [string length $b] > 64 ||
+ [string length $c] > 0
+ } {
+ # no good
+ soap::fault::raise "Invalid symbol: '$symbol'"
+ }
+}
+
+
+ad_proc -private soap::service_from_uri {
+ uri
+} {
+ @author William Byrne
+} {
+
+ # expects format similar to that returned
+ # from soap::wsdl::build_namespace_uri
+
+ # skip protocol scheme
+ set offset [string first {://} $uri]
+
+ # found ?
+ if { $offset >= 0 } {
+ # strip scheme
+ set uri [string range $uri [expr $offset + 3] end]
+ }
+
+ # split sub domains and return first
+ return [llindex [split $uri .] 0]
+}
+
+
+ad_proc -private soap::get_base_url {
+} {
+ @author William Byrne
+} {
+
+ # calc href base
+ set base [ad_conn package_url]
+
+ # verify we're in a soap-gateway site
+ if { ![string equal [ad_conn package_key] "soap-gateway"] } {
+ # force to apm registration
+ set base [apm_package_url_from_key soap-gateway]
+ }
+
+ # test for problems
+ if { $base == {} } {
+ # force to install mode
+ set base {/soap/}
+ }
+
+ # return it
+ return $base
+}
+
+
+ad_proc -private soap::get_doc_elements {
+ {-service {}}
+ proc
+} {
+ @param proc
+} {
+ # test for service arg
+ if { $service != {} } {
+ # build full path
+ set proc [format "::sg::%s::%s" $service $proc]
+ }
+
+ # try and get elements
+ if [catch {
+ # try
+ set elements [nsv_get api_proc_doc $proc]
+ }] {
+ # failed - strip off leading namespace qualifier
+ set elements [nsv_get api_proc_doc [string range $proc 2 end]]
+ }
+
+ # return elements
+ return $elements
+}
+
+
+ad_proc -private soap::get_source_procs {
+ {-private 0}
+ {-local 0}
+ service
+} {
+ Returns a list of procedures within the tcl namespace
+ formulated by sg::::*
+
+ @param service
+} {
+ # decl unpublished list
+ set procs [list]
+
+ # safe fetch
+ catch {
+ # get methods
+ set procs [info commands [format "::sg::%s::*" $service]]
+ }
+
+ # decl result
+ set result [list]
+
+ # loop through source procs
+ foreach proc $procs {
+
+ # test for public
+ set public 0
+
+ # safe
+ catch {
+
+ # get proc doc elements
+ array set doc_elements [nsv_get api_proc_doc \
+ [string range $proc 2 end]]
+
+ # assign
+ set public $doc_elements(public_p)
+ }
+
+ # test
+ if { $public || $private } {
+ # test for local (no namespace)
+ if [soap::server::lib::true $local] {
+ # get last element after ::
+ regexp {([^:]+$)} $proc {} proc
+ }
+ # add to list
+ lappend result $proc
+ }
+ }
+
+ # return procs
+ return $result
+}
+
+
+ad_proc -private soap::get_source_idl {
+ proc
+} {
+ Returns the idl of a procedure. If the procedure exists,
+ an attempt is made to return @idl description. If @idl doesn't
+ exists, the idl is formulated from the procedures args. If
+ the procedure doesn't exists, an empty value is returned.
+
+ @param proc
+} {
+ # build formal name
+ set formal $proc; #[format "::sg::%s::%s" $service $proc]
+
+ # verify
+ if { [info commands $formal] == {} } {
+ # let's return empty string to signal error
+ soap::fault::raise "Cannot get idl for invalid procedur: $proc"
+ }
+
+ # decl idl
+ set idl {}
+
+ # safe
+ catch {
+ # get the documentenation array for the method
+ array set doc_elements [soap::get_doc_elements $formal]
+
+ # get the @idl value and remove curlies via 'join'
+ set idl [join $doc_elements(idl)]
+ }
+
+ # test idl
+ if { $idl == {} } {
+
+ # build from tcl info
+
+ # decl temp
+ set args2 {}
+
+ # the default idl will always return a string
+ # and each arg will be type string
+ foreach arg [info args $formal] {
+
+ # first time
+ if { $args2 == {} } {
+ # assign
+ set args2 "string $arg"
+ } else {
+ # add to
+ append args2 ", string $arg"
+ }
+ }
+
+ # remove namespace from proc
+ set proc [namespace tail $proc]
+
+ # finish
+ set idl [format "string %s(%s)" $proc $args2]
+ }
+
+ # return whatever we got
+ return $idl
+}
+
+
+ad_proc -private soap::get_source_idls {
+ service
+} {
+ Returns a list of idls for public procedures defined
+ within the sg:::: namespace.
+
+ @see soap::get_source_idl
+ @param service
+} {
+ # get source procs for service
+ set procs [soap::get_source_procs $service]
+
+ # decl result list
+ set result [list]
+
+ # loop though procs
+ foreach proc $procs {
+ # get idl for proc
+ lappend result [soap::get_source_idl $proc]
+ }
+
+ # return list
+ return $result
+}
+
+
+ad_proc -private soap::method_get_procs {
+ namespace_id
+} {
+ @param namespace_id
+} {
+ # init
+ set procs [list]
+
+ db_foreach select_procs {} {
+ # append method proc
+ lappend procs $proc
+ }
+
+ # return methods
+ return $procs
+}
+
+
+ad_proc -private soap::diff_methods {
+ {-same 0}
+ service
+} {
+ Compares the published service methods to those in the source file
+ @param service
+} {
+ # decl unpublished list
+ set procs [soap::get_source_procs $service]
+
+ # decl published list
+ set methods [list]
+ set idls [list]
+
+ # get namespace id
+ set nid [soap::server::namespace_get_id $service]
+
+ # verify
+ if { $nid >= 0 } {
+
+ # get published method Tcl proc bindings (proc symbol in db);
+ set bindings [soap::method_get_procs $nid]
+
+ # and their idls
+ set idls [soap::wsdl::method_get_idls $nid]
+ }
+
+ # decl history list
+ set history [list]
+
+ # decl diff array
+ array set diffs [list]
+
+ # decl short names list for procs
+ set shorts [list]
+
+ # get idl parser expression for method - "C" syntax
+ set method_expr [soap::wsdl::get_style_parser_expr C]
+ set arg_expr [soap::wsdl::get_style_parser_expr -argpart 1 C]
+
+ # decl published list
+ set published [list]
+
+ # duplicate procs as they're duplicated in the WSDL
+ # database - this will ensure
+ # every entry in the database is tested. ??? weak
+
+ # decl dups
+ set dups [list]
+
+ # scan
+ foreach proc $procs {
+
+ # trim proc name
+ set short [namespace tail $proc]
+
+ # decl counter
+ set count 0
+
+ # get hits in db
+ foreach binding $bindings {
+
+ # compare
+ if [string equal $binding $short] {
+
+ # incr counter
+ incr count
+
+ # test for more than 1
+ if { $count > 1 } {
+
+ # add dup
+ lappend dups $proc
+ }
+ }
+ }
+ }
+
+ # update proc list with duplicated db method entries
+ foreach dup $dups {
+ # add to proc list
+ lappend procs $dup
+ }
+
+ # loop through source procs
+ foreach proc $procs {
+
+ # trim proc name
+ set short [namespace tail $proc]
+
+ # decl found
+ set found {}
+
+ # decl diff var
+ set diff {}
+
+ # get args for source proc (unpublished?)
+ set src_idl [soap::get_source_idl $proc]; #[info args $proc]
+
+ # decl uargs (unpublished)
+ set uargs {}
+
+ # invoke regexp to get args
+ if [regexp $method_expr $src_idl {} type src_meth argz] {
+
+ # loop through args
+ foreach arg [split $argz ,] {
+
+ # split
+ if [regexp $arg_expr $arg {} type name] {
+
+ # add to list
+ lappend uargs $name
+ }
+ }
+ } else {
+ # store for check below
+ set src_meth $short
+ }
+
+ # search published
+ foreach binding $bindings idl $idls {
+
+ # try
+ if [catch {
+
+ # test for case sensitive match
+ if [string equal $short $binding] {
+
+ # decl pargs
+ set pargs [list]
+
+ # invoke regexp to get args
+ if [regexp $method_expr $idl {} type method argz] {
+
+ # loop through args
+ foreach arg [split $argz ,] {
+
+ # split
+ if [regexp $arg_expr $arg {} type name] {
+
+ # add to list
+ lappend pargs $name
+ }
+ }
+
+ # park idl method name into found - used below
+ #set found $meth
+ } else {
+ # egats
+ continue
+ }
+
+ # set found indicator
+ set found $method
+
+ # compare unpublished args against published args
+
+ # compare
+ if { [llength $uargs] != [llength $pargs] } {
+
+ # note difference
+ set diff [list $uargs $pargs]
+
+ } else {
+
+ # compare arg names
+ foreach u $uargs p $pargs {
+
+ # compare
+ if ![string equal -nocase $u $p] {
+
+ # note difference
+ set diff [list $uargs $pargs]
+
+ # enough to note diff
+ break
+ }
+ }
+ }
+
+ # add to published list
+ lappend published $binding
+
+ # get idx of binding
+ set idx [lsearch $bindings $binding]
+
+ # remove from db lists
+ set bindings [lreplace $bindings $idx $idx]
+ set idls [lreplace $idls $idx $idx]
+ set methods [lreplace $methods $idx $idx]
+ }
+ } msg] {
+
+ # show error for diff
+ set diff "err $msg"
+ }
+
+ # test found
+ if { $found != {} } {
+ # stop scanning bindings for match - we found it
+ break
+ }
+ }
+
+ # found ?
+ if { $found != {} } {
+
+ # upper case found
+ set ufound [string toupper $found]
+
+ # check for duplicate
+ if { [lsearch $history $ufound] >= 0 } {
+ # mark as duplicate
+ set diffs($found) [list DUPL $uargs $pargs]
+ } else {
+ # differences ?
+ if { $diff != {} } {
+ # append to results list
+ set diffs($found) [list ARGS $uargs $pargs]
+ } elseif [soap::server::lib::true $same] {
+ # append procs that are identical - 'same' flag set
+ set diffs($found) [list SAME $uargs $pargs]
+ }
+
+ # add to history
+ lappend history $ufound
+ }
+ } else {
+
+ # upper case
+ set found [string toupper $src_meth]
+
+ # use full proc name to avoid potential clash
+ # with any db methods of same name
+
+ # check for duplicate
+ if { [lsearch $history $found] >= 0 } {
+ # mark as duplicate
+ set diffs($proc) [list DUPL $uargs {}]
+ } else {
+ # append missing - modify array key to avoid
+ # clash with db method of same name
+ set diffs($proc) [list UPUB $uargs {}]
+
+ # add to history
+ lappend history $found
+ }
+ }
+ }
+
+ # add remaining bindings
+ foreach binding $bindings idl $idls {
+
+ # invoke regexp to get args
+ if [regexp $method_expr $idl {} type method argz] {
+
+ # decl pargs
+ set pargs [list]
+
+ # loop through args
+ foreach arg [split $argz ,] {
+ # split
+ if [regexp $arg_expr $arg {} type name] {
+ # add to list
+ lappend pargs $name
+ }
+ }
+
+ # append missing
+ set diffs($method) [list ORPH {} $pargs]
+
+ } else {
+
+ # append error
+ set diffs($binding) [list ERR {} {}]
+ }
+ }
+
+ #return differences
+ return [array get diffs]
+}
+
+
+ad_proc -private soap::namespace_check {
+ namespace_id
+} {
+ @param namespace_id
+} {
+ # exec db
+ set exists [db_string namespace_exists {} -default 0]
+
+ # test result
+ if { $exists == 0 || [string is integer $exists] != 1 } {
+ # failed, throw
+ soap::fault::raise "invalid namespace id: $namespace_id"
+ }
+ # valid
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs-postgresql.xql 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,94 @@
+
+
+
+ postgresql7.1
+
+
+
+ select path from sg_libraries;
+
+
+
+
+
+ select sg_method__new(
+ :namespace_id,
+ :method,
+ :idl,
+ :idl_style,
+ :proc,
+ :notes,
+ now(),
+ :user_id,
+ :peeraddr,
+ :package_id
+ );
+
+
+
+
+
+ select sg_namespace__new (
+ :service,
+ :uri,
+ :notes,
+ now(),
+ :user_id,
+ :peeraddr,
+ :package_id
+ ) from dual;
+
+
+
+
+
+ select sg_namespace__update(
+ :namespace_id,
+ :service,
+ :uri,
+ :notes,
+ ) from dual;
+
+
+
+
+
+ select service, uri, notes
+ from sg_namespaces
+ where namespace_id = :nid
+
+
+
+
+
+
+
+
+
+
+
+ select sg_library__new(:path) from dual
+
+
+
+
+
+ select path
+ from sg_libraries
+ where library_id = :library_id
+
+
+
+
+
+ select 0 + sg_library__delete(:library_id)
+
+
+
+
+
+ select 0 + sg_library__update(:library_id,:path)
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-server-lib-procs.tcl 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,624 @@
+ad_library {
+
+ SOAP API for registering and handling TCL services located in the
+ library directory.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+ @author Nick Carroll (ncarroll@ee.usyd.edu.au)
+}
+
+
+namespace eval soap::server::lib {}
+
+
+ad_proc -public soap::server::lib::library_new {
+ path
+} {
+ @param path
+} {
+ db_exec_plsql library_new {}
+}
+
+
+ad_proc -public soap::server::lib::library_update {
+ library_id
+ path
+} {
+ @param library_id
+ @param path
+} {
+ db_exec_plsql update_library {}
+}
+
+ad_proc -public soap::server::lib::library_delete {
+ library_id
+} {
+ @param library_id
+} {
+ db_exec_plsql delete_library {}
+}
+
+
+ad_proc -public soap::server::lib::library_get_path {
+ library_id
+} {
+ @param library_id
+} {
+ set path [db_string select_path {} -default {} ]
+
+ # return
+ return $path
+}
+
+
+ad_proc -private soap::server::lib::is_library_valid {
+ library
+} {
+ @param library
+} {
+
+ # get root without tail /
+ set root [file join [acs_root_dir]]
+
+ # test for directory
+ if [file isdirectory [file join $root $library]] {
+ # append wildcard
+ set library [file join $library *.tcl]
+ }
+
+ # scan glob list
+ foreach f [glob -nocomplain -directory $root $library] {
+ # verify extension
+ if ![string equal -nocase [file extension $f] {.tcl}] {
+ # skip it
+ continue
+ }
+ # yup
+ return 1
+ }
+ # clean
+ return 0
+}
+
+ad_proc -private soap::server::lib::is_library_dirty {
+ library
+} {
+ @author William Byrne
+} {
+ # get root without trailing /
+ set root [file join [acs_root_dir]]
+
+ # get len + 1 for eventual /
+ set len [expr [string length $root] + 1]
+
+ # test for directory
+ if [file isdirectory [file join $root $library]] {
+ # append wildcard
+ set library [file join $library *.tcl]
+ }
+
+ # scan glob list
+ foreach f [glob -nocomplain -directory $root $library] {
+ # verify extension
+ if ![string equal -nocase [file extension $f] {.tcl}] {
+ # skip it
+ continue
+ }
+
+ # get mtime
+ set mtime [file mtime $f]
+
+ # get short
+ set short [string range $f $len end]
+
+ # check to see if registered in loader
+ if ![nsv_exists apm_reload_watch $short] {
+ # remove from mtime
+ catch { nsv_unset apm_library_mtime $short }
+ }
+
+ # get property without root
+ set cached [soap::get -set apm_library_mtime $short]
+
+ # test
+ if { $cached == {} || $mtime != $cached } {
+ # dirty
+ return 1
+ }
+ }
+ # clean
+ return 0
+}
+
+
+ad_proc -private soap::server::lib::library_get_paths {
+} {
+ @author William Byrne
+} {
+ # init
+ set paths [list]
+
+ # loop through libraries
+ db_foreach select_lib_paths {} {
+ # append name
+ lappend paths $path
+ }
+
+ # return names
+ return $paths
+}
+
+
+ad_proc -public soap::server::lib::update_libraries {
+ {-stop 0}
+ {libraries [list]}
+} {
+ @author William Byrne
+} {
+ # get root without trailing /
+ set root [file join [acs_root_dir]]
+
+ # get len + 1 for eventual /
+ set len [expr [string length $root] + 1]
+
+ # loop through libraries
+ foreach lib $libraries {
+
+ # test for directory
+ if [file isdirectory [file join $root $lib]] {
+ # append wildcard
+ set lib [file join $lib *.tcl]
+ } elseif ![string equal -nocase [file extension $lib] {.tcl}] {
+ # skip it
+ continue
+ }
+
+ # scan glob list
+ foreach f [glob -nocomplain -directory $root $lib] {
+ # add to watch without root
+ soap::server::lib::watch -stop $stop [string range $f $len end]
+ }
+ }
+ # return something
+ return 1
+}
+
+
+ad_proc -private soap::server::lib::true {
+ value
+} {
+ @author William Byrne
+} {
+ # handle ints > 1 || < 0
+ if [string is integer $value] {
+ # eval
+ return [expr $value != 0 ? 1 : 0]
+ }
+
+ # empty value is false
+ return [expr [string length $value] > 0 && [string is true $value] ? 1 : 0]
+}
+
+
+ad_proc -public soap::server::lib::watch {
+ {-stop 0}
+ file
+} {
+ @author William Byrne
+} {
+ # setup result
+ set result 1
+
+ # test for stop
+ if [soap::server::lib::true $stop] {
+ # safe
+ if [catch {
+ # stop watch
+ nsv_unset apm_reload_watch $file
+ }] {
+ # egats
+ set result 0
+ }
+ # safe
+ catch {
+ # remove cache
+ nsv_unset apm_library_mtime $file
+ }
+
+ } else {
+ # add
+ apm_file_watch $file
+ }
+
+ # return status
+ return $result
+}
+
+
+ad_proc -public soap::server::lib::boot_libraries {
+} {
+ @author William Byrne
+} {
+ # get paths
+ set paths [soap::server::lib::library_get_paths]
+
+ # send to update
+ foreach lib $paths {
+ soap::server::lib::update_libraries $lib
+ }
+
+ # return something
+ return 1
+}
+
+
+ad_proc -private soap::server::lib::get_library_doc {
+ service
+} {
+ @param service
+} {
+ # get a command from namespace
+ set procs [info commands [format "::sg::%s" $service]]
+
+ # decl source path
+ set path {}
+
+ # any ?
+ if [llength $procs] {
+ # get first one
+ set proc [lindex $procs 0]
+
+ # safe
+ catch {
+ # get the documentenation array for the method
+ array set doc_elements [nsv_get api_proc_doc \
+ [format "::sg::%s::%s" $service $proc]]
+
+ # get script path
+ set path $doc_elements(script)
+ }
+ }
+
+ # check path
+ if { $path == {} } {
+
+ # try lib directory
+ set path "packages/soap-gateway/lib/[string tolower $service]-procs.tcl"
+ }
+
+ # decl result
+ set result {}
+
+ # try to get doc info from file
+ catch {
+ # get source file docs - force lower case convention
+ array set doc_elements [nsv_get api_library_doc $path]
+
+ # update and remove curlies
+ set result [join $doc_elements(main)]
+ }
+
+ # return whatever we got
+ return $result
+}
+
+
+ad_proc -public soap::server::lib::method_new {
+ namespace_id
+ method
+ idl
+ idl_style
+ proc
+ notes
+ user_id
+ peeraddr
+ package_id
+} {
+ @param namespace_id
+ @param method
+ @param idl
+ @param idl_style
+ @param proc
+ @param notes
+ @param user_id
+ @param peeraddr
+ @param package_id
+} {
+ # create new -
+ db_exec_plsql method_new {}
+}
+
+
+ad_proc -public soap::server::lib::namespace_new {
+ service
+ uri
+ notes
+ user_id
+ peeraddr
+ package_id
+} {
+ @param service
+ @param uri
+ @param notes
+ @param user_id
+ @param peeraddr
+ @param package_id
+} {
+ # db new
+ db_exec_plsql namespace_new {}
+}
+
+
+ad_proc -public soap::server::lib::namespace_update {
+ namespace_id
+ service
+ uri
+ notes
+} {
+ @param namespace_id
+ @param service
+ @param uri
+ @param notes
+} {
+ db_exec_plsql namespace_update {}
+}
+
+
+ad_proc -private soap::server::lib::get_proc_doc {
+ proc
+} {
+ @param proc
+} {
+ # decl result
+ set result {}
+
+ # safe
+ catch {
+
+ # remove sg namespace
+ if { [string equal -length 6 ::sg:: $proc] } {
+ # trim ::
+ set proc [string range $proc 2 end]
+ }
+
+ # get doc set for procedure
+ array set doc_elements [nsv_get api_proc_doc $proc]
+
+ # get main documentation and remove curlies
+ set result [join $doc_elements(main)]
+ }
+
+ # return procedure doc
+ return $result
+}
+
+
+ad_proc -private soap::server::lib::idl_to_xsd {
+ style
+ idl
+} {
+ @param style
+ @param idl
+} {
+ # verify style
+ if { [string compare -nocase $style "C"] != 0 } {
+
+ # not yet supported
+ soap::fault::unsupported "Unsupported IDL style: $style\n Use 'C'"
+
+ }
+
+ # set up regexp expression for "C" style function
+ set expr [soap::wsdl::get_style_parser_expr C]
+
+ # invoke regexp
+ regexp $expr $idl {} type method argz
+
+ # map type
+ set xtype [soap::wsdl::map_ctype_to_xtype $type]
+
+ # verify
+ if { [llength $xtype] > 1 } {
+
+ # not yet supported
+ soap::fault::unsupported "cannot spec non simple types: $type"
+
+ }
+
+ # setup arg list
+ set xargs [list]
+
+ # get arg parser expr
+ set expr [soap::wsdl::get_style_parser_expr -argpart 1 C]
+
+ # loop through args
+ foreach a [split $argz ,] {
+
+ # split arg type from its name
+ if ![regexp $expr $a {} typ nam] {
+
+ # format problem
+ error "unexpected argument format: $a"
+
+ }
+
+ # add arg to param order var
+ lappend order $nam
+
+ # map type
+ set xtype2 [soap::wsdl::map_ctype_to_xtype $typ]
+
+ # get component count
+ set cnt [llength $xtype2]
+
+ # test for simple
+ if { $cnt == 1 } {
+
+ # append to arg list
+ lappend xargs [list [lindex $xtype2 0] $nam]
+
+ } else {
+
+ # not yet supported
+ soap::fault::unsupported "cannot spec non simple types: $a, $xtype2"
+ }
+ }
+
+ # build return
+ return [list $xtype $method $xargs]
+}
+
+
+ad_proc -public soap::server::lib::method_update {
+ method_id
+ method
+ idl
+ idl_style
+ proc
+ notes
+} {
+ @param method_id
+ @param method
+ @param idl
+ @param idl_style
+ @param proc
+ @param notes
+} {
+ # update existing
+ db_exec_plsql method_update {}
+}
+
+
+ad_proc -private soap::server::lib::import_service {
+ {-force 0}
+ {-proc {}}
+ service
+} {
+ @param service
+} {
+ # set connection vars
+ set user_id [ad_conn user_id]
+ set peeraddr {}
+ set package_id [ad_conn package_id]
+
+ # verify workspace namespace
+ set nid [soap::server::namespace_get_id $service]
+
+ # test
+ if { $nid == -1 } {
+
+ # get doc
+ set notes [soap::server::lib::get_library_doc $service]
+
+ # create
+ soap::server::lib::namespace_new \
+ $service "http://$service.openacs.org/methods" \
+ $notes $user_id $peeraddr $package_id
+
+ # clear
+ unset notes
+
+ # get id
+ set nid [soap::server::namespace_get_id $service]
+
+ } elseif { $force } {
+
+ # query for namespace attributes
+ db_1row namespace_select {}
+
+ # get doc
+ set notes [soap::server::lib::get_library_doc $service]
+
+ # update with new notes
+ soap::server::lib::namespace_update $nid $service $uri $notes
+ }
+
+ # get public procs for namespace
+
+ # set method parameters - idl style
+ set idl_style {C}
+
+ # build procs list
+ set procs [soap::get_source_procs $service]
+
+ # test for optional proc arg
+ if { $proc != {} } {
+
+ # test for ns qualifier ??? (weak)
+ if ![string equal -length 6 $proc {::sg::}] {
+ # fix up
+ set proc [format "::sg::%s::%s" $service $proc]
+ }
+
+ # contained in list
+ if { [lsearch -exact $procs $proc] >= 0 } {
+ # use
+ set procs [list $proc]
+ } else {
+ # clear, not found
+ set procs [list]
+ }
+ }
+
+ # loop
+ foreach proc $procs {
+ # get idl
+ set idl [soap::get_source_idl $proc]
+
+ # get notes
+ set note [soap::server::lib::get_proc_doc $proc]
+
+ # try
+ if [catch {
+ # decompose IDL
+ set xsd [soap::server::lib::idl_to_xsd $idl_style $idl]
+ } msg] {
+ # report
+ soap::fault::raise "Error importing: $proc, idl: $idl\n$msg"
+ }
+
+ # get method name from idl
+ set method [lindex $xsd 1]
+
+ # remove namespace
+ set proc [namespace tail $proc]
+
+ # verify workspace method
+ set mid [soap::wsdl::method_get_id $nid $method]
+
+ # test
+ if { $mid == -1 } {
+ # create
+ soap::server::lib::method_new $nid $method $idl $idl_style \
+ $proc $note $user_id $peeraddr $nid
+
+ # test for 'login'
+ if [string equal -nocase $method "LOGIN"] {
+ # get method id
+ set mid [soap::wsdl::method_get_id $nid $method]
+
+ # verify
+ soap::fault::assert {$mid != -1} "Error retrieving 'login' method id: $method => $mid"
+
+ # get public
+ set public_id [acs_magic_object the_public]
+
+ # get invoke symbol
+ set invoke [soap::server::get_invoke_permission_moniker]
+
+ # grant invoke permission to public
+ permission::grant -party_id $public_id -object_id $mid -privilege $invoke
+
+ # verify
+ set ok [permission::permission_p -party_id $public_id -object_id $mid -privilege $invoke]
+ soap::fault::assert $ok "Error granting '$invoke' permission to public"
+ }
+ } elseif { $force } {
+ # update
+ error "soap::server::lib::method_update $mid $method $idl $idl_style $proc $note"
+ }
+ }
+
+ # return namespace id
+ return $nid
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-server-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-server-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-server-procs-postgresql.xql 17 Oct 2004 05:51:53 -0000 1.1
@@ -0,0 +1,32 @@
+
+
+
+ postgresql7.1
+
+
+
+ select sg_namespace__get_id(:service) from dual
+
+
+
+
+
+ select sg_namespace__get_id(:service) from dual
+
+
+
+
+
+ select method_id || ' ' || proc
+ from sg_methods
+ where namespace_id = :namespace_id and
+ lower(method) = lower(:method)
+
+
+
+
+
+ select * from sg_invoke_moniker
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-server-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-server-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-server-procs.tcl 17 Oct 2004 05:51:54 -0000 1.1
@@ -0,0 +1,425 @@
+ad_library {
+ Tcl API for a SOAP Server.
+
+ Based on William Byrne's soap-gateway implementation.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+ @author Nick Carroll (ncarroll@ee.usyd.edu.au)
+ @creation-date 2004-09-24
+ @cvs-id $Id: soap-server-procs.tcl,v 1.1 2004/10/17 05:51:54 ncarroll Exp $
+}
+
+namespace eval soap::server {}
+
+ad_proc -public soap::server::get_version_namespace {
+ ver
+} {
+ Returns the namespace for the specified SOAP version.
+
+ @param ver A SOAP version, eg 1.1 or 1.2.
+ @return Returns the namespace associated with the specified
+ version of SOAP.
+} {
+
+ switch $ver {
+ 1.1 {
+ # Namespace for SOAP 1.1
+ return [parameter::get -parameter "SOAP_NS_1_1"]
+ }
+ 1.2 {
+ # Namespace for SOAP 1.2
+ return [parameter::get -parameter "SOAP_NS_1_2"]
+ }
+ }
+
+ # return 1.1 as safety
+ return [parameter::get -parameter "SOAP_NS_1_1"]
+}
+
+ad_proc -public soap::server::get_version_encoding {
+ ver
+} {
+ Returns the encoding for the specified SOAP version.
+
+ @param ver A SOAP version, eg 1.1 or 1.2.
+ @return Returns the encoding associated with the specified
+ version of SOAP.
+} {
+ switch $ver {
+ 1.1 {
+ return [parameter::get -parameter "SOAP_ENC_1_1"]
+ }
+ 1.2 {
+ return [parameter::get -parameter "SOAP_ENC_1_2"]
+ }
+ }
+
+ # return 1.1 as safety
+ return [parameter::get -parameter "SOAP_ENC_1_1"]
+}
+
+ad_proc -public soap::server::get_url_params {
+} {
+ @author William Byrne
+} {
+ # try to get from target url
+ set request [ns_conn request]
+
+ # search for ?
+ set offset [string first "?" $request]
+
+ # test
+ if { $offset >= 0 } {
+
+ # fixup offset
+ incr offset
+
+ # find first space after query
+ set last [string first " " $request $offset]
+
+ # fixup
+ if { $last < 0 } {
+ set last end
+ } else {
+ incr last -1
+ }
+
+ # get query
+ set query [string range $request $offset $last]
+
+ } else {
+ # clear
+ set query {}
+ }
+ # return params as ns_set
+ return [ns_parsequery $query]
+}
+
+ad_proc -public soap::server::get_url_param {
+ param
+} {
+ @author William Byrne
+} {
+ # get params
+ set params [soap::server::get_url_params]
+
+ # return requested
+ return [ns_set get $params $param]
+}
+
+ad_proc -public soap::server::has_permission {
+ {-user_id {}}
+ object_id
+ privilege
+} {
+ @param object_id
+ @param privilege
+} {
+ # test user
+ if { $user_id == {} } {
+ # set to current user
+ set user_id [ad_conn user_id]
+ }
+
+ # return permission cache
+ return [permission::permission_p -party_id $user_id \
+ -object_id $object_id -privilege $privilege]
+}
+
+ad_proc -public soap::server::require_permission {
+ object_id
+ privilege
+} {
+ @param object_id
+ @param privilege
+} {
+ # check permission cache
+ if { ![soap::server::has_permission $object_id $privilege] } {
+ # deny
+ return [soap::fault::generate_error "Unauthorized: Access Denied"]
+ }
+}
+
+ad_proc -public soap::server::invoke {
+ env
+} {
+ Take the SOAP request and invoke the method on the server.
+
+ @param env The SOAP envelope sent from the client.
+ @return result wrapped in a SOAP response envelope and returned
+ to the client.
+} {
+
+ # Invoke in safe block
+ if {[catch {set result [soap::server::do_invoke $env]} err_msg]} {
+ # build fault
+ set result [soap::fault::generate_fault $err_msg]
+ }
+
+ # return envelope
+ return $result
+}
+
+
+ad_proc -private soap::server::do_invoke {
+ env
+} {
+ Parses the specified SOAP envelope for methods, and invokes these
+ methods with the supplied arguments. The results (if any) are
+ returned to the invoking client as a SOAP response.
+
+ @param env The SOAP envelope to parse for methods to invoke.
+ @return Returns a SOAP response for the invoking client.
+} {
+ # force to v1.1
+ set ver 1.1
+
+ # set encoding style
+ set encoding [soap::server::get_version_encoding $ver]
+
+ # set envelope version
+ set version [soap::server::get_version_namespace $ver]
+
+ # parse incoming soap envelope
+ set doc [dom parse $env]
+
+ # LOG SOAP Request
+ ns_log Notice "\nSOAP Request:\n[$doc asXML]"
+
+ # get doc root
+ set root [$doc documentElement]
+
+ # get child nodes of Envelope
+ set children [$root childNodes]
+
+ # decl method for response
+ set method {}
+ set result {}
+
+ # Brute force envelope search is performed in place of
+ # preferred XPath search. I ran into issues that were complicated
+ # by the fact that XPath was not available on a
+ # baseline installation. The goal is to demonstrate SOAP interop
+ # and not necessarily write the ideal implementation. Furthermore,
+ # if the envelope exists within XML, it
+ # should be found quickly.
+
+ # decl mustUnderstand list
+ set misunderstood {}
+
+ set header [$root selectNodes /SOAP-ENV:Envelope/SOAP-ENV:Header]
+
+ # test for header
+ if ![empty_string_p $header] {
+
+ # get requisites
+ set reqs [$header childNodes]
+
+ # loop
+ foreach r $reqs {
+
+ # look for must understand
+ set mu [$r getAttribute mustUnderstand]
+
+ # test
+ if { $mu == "1" || [string equal -nocase $mu true] } {
+
+ # don't understand anything other than
+ # basics right now
+ # add to list - should be qnames with namespaces??
+ lappend misunderstood [list $r {}]
+ }
+ }
+ }
+
+ set body [$root selectNodes /SOAP-ENV:Envelope/SOAP-ENV:Body]
+
+ # test for body
+ if ![empty_string_p $body] {
+
+ # before proceeding, make sure "misunderstood" var is clear
+ if { $misunderstood != {} } {
+
+ # return misunderstood fault
+ return [soap::fault::generate_misunderstood $misunderstood]
+
+ }
+
+ # get methods
+ set methods [$body childNodes]
+
+ # loop
+ foreach m $methods {
+
+ # get node type
+ set type [$m nodeType]
+
+ # test for element - skip cdata (axis)
+ if { [string equal -nocase $type "cdata_section"] } {
+ # skip
+ continue
+ }
+
+ # get method namespace
+ set service {};
+
+ # verify
+ if { $service == {} } {
+ # parse connection url and see if it's there
+ set service [soap::server::get_url_param service]
+ }
+
+ # get service/namespace id
+ set nid [soap::server::namespace_get_id $service]
+
+ # verify
+ if { $nid < 0 } {
+ # not found
+ return [soap::fault::generate_error "Error: $namespace not found"]
+ }
+
+ # get method
+ set method [$m nodeName]
+
+ # authenticate
+
+ # get method id and proc
+ set id_proc [soap::server::method_get_id_and_proc $nid $method]
+
+ # get id
+ set mid [lindex $id_proc 0]
+
+ # get proc
+ set proc [lindex $id_proc 1]
+
+ # verify
+ if { $mid < 0 } {
+ # throw
+ set error_msg [format "Invalid service method: '%s:%s'" \
+ $service $method]
+ return [soap::fault::generate_error "Error: $error_msg"]
+ }
+
+### Get this working!
+ # try authenticating to method
+#### soap::server::require_permission $mid [soap::server::get_invoke_permission_moniker]
+
+ # build namespace into expr
+ set expr "sg::"
+
+ # append namespace and proc
+ append expr $service :: $proc
+
+ # get args
+ set args [$m childNodes]
+
+ # loop
+ foreach a $args {
+ # get node type
+ set text_node [$a firstChild]
+ lappend expr [$text_node nodeValue]
+ }
+
+ # invoke - error will be caught by
+ # caller and returned as fault
+ set result [eval $expr]
+
+ # done
+ break
+ }
+ }
+
+ return [soap::server::response $version $encoding $method $result]
+}
+
+ad_proc -private soap::server::response {
+ version
+ encoding
+ method
+ result
+} {
+ Constructs a SOAP response based on the specified result and method.
+
+ @param version The version of SOAP.
+ @param encoding The encoding used for the version of SOAP specified.
+ @param method Method name.
+ @param result Result to return to the SOAP client.
+ @return Returns a SOAP response envelope.
+} {
+ # construct xml doc object
+ set doc [dom createDocument env:Envelope]
+
+ # create root node: "env:Envelope"
+ set env [$doc documentElement]
+
+ # define namespace atts into node
+ $env setAttribute xmlns:env $version
+
+ # define encoding style atts into node
+ $env setAttribute env:encodingStyle $encoding
+
+ # create SOAP header - "env:Envelope/env:Header"
+ set header [$env appendChild [$doc createElement env:Header]]
+
+ # create SOAP body - "env:Envelope/env:Body"
+ set body [$env appendChild [$doc createElement env:Body]]
+
+ # create method node - "env:Envelope/env:Body/?method?"
+ set method_node [$body appendChild [$doc createElement [format "m:%s%s" $method Response]]]
+
+ # define namespace atts into node
+ $method_node setAttribute xmlns:m {http://namespace}; # need real namespace
+
+ # create args node - "env:Envelope/env:Body/?method?/?arg?"
+ set result_node [$method_node appendChild [$doc createElement Result]]
+ set args [$result_node appendChild [$doc createTextNode $result]]
+
+ # LOG SOAP Response
+ ns_log Notice "\nSOAP Response:\n[$doc asXML]"
+
+ # render xml into result string
+ return [$doc asXML]
+}
+
+ad_proc -public soap::server::namespace_get_id {
+ service
+} {
+ @param service The service used to query the namespace id for.
+ @return Returns the namespace id for the given service.
+} {
+ return [db_string namespace_id {} -default -1 ]
+}
+
+ad_proc -public soap::server::method_get_id_and_proc {
+ namespace_id
+ method
+} {
+ @param namespace_id
+ @param method
+ @return Returns the method ID and proc name for the given namespace ID.
+} {
+ return [db_string method_id_proc {} -default {-1 {}}]
+}
+
+ad_proc -private soap::server::get_invoke_permission_moniker {
+} {
+ @author William Byrne
+} {
+ # short cut
+ return "invoke"
+
+ # eval global within sg namespace
+ namespace eval sg {
+ # decl moniker
+ variable invoke_moniker
+
+ # test for moniker
+ if { ![info exists invoke_moniker] } {
+ # get it
+ set invoke_moniker [db_string select_moniker {}]
+ }
+
+ # return it
+ return $invoke_moniker
+ }
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs-postgresql.xql 17 Oct 2004 05:51:54 -0000 1.1
@@ -0,0 +1,48 @@
+
+
+
+ postgresql7.1
+
+
+
+ select idl
+ from sg_methods
+ where namespace_id = :namespace_id
+ order by method_id
+
+
+
+
+
+ select notes
+ from sg_methods
+ where method_id = :method_id
+
+
+
+
+
+ select method_id
+ from sg_methods
+ where namespace_id = :namespace_id and
+ lower(method) = lower(:method)
+
+
+
+
+
+ select method_id
+ from sg_methods
+ where namespace_id = :namespace_id and proc = :method
+
+
+
+
+
+ select notes
+ from sg_namespaces
+ where namespace_id = :namespace_id
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/tcl/soap-wsdl-procs.tcl 17 Oct 2004 05:51:54 -0000 1.1
@@ -0,0 +1,639 @@
+ad_library {
+ Tcl API for generating WSDLs.
+
+ Based on William Byrne's soap-gateway implementation.
+
+ @author William Byrne (WilliamB@ByrneLitho.com)
+ @author Nick Carroll (ncarroll@ee.usyd.edu.au)
+ @creation-date 2004-09-24
+ @cvs-id $Id: soap-wsdl-procs.tcl,v 1.1 2004/10/17 05:51:54 ncarroll Exp $
+}
+
+
+namespace eval soap::wsdl {}
+
+
+ad_proc -private soap::wsdl::build_wsdl_url {
+ service
+} {
+ @param service
+} {
+
+ # normal
+ set location [ns_conn location]
+
+ # build wsdl url
+ set wsdl [file join [ad_conn object_url] wsdl]
+
+ # return format
+ return [format "%s%s?service=%s" $location $wsdl $service]
+}
+
+
+ad_proc -private soap::wsdl::method_get_idls {
+ namespace_id
+} {
+ @author William Byrne
+} {
+ # init
+ set methods [list]
+
+ # loop through methods belonging to namespace ??? XQL
+ db_foreach select_idls {} {
+ # append method idl
+ lappend methods $idl
+ }
+
+ # return methods
+ return $methods
+}
+
+
+ad_proc -private soap::wsdl::get_style_parser_expr {
+ {-argpart 0}
+ {style "C"}
+} {
+ @author William Byrne
+} {
+ # switch
+ switch $style {
+ C {
+ # test for arg expression
+ if $argpart {
+
+ #return {(.+)(\w+) *$}
+ return {(\w+\W+)(\w+)}
+
+ } else {
+
+ return {^ *([^ ]+) +([a-zA-Z][a-zA-Z0-9_]*) *\(([^)]*)}
+ }
+ }
+ default {
+ # throw
+ soap::fault::raise "Unsupported IDL parse style: $style"
+ }
+ }
+}
+
+
+ad_proc -public soap::wsdl::method_get_notes {
+ method_id
+} {
+ @author William Byrne
+} {
+ return [db_string select_notes {} -default -1 ]
+}
+
+
+ad_proc -public soap::wsdl::method_get_id {
+ {-proc 0}
+ namespace_id
+ method
+} {
+ @author William Byrne
+} {
+ # test for 'proc' clause
+ if [soap::server::lib::true $proc] {
+ set id [db_string method_get_id_with_proc {} -default -1 ]
+ } else {
+ set id [db_string method_get_id {} -default -1 ]
+ }
+
+ # return
+ return $id
+}
+
+
+ad_proc -private soap::wsdl::build_namespace_uri {
+ service
+} {
+ @author William Byrne
+} {
+ # basic uri
+ return "http://$service.openacs.org/message/"
+}
+
+
+ad_proc -public soap::wsdl::namespace_get_notes {
+ namespace_id
+} {
+ @param namespace_id
+} {
+ return [db_string select_notes {} -default -1 ]
+}
+
+
+ad_proc -private soap::wsdl::map_ctype_to_xtype {
+ type
+} {
+ @param type
+} {
+
+ # strip whitespace
+ regsub -all { } $type {} typ
+
+ # map type
+ switch $typ {
+
+ char -
+ wchar_t {
+ # simple character type
+ return [list xsd:string]
+ }
+
+ int -
+ long {
+ # simpl int
+ return [list xsd:int]
+ }
+
+ float -
+ double {
+ # simple floating point
+ return [list xsd:double]
+ }
+
+ __int64 {
+ # simple long long
+ return [list xsd:long]
+ }
+
+ char[] -
+ wchar_t[] -
+ string -
+ wstring {
+ # string (keep simple)
+ return [list xsd:string]
+ }
+
+ int[] -
+ long[] {
+ # array of ints
+ return [list xsd:int *]
+ }
+
+ float[] -
+ double[] {
+ # array of floating point
+ return [list xsd:double *]
+ }
+
+ __int64[] {
+ # array long long
+ return [list xsd:long *]
+ }
+
+ void {
+ # void type
+ return [list]
+ }
+ }
+
+ # not supported
+ soap::fault::unsupported "unable to map $type to xml type - '$type' refined to '$typ'"
+}
+
+
+ad_proc -private soap::wsdl::build_endpoint {
+ service
+ {trace {}}
+} {
+ @param service
+ @param trace
+} {
+ # test for trace
+ if { $trace != {} } {
+ # use trace info specified in call
+ set location $trace
+ } else {
+ # normal
+ set location [ns_conn location]
+ }
+
+ # build action url
+ set action [file join [ad_conn object_url] action]
+
+ # return format
+ return [format "%s%s?service=%s" $location $action $service]
+}
+
+
+ad_proc -private soap::wsdl::do_generate_wsdl {
+ namespace
+ documentation
+ oneway
+ trace
+} {
+ @author William Byrne
+} {
+
+ # get namespace id
+ set nid [soap::server::namespace_get_id $namespace]
+
+ # verify
+ if { $nid < 0 } {
+
+ # not found
+ soap::fault::raise "service '$namespace' not found" 404
+
+ }
+
+ # fixup documentation boolean
+ set documentation [soap::server::lib::true $documentation]
+
+ # authenticate
+ # ??? soap::server::require_permission $nid read
+
+ # force to v1.1
+ set ver 1.1
+
+ # set encoding style
+ set encoding [soap::server::get_version_encoding $ver]
+
+ # get methods for namespace
+ set funcs [soap::wsdl::method_get_idls $nid]
+
+ # decl methods
+ set methods [list]
+
+ # set up regexp expression for "C" style function
+ set expr [soap::wsdl::get_style_parser_expr C]
+ #set expr {^ *([^ ]+) +([a-zA-Z0-9_]+) *\(([^)]*)}
+
+ # loop through functions
+ foreach func $funcs {
+
+ # invoke regexp
+ regexp $expr $func {} type method argz
+
+ # add func to methods list0
+ lappend methods $method
+
+ # store funcs
+ set method_funcs($method) $argz
+
+ # store func type
+ set method_types($method) $type
+
+ # store args
+ set method_args($method) [split $argz ,]
+
+ # get notes
+ if $documentation {
+ set method_notes($method) [soap::wsdl::method_get_notes \
+ [soap::wsdl::method_get_id $nid $method]]
+ }
+ }
+
+ # construct wsdl doc object
+ set doc [dom createDocument definitions]
+
+ # create root WSDL node: "definitions"
+ set defs [$doc documentElement]
+
+ # build namespace uri for methods
+ set nsuri [soap::wsdl::build_namespace_uri $namespace]
+
+ # define namespace atts into "definitions" node
+ $defs setAttribute name $namespace
+ $defs setAttribute targetNamespace "http://$namespace.openacs.org/wsdl/"
+ $defs setAttribute xmlns:wsdlns "http://$namespace.openacs.org/wsdl/"
+ $defs setAttribute xmlns:typens "http://$namespace.openacs.org/type"
+ $defs setAttribute xmlns:soap "http://schemas.xmlsoap.org/wsdl/soap/"
+ $defs setAttribute xmlns:xsd "http://www.w3.org/2001/XMLSchema"
+ $defs setAttribute xmlns "http://schemas.xmlsoap.org/wsdl/"
+
+ # add documentation
+ if $documentation {
+ # get notes for namespace
+ set notes [soap::wsdl::namespace_get_notes $nid]
+
+ # create child "definitions/documentation" node (allow empty notes)
+ set doc_node [$defs appendChild [$doc createElement documentation]]
+ set docu [$doc_node appendChild [$doc createTextNode $notes]]
+ }
+
+ # create child "definitions/types" node
+ set types [$defs appendChild [$doc createElement types]]
+
+ # create child "definitions/types/schema" node
+ set schema [$types appendChild [$doc createElement schema]]
+
+ # define namespace atts into "definitions/types/schema" node
+ $schema setAttribute targetNamespace "http://$namespace.openacs.org/type"
+ $schema setAttribute xmlns "http://www.w3.org/2001/XMLSchema"
+ $schema setAttribute xmlns:enc $encoding
+ $schema setAttribute xmlns:wsdl "http://schemas.xmlsoap.org/wsdl/"
+ $schema setAttribute elementFormDefault "qualified"
+
+ # loop through decomposed methods
+ foreach m $methods {
+
+ # get args
+ set argz $method_args($m)
+
+ # create "definitions/message" node
+ set message [$defs appendChild [$doc createElement message]]
+
+ # add name attr
+ $message setAttribute name "$namespace.$m"
+
+ # add documentation
+ if $documentation {
+
+ # create child "definitions/message/documentation" node
+ # (allow empty notes)
+ set doc_node [$message appendChild [$doc createElement documentation]]
+ set docu [$doc_node appendChild [$doc createTextNode $method_notes($m)]]
+ }
+
+ # decl param order arg
+ set order ""
+
+ # get arg part parser expr
+ set expr [soap::wsdl::get_style_parser_expr -argpart 1 C]
+
+ # loop through args
+ foreach a $argz {
+
+ # split arg type from its name
+ if ![regexp $expr $a {} typ nam] {
+
+ # format problem
+ error "unexpected argument format: '$a' in '$argz', '$m', '$method_args($m)'"
+
+ }
+
+ # add arg to param order var
+ lappend order $nam
+
+ # map type
+ set xtype [soap::wsdl::map_ctype_to_xtype $typ]
+
+ # get component count
+ set cnt [llength $xtype]
+
+ # test for simple
+ if { $cnt == 1 } {
+
+ # create arg parts
+ set part [$message appendChild [$doc createElement part]]
+
+ # add name attr
+ $part setAttribute name $nam
+
+ # add type attr
+ $part setAttribute type [lindex $xtype 0]
+
+ } else {
+
+ # not yet supported
+ soap::fault::unsupported "cannot spec non simple types: $a, $xtype"
+ }
+ }
+
+ # reset method_args to hold param order
+ set method_args($m) $order
+
+ # build return message
+ set typ $method_types($m)
+
+ # map type
+ set xtype [soap::wsdl::map_ctype_to_xtype $typ]
+
+ # get component count
+ set cnt [llength $xtype]
+
+ # test for void
+ if { $cnt != 0} {
+
+ # set boolean into method type for Respond in portType wsdl node
+ set method_types($m) 1
+
+ # create response message
+ set message [$defs appendChild [$doc createElement message]]
+
+ # add name attr
+ $message setAttribute name [format "$namespace.$m%s" Response]
+
+ # test for simple
+ if { $cnt == 1 } {
+
+ # create arg parts
+ set part [$message appendChild [$doc createElement part]]
+
+ # add name attr
+ $part setAttribute name Result
+
+ # add type attr
+ $part setAttribute type [lindex $xtype 0]
+
+ } else {
+ # not yet supported
+ soap::fault::unsupported "cannot spec non simple types: $typ"
+ }
+
+ } elseif { $oneway } {
+ # set false boolean into method type eliminating
+ # Respond in portType wsdl node
+ set method_types($m) 0
+ } else {
+ # set true boolean into method type forcing
+ # void Respond in portType wsdl node
+ set method_types($m) 1
+
+ # create response message
+ set message [$defs appendChild [$doc createElement message]]
+
+ # add name attr
+ $message setAttribute name [format "$namespace.$m%s" Response]
+
+ # force string result type
+ if { 1 } {
+
+ # create arg parts
+ set part [$message appendChild [$doc createElement part]]
+
+ # add name attr
+ $part setAttribute name Result
+
+ # add type attr
+ $part setAttribute type {xsd:string}
+ }
+ }
+ }
+
+ # create portType "definitions/portType" node
+ set portType [$defs appendChild [$doc createElement portType]]
+
+ # set its name
+ $portType setAttribute name [format "%s%s" $namespace SoapPort]
+
+ # create operations for each function
+ foreach m $methods {
+
+ # create new operation
+ set operation [$portType appendChild [$doc createElement operation]]
+
+ # set its name
+ $operation setAttribute name $m
+
+ # set parameter order
+ $operation setAttribute parameterOrder $method_args($m)
+
+ # create input op
+ set input [$operation appendChild [$doc createElement input]]
+
+ # bind to message node
+ $input setAttribute message [format "wsdlns:%s.%s" $namespace $m]
+
+ # test for non void function (false if void)
+ if $method_types($m) {
+
+ # create output op
+ set output [$operation appendChild [$doc createElement output]]
+
+ # bind to message node
+ $output setAttribute message [format "wsdlns:%s.%s%s" $namespace $m Response]
+ }
+ }
+
+ # setup RPC bindings, encodings, and namespaces
+
+ # create binding node - "definitions/binding"
+ set binding [$defs appendChild [$doc createElement binding]]
+
+ # set its name
+ $binding setAttribute name [format "%s%s" $namespace SoapBinding]
+
+ # set its type
+ $binding setAttribute type [format "wsdlns:%s%s" $namespace SoapPort]
+
+ # create child soap binding node
+ set soap_binding [$binding appendChild [$doc createElement soap:binding]]
+
+ # set rpc style
+ $soap_binding setAttribute style rpc
+
+ # set transport
+ $soap_binding setAttribute transport {http://schemas.xmlsoap.org/soap/http}
+
+ # loop through methods
+ foreach m $methods {
+
+ # create input child - "definitions/binding/operation"
+ set operation [$binding appendChild [$doc createElement operation]]
+
+ # set its name
+ $operation setAttribute name $m
+
+ # create child soap operation node
+ # definitions/binding/operation/soap:operation
+ set soap_operation [$operation appendChild [$doc createElement soap:operation]]
+
+ # set soap action
+ $soap_operation setAttribute soapAction [format "http://%s.openacs.org/action/%s.%s" $namespace $namespace $m]
+
+ # create child input - "definitions/binding/operation/input"
+ set input [$operation appendChild [$doc createElement input]]
+
+ # create child soap_body node
+ # definitions/binding/operation/input/soap:body
+ set soap_body [$input appendChild [$doc createElement soap:body]]
+
+ # set 'use' attr
+ $soap_body setAttribute use encoded
+
+ # set namespace
+ $soap_body setAttribute namespace $nsuri
+
+ # set encoding
+ $soap_body setAttribute encodingStyle $encoding
+
+ # test for output
+ if $method_types($m) {
+
+ # create child output - "definitions/binding/operation/output"
+ set output [$operation appendChild [$doc createElement output]]
+
+ # create child soap_body node
+ # definitions/binding/operation/output/soap:body
+ set soap_body [$output appendChild [$doc createElement soap:body]]
+
+ # set 'use' attr
+ $soap_body setAttribute use encoded
+
+ # set namespace
+ $soap_body setAttribute namespace "http://$namespace.openacs.org/message/"
+
+ # set encoding
+ $soap_body setAttribute encodingStyle $encoding
+ }
+ }
+
+ # create service
+
+ # create service node - "definitions/service"
+ set service [$defs appendChild [$doc createElement service]]
+
+ # set its name
+ $service setAttribute name $namespace
+
+ # create child port - "definitions/service/port"
+ set port [$service appendChild [$doc createElement port]]
+
+ # set its name
+ $port setAttribute name [format "%s%s" $namespace SoapPort]
+
+ # set its binding
+ $port setAttribute binding [format "wsdlns:%s%s" $namespace SoapBinding]
+
+ # create child address - "definitions/service/port/soap:address"
+ set soap_address [$port appendChild [$doc createElement soap:address]]
+
+ # set its location
+ $soap_address setAttribute location [soap::wsdl::build_endpoint $namespace $trace]
+
+ # render xml into string
+ return [$doc asXML]
+
+}
+
+
+ad_proc -public soap::wsdl::generate_wsdl {
+ {-documentation 1}
+ namespace
+ {oneway 1}
+ {trace {}}
+} {
+ @author William Byrne
+} {
+ # fixup and set missing to true
+ if { $oneway == {} } { set oneway 1 }
+
+ # try
+ if { [catch {
+
+ # delegate to do_generate
+ set wsdl [soap::wsdl::do_generate_wsdl $namespace $documentation $oneway $trace]
+
+ } msg] } {
+
+ # get error code
+ global errorCode
+ set code $errorCode
+
+ # normalize error code
+ if { ![string is integer $code] } { set code 500 }
+
+ # error
+ global errorInfo
+ ns_returnerror $code "$msg\n$errorInfo
"
+
+ } else {
+
+ # return wsdl
+ return $wsdl
+ }
+}
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/action.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/action.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/action.tcl 17 Oct 2004 05:51:55 -0000 1.1
@@ -0,0 +1,78 @@
+# /packages/soap-gateway/www/action.tcl
+
+# page contract not included due to cost of parsing payload - (not necessary)
+
+# generate temp file name
+set tmp [ns_tmpnam]
+
+# open it
+set f [open $tmp w+]
+
+# perform file ops in safe block to ensure tmp file unlink
+# (yes, this is a back asswards approach)
+set err [catch {
+
+ # dump payload to file - there's gotta be a better way to get the content
+ ns_conncptofp $f
+
+ # get file size
+ set size [tell $f]
+
+ # limit incoming envelope size to 1/4 meg
+ if { $size > 262144 || $size < 0 } {
+
+ # throw it
+ error "payload too large"
+
+ }
+
+ # seek to beginning
+ seek $f 0
+
+ # read file contents into SOAP envelope var
+ set env [read $f $size]
+
+} msg]
+
+# test for error
+if { $err != 0 } {
+
+ # make em' wait
+ ns_sleep 5
+
+ # prep
+ set savedInfo {}
+
+ # advise
+ global errorInfo
+
+ # test
+ if { [info exists errorInfo] != 0 } {
+
+ # preserve error info
+ set savedInfo $errorInfo
+
+ }
+
+ # release file
+ catch { close $f }
+
+ # unlink file
+ ns_unlink $tmp
+
+ # throw
+ error "$msg\nfile: $tmp" $savedInfo
+
+} else {
+
+ # release file
+ catch { close $f }
+
+ # unlink file
+ ns_unlink $tmp
+
+
+}
+
+# invoke envelope using lib functions and return
+ns_return 200 text/xml [soap::server::invoke $env]
Index: openacs-4/packages/soap-gateway/www/debug.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/debug.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/debug.adp 17 Oct 2004 05:51:55 -0000 1.1
@@ -0,0 +1,4 @@
+
+
+
+@result@
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/debug.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/debug.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/debug.tcl 17 Oct 2004 05:51:55 -0000 1.1
@@ -0,0 +1,37 @@
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: debug.tcl,v 1.1 2004/10/17 05:51:55 ncarroll Exp $
+} {
+ {expr {}}
+}
+
+template::form create debug_form
+
+# build service input field
+template::element create debug_form expr \
+ -widget textarea \
+ -datatype text \
+ -label "expr" \
+ -html { rows 8 cols 80 wrap off } \
+ -value $expr
+
+# test for valid form
+if [template::form is_valid debug_form] {
+
+ if [catch {
+ set result [uplevel $expr]
+ } msg] {
+ set result $msg
+ }
+
+} else {
+
+ set result {}
+
+}
+
+ad_return_template
+
+
Index: openacs-4/packages/soap-gateway/www/index-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/index-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/index-postgresql.xql 17 Oct 2004 05:51:55 -0000 1.1
@@ -0,0 +1,11 @@
+
+
+
+ postgresql7.1
+
+
+
+ select namespace_id, service, uri, notes from sg_namespaces
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/index.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/index.adp 17 Oct 2004 05:51:55 -0000 1.1
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+There are no namespaces
+
+
+
+
+
+
+
+
+
Index: openacs-4/packages/soap-gateway/www/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/index.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/index.tcl 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,61 @@
+# packages/soap-gateway/www/index.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: index.tcl,v 1.1 2004/10/17 05:51:56 ncarroll Exp $
+} {
+}
+
+# clear title
+set title {}
+
+# installed correctly
+if [catch {
+
+ soap::server::lib::true 1
+
+}] {
+
+ # report as installation error
+ error "Failure while calling soap-gateway function!\nDid you restart the server after installing soap-gateway package?\n\n"
+
+}
+
+# get package id
+set package_id [ad_conn package_id]
+
+# require read permission
+ad_require_permission $package_id read
+
+# query namespaces
+db_multirow -extend {endpoint edit delete wsdl} namespaces namespace_list {} {
+ set endpoint [soap::wsdl::build_endpoint $service]
+ set edit "edit-namespace?namespace_id=$namespace_id"
+ set delete "delete-namespace?namespace_id=$namespace_id"
+ set wsdl [soap::wsdl::build_wsdl_url $service]
+}
+
+# create form
+template::form create new_namespace_form
+
+# change action attribute for form - not documented
+set new_namespace_form:properties(action) edit-namespace
+
+# create form
+template::form create init_workspace_form
+
+# change action attribute for form - not documented
+set init_workspace_form:properties(action) init-workspace
+
+# create form
+template::form create init_interop_form
+
+# change action attribute for form - not documented
+set init_interop_form:properties(action) init-interop
+
+# update caption
+set caption "services"
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/master.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/master.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/master.adp 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,91 @@
+
+@title@
+
+ @context@
+
+@context_bar@
+
+@header_stuff@
+
+
+
+
+
Index: openacs-4/packages/soap-gateway/www/master.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/master.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/master.tcl 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,18 @@
+# Expects "title" and "header" and "context_bar"
+
+if { ![info exists context_bar] } {
+ set context_bar {}
+}
+
+if ![info exists header_stuff] {
+ set header_stuff {}
+}
+
+if ![info exists title] {
+
+ # clear
+ set title {}
+
+}
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/toolbar.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/toolbar.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/toolbar.adp 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,22 @@
+
+
+
+
Index: openacs-4/packages/soap-gateway/www/toolbar.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/toolbar.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/toolbar.tcl 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,85 @@
+# /packages/soap-gateway/www/toolbar.tcl
+
+# layout inspired by bug-tracker
+
+# safety
+if ![info exists caption] {
+
+ # clear
+ set caption {}
+}
+
+# clear for tools
+set tools []
+
+# add standard tools
+set defaults [list help services tests]
+
+# package id
+set pid [soap::package_id -throw f]
+
+# verify
+if { $pid == 0 } {
+
+ # must be just starting out - clear everything
+ set defaults [list]
+
+# test for admin user
+} elseif { [soap::server::has_permission $pid admin] != 0 } {
+
+ # add em'
+ lappend defaults admin permissions
+
+}
+
+# update tools list
+foreach default $defaults {
+
+ # test current list and skip if caption
+ # ??? if $default equal to caption, then assume $default tool page is current
+ if { [lsearch $tools $default] < 0 && ![string equal -nocase $default $caption] } {
+
+ # add
+ lappend tools $default
+ }
+}
+
+# get href base
+set base [soap::get_base_url]
+
+# create multirow
+multirow create toolbar symbol url
+
+# loop through list
+foreach tool $tools {
+
+ # switch
+ case $tool {
+ help {
+ # add
+ multirow append toolbar help [file join $base doc]
+ }
+ services {
+ # add
+ multirow append toolbar services [file join $base ]
+ }
+ admin {
+ # add
+ multirow append toolbar admin [file join $base admin ]
+ }
+ tests {
+ # add
+ multirow append toolbar tests [file join $base tests ]
+ }
+ permissions {
+ # set href
+ set url "/permissions/one?object_id=$pid"
+
+ # add
+ multirow append toolbar permissions $url
+
+ }
+ }
+}
+
+ad_template_return
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/top.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/top.gif,v
diff -u
Binary files differ
Index: openacs-4/packages/soap-gateway/www/wsdl.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/wsdl.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/wsdl.tcl 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,19 @@
+# packages/soap-gateway/www/wsdl.tcl
+
+# clear title
+set title {}
+
+# get params from url
+set params [soap::server::get_url_params]
+
+# get interested params
+set service [ns_set get $params service]
+set oneway [ns_set get $params oneway]
+set trace [ns_set get $params trace]
+set docs [ns_set get $params documentation]
+if ![string length $docs] { set docs 1 }
+
+# render xml and return
+ns_return 200 text/xml [soap::wsdl::generate_wsdl -documentation $docs $service $oneway $trace]
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/delete-method-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-method-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-method-postgresql.xql 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,13 @@
+
+
+
+ postgresql7.1
+
+
+
+ select method, idl, idl_style, notes
+ from sg_methods
+ where method_id = :method_id
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/delete-method.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-method.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-method.adp 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,6 @@
+
+
+
+
+Delete the following method: @method@
+
Index: openacs-4/packages/soap-gateway/www/admin/delete-method.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-method.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-method.tcl 17 Oct 2004 05:51:56 -0000 1.1
@@ -0,0 +1,55 @@
+# packages/soap-gateway/www/admin/method-namespace.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: delete-method.tcl,v 1.1 2004/10/17 05:51:56 ncarroll Exp $
+} {
+ namespace_id:integer,notnull
+ method_id:integer,notnull
+}
+
+# clear title
+set title {}
+
+# get package
+set package_id [ad_conn package_id]
+
+# verify namespace id
+soap::method_check $method_id
+
+# require write permission
+ad_require_permission $method_id admin; #write
+
+# set session context
+set context [list "Administration"]
+
+# create form
+template::form create method_form
+
+# store namespace_id into hidden form element
+template::element create method_form namespace_id \
+ -widget hidden \
+ -datatype text \
+ -value $namespace_id
+
+# store method_id into hidden form element
+template::element create method_form method_id \
+ -widget hidden \
+ -datatype text \
+ -value $method_id
+
+# query for method attributes
+db_1row select_method {}
+
+# test for valid form
+if [template::form is_valid method_form] {
+
+ # update existing
+ soap::method_delete $method_id
+
+ ad_returnredirect "./edit-namespace?namespace_id=$namespace_id"
+}
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/admin/delete-namespace-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-namespace-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-namespace-postgresql.xql 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,13 @@
+
+
+
+ postgresql7.1
+
+
+
+ select service, uri, notes
+ from sg_namespaces
+ where namespace_id = :namespace_id
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/delete-namespace.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-namespace.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-namespace.adp 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,5 @@
+
+
+
+Delete the following service: @service@
+
Index: openacs-4/packages/soap-gateway/www/admin/delete-namespace.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/delete-namespace.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/delete-namespace.tcl 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,48 @@
+# packages/soap-gateway/www/admin/delete-namespace.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: delete-namespace.tcl,v 1.1 2004/10/17 05:51:57 ncarroll Exp $
+} {
+ namespace_id:integer,notnull
+}
+
+# clear title
+set title {}
+
+# get package
+set package_id [ad_conn package_id]
+
+# verify namespace id
+soap::namespace_check $namespace_id
+
+# require admin permission
+ad_require_permission $namespace_id admin; #write
+
+# set session context to delete mode
+set context [list "Administration"]
+
+# create form
+template::form create namespace_form
+
+# store namespace_id into hidden form element
+template::element create namespace_form namespace_id \
+ -widget hidden \
+ -datatype text \
+ -value $namespace_id
+
+# query for namespace attributes
+db_1row namespace_select {}
+
+# test for valid form
+if [template::form is_valid namespace_form] {
+
+ # update existing
+ soap::namespace_delete $namespace_id
+
+ ad_returnredirect "./"
+}
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/admin/edit-namespace-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/edit-namespace-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/edit-namespace-postgresql.xql 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,29 @@
+
+
+
+ postgresql7.1
+
+
+
+ select service, uri, notes
+ from sg_namespaces
+ where namespace_id = :namespace_id
+
+
+
+
+
+ select method_id, namespace_id, method, idl, idl_style, proc, notes
+ from sg_methods
+ where namespace_id = :namespace_id
+
+
+
+
+
+ select method, idl, idl_style, proc, notes
+ from sg_methods
+ where method_id = :method_id
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/edit-namespace.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/edit-namespace.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/edit-namespace.adp 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,143 @@
+
+
+@focus@
+
+
+
+
+Methods
+
+
+
+
+Error Descriptions
+
+
+ Not Published |
+ A public Tcl proc within the
+ @namespace@
+ namespace exists that is not published . Selecting import will
+ add the procedure to the WSDL database. The proc will then be available
+ for public access using the name specified within ad_proc's
+ @idl
+ parameter. If the @idl parameter is missing, the proc's symbolic name will be used instead.
+ |
+
+
+ Duplicate IDL |
+ The soap-gateway's diff algorithm detected a potential duplicate
+ method name. The calculated IDL name already exists within the WSDL
+ database for the @namespace@ namespace. Or, the IDL name for the Tcl proc was
+ detected within the list of sibling procs not yet published to the WSDL database.
+ In either case, the Tcl proc cannot be published
+ until it's IDL name is made unique within the
+ @namespace@
+ namespace.
+ |
+
+
+ Orphan |
+ A published method exists within the WSDL database that has no corresponding
+ public Tcl proc in the
+ @namespace@
+ namespace. Either delete the entry or supply a public Tcl proc.
+
+ |
+
+
+ Arguments |
+ A discrepency exists between the arguments of the Tcl proc and the published method in the
+ WSDL database. Comparisons are made to the argument names only. No type checking is performed.
+
+ |
+
+
+
+There are no methods!
+
+@diffdata@
Index: openacs-4/packages/soap-gateway/www/admin/edit-namespace.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/edit-namespace.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/edit-namespace.tcl 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,492 @@
+# packages/soap-gateway/www/admin/edit-namespace.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: edit-namespace.tcl,v 1.1 2004/10/17 05:51:57 ncarroll Exp $
+} {
+ namespace_id:integer,notnull,optional
+ {service ""}
+ {notes:html ""}
+ method_id:integer,notnull,optional
+ {idl ""}
+ {proc ""}
+ {method_notes:html ""}
+ {import 0}
+} -properties {
+ focus
+}
+
+# test for import
+if [soap::server::lib::true $import] {
+
+ # test for single method import
+ if { $proc != {} } {
+
+ # perform single import
+ set nid [soap::server::lib::import_service \
+ -proc $proc $service]
+
+ } else {
+
+ # perform full import
+ set nid [soap::server::lib::import_service $service]
+
+ # return to admin page
+ ad_returnredirect .
+
+ }
+
+ # verify args
+ if { [info exists namespace_id] != 0 && $nid != $namespace_id } {
+
+ # egats
+ soap::fault::raise "Namespace id mismatch during import"
+
+ } else {
+
+ # set id
+ set namespace_id $nid
+
+ }
+
+}
+
+# clear error
+set error {}
+
+# clear focus
+set focus {}
+
+# init debug var
+set diffdata {}
+
+# get idl help
+set idl_help [soap::get_idl_help]
+
+# get package
+set package_id [ad_conn package_id]
+
+# check to see if namespace_id is assigned
+if {[info exists namespace_id]} {
+
+ # verify namespace id
+ soap::namespace_check $namespace_id
+
+ # require write permission
+ ad_require_permission $namespace_id admin; #write
+
+ # set session context to edit mode
+ set context [list "Edit Namespace"]
+
+} else {
+
+ # require write permission for new namespace
+ ad_require_permission $package_id admin; #create
+
+ # set session context to creation mode
+ set context [list "New Namespace"]
+
+}
+
+# create form
+template::form create namespace_form
+
+# test for namespace_id assigment
+if {[info exists namespace_id]} {
+
+ # set editing
+ set editing_namespace 1
+
+} else {
+
+ # creating
+ set editing_namespace 0
+
+}
+
+# build service input field
+template::element create namespace_form service \
+ -datatype text \
+ -label "Service" \
+ -html { size 32 } \
+ -value {}; #$service
+
+# build notes input field
+template::element create namespace_form notes \
+ -widget textarea \
+ -datatype text \
+ -label "Notes" \
+ -html { rows 8 cols 80 wrap off } \
+ -value {}; #$notes
+
+# test for valid form
+if [template::form is_valid namespace_form] {
+
+ # clear method_id to disable method logic below
+ if [info exists method_id] { unset method_id }
+
+ # clean up service
+ set service [string trim $service]
+
+ # try
+ set err [catch {
+
+ # verify
+ soap::check_symbol $service
+
+ } error]
+
+ # verify
+ if { $err } {
+
+ # do nothing
+
+ } else {
+
+ # get session values
+ set user_id [ad_conn user_id]
+ set peeraddr [ad_conn peeraddr]
+
+ # force uri to xxxx.openacs.org
+ set uri "http://$service.openacs.org/methods"
+
+ # look for id of named method
+ set nid [soap::server::namespace_get_id $service]
+
+ # verify
+ if { $nid > 0 && (![info exists namespace_id] || $nid != $namespace_id) } {
+
+ # egats
+ soap::fault::raise "Duplicate service: $service"
+ }
+
+ # test for assigned namespace id
+ if [info exists namespace_id] {
+
+ # update existing
+ soap::server::lib::namespace_update $namespace_id \
+ $service $uri $notes
+
+ } else {
+
+ # create new
+ soap::server::lib::namespace_new $service $uri $notes $user_id $peeraddr $package_id
+
+ # return to admin page
+ ad_returnredirect .
+
+ }
+
+ # ok return to main list
+ #ad_returnredirect "./"
+
+ }
+
+}
+
+# test for editing
+if { $editing_namespace != 0 } {
+
+ # store namespace_id into hidden form element
+ template::element create namespace_form namespace_id \
+ -widget hidden \
+ -datatype text \
+ -value $namespace_id
+
+ # query for namespace attributes
+ db_1row namespace_select {}
+
+ # update form elements
+ template::element set_value namespace_form service $service
+ template::element set_value namespace_form notes $notes
+
+ # create method form
+ template::form create method_form
+
+ set method_form:properties(action) edit-namespace
+
+ # test for method_id assigment
+ if [info exists method_id] {
+
+ # set editing
+ set editing_method $method_id
+
+ } else {
+
+ # creating
+ set editing_method 0
+
+ }
+
+ # store namespace_id into hidden form element
+ template::element create method_form namespace_id \
+ -widget hidden \
+ -datatype text \
+ -value $namespace_id
+
+ # build idl input field
+ template::element create method_form idl \
+ -datatype text \
+ -label "IDL" \
+ -html { size 48 } \
+ -value {}; #$idl
+
+ # decl procs
+ set procs2 [list]
+
+ # get source procs and double entries for HTML options
+ foreach p [soap::get_source_procs $service] {
+
+ # get local
+ set local [namespace tail $p]
+
+ # append
+ lappend procs2 [list "$local {[info args $p]}" $local]
+
+ }
+
+ # build proc select
+ template::element create method_form proc \
+ -datatype text \
+ -label "Procedure" \
+ -widget select \
+ -options $procs2 \
+ -value $proc
+
+ # build notes input field
+ template::element create method_form method_notes \
+ -widget textarea \
+ -datatype text \
+ -label "Notes" \
+ -html { rows 10 cols 40 wrap off } \
+ -value {}; #$notes
+
+ # test for valid form
+ if { [template::form is_valid method_form] } {
+
+ # try
+ set err [catch {
+
+ # decompose IDL
+ set xsd [soap::server::lib::idl_to_xsd "C" $idl]
+
+ # get method
+ set method [lindex $xsd 1]
+
+ # verify
+ soap::check_symbol $method
+
+ } error]
+
+ # verify
+ if { $err } {
+
+ # do nothing
+
+ } else {
+
+ # show
+ set error $xsd
+
+ # set fixed
+ set idl_style "C"
+
+ # get session values
+ set user_id [ad_conn user_id]
+ set peeraddr [ad_conn peeraddr]
+
+ # look for id of named method
+ set mid [soap::wsdl::method_get_id $namespace_id $method]
+
+ # verify
+ if { $mid > 0 && $mid != $editing_method } {
+
+ # egats
+ soap::fault::raise "Duplicate method: $method"
+
+ }
+
+ # test for assigned method id
+ if { $editing_method != 0 } {
+
+ # update existing
+ soap::server::lib::method_update $method_id $method $idl $idl_style $proc $method_notes
+
+ } else {
+
+ # create new
+ soap::server::lib::method_new $namespace_id $method $idl $idl_style $proc $method_notes $user_id $peeraddr $namespace_id
+ }
+
+ # clear editing mode
+ set editing_method 0
+
+ #ad_returnredirect "./edit-namespace"
+ }
+ }
+
+ # get diffs
+ array set diffs [soap::diff_methods -same t $service]
+
+ if { $editing_method } {
+
+ # query for method attributes
+ db_1row method_select {}
+
+ # store method_id into hidden form element
+ template::element create method_form method_id \
+ -widget hidden \
+ -datatype text \
+ -value $method_id
+
+ # set db method values into field elements
+ template::element set_value method_form idl $idl
+ template::element set_value method_form proc $proc
+ template::element set_value method_form method_notes $notes
+
+ } else {
+
+ # clear
+ template::element set_value method_form proc {}
+ template::element set_value method_form idl {}
+ template::element set_value method_form method_notes {}
+
+ }
+
+ # record history list of db entries
+ set history [list]
+
+ # query methods
+ db_multirow -extend {edit delete cancel diff} methods \
+ namespace_select_all {} {
+
+ # build hot links for edit/delete/...
+ set edit "edit-namespace?method_id=$method_id&namespace_id=$namespace_id"
+ set delete "delete-method?method_id=$method_id&namespace_id=$namespace_id"
+ set cancel "edit-namespace?namespace_id=$namespace_id"
+
+ # init diff code
+ set diff ERR
+
+ # try
+ if [catch {
+
+ # get the diff details for $method
+ set details $diffs($method)
+
+ # get the diff description code
+ set diff [lindex $details 0]
+
+ # add entry to history list
+ lappend history $method
+
+ # get the args
+ set proc [format "$proc {%s}" [lindex $details 1]]
+
+ # check for orphan
+ if [string equal -nocase -length 4 $diff ORPH] {
+
+ # modify proc to reflect orphan
+ set proc "#ORPHAN#"
+
+ }
+
+
+ } msg] {
+
+ # display error using proc
+ set proc $msg
+
+ }
+
+ # use hard spaces
+ regsub -all { } $proc {\ } proc
+ regsub -all { } $idl {\ } idl
+ }
+
+ # debug
+ #set diffdata [array get diffs]
+
+ # scan history list
+ foreach remove $history {
+
+ # remove entry from diffs array
+ array unset diffs $remove
+
+ }
+
+ # loop through remaining elements in diffs
+ foreach proc [array names diffs] {
+
+ # local
+ set local [namespace tail $proc]
+
+ # build import expression
+ set import "edit-namespace?namespace_id=$namespace_id&service=$service&import=1&proc=$local"
+
+ # get diff code
+ set diff [lindex $diffs($proc) 0]
+
+ # describe code
+ switch $diff {
+
+ UPUB {
+ set desc {*NOT PUBLISHED*}
+ }
+
+ DUPL {
+ set desc {*DUPLICATE IDL*}
+ }
+
+ default {
+ set desc {*UNKNOWN ERROR*}
+ }
+
+ }
+
+ # get proc
+ set local [format "$local {%s}" [lindex $diffs($proc) 1]]
+
+ # change to hard spaces
+ regsub -all { } $local {\ } local
+
+ # add to table
+ multirow append methods -1 $namespace_id {} $desc {} $local {} $import {} {} $diff
+
+ }
+
+ # create goto anchor
+ set focus "method_form.idl"
+
+} else {
+
+ # clear
+ set editing_method 0
+
+ # clear diffs
+ array set diffs [list empty {}]
+}
+
+
+
+# set context
+set context "Administration"
+
+# update caption for toolbar
+if $editing_namespace {
+
+ # set to edit
+ set caption "edit '$service'"
+
+ # create namespace var for help
+ set namespace [format "::sg::%s" $service]
+
+} else {
+
+ # set to create
+ set caption "create service"
+}
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/admin/index-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/index-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/index-postgresql.xql 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,11 @@
+
+
+
+ postgresql7.1
+
+
+
+ select namespace_id, service, uri, notes from sg_namespaces
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/index.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/index.adp 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+There are no namespaces
+
+
+Maintenance
+
+ - Manage source libraries.
+
+
+
+ - Import the following unpublished service: @unpublished.service@
+
+
+
+-
+Registered Users do not have 'invoke' privileges on the soap-gateway package! Go to Permissions.
+
+
+
+-
+The Public do not have 'read' privileges on the soap-gateway package! This may restrict clients from downloading WSDL service specifications. Go to Permissions.
+
+
+
+Note: Only public procedures within the sg::<my-namespace>::* will be
+ imported. Comments are extracted
+ from the source files and can modified once imported.
+
+
+
+
+
+
Index: openacs-4/packages/soap-gateway/www/admin/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/index.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/index.tcl 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,97 @@
+# packages/soap-gateway/www/admin/index.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: index.tcl,v 1.1 2004/10/17 05:51:57 ncarroll Exp $
+} {
+}
+
+# clear title
+set title {}
+
+# installed correctly
+if [catch {
+
+ soap::server::lib::true 1
+
+}] {
+
+ # report as installation error
+ error "Failure while calling soap-gateway function!\nDid you restart the server after installing soap-gateway package?\n\n"
+
+}
+
+# get package id
+set package_id [ad_conn package_id]
+
+# require read permission
+ad_require_permission $package_id admin
+
+# query namespaces
+db_multirow -extend {endpoint edit delete wsdl status} namespaces namespace_list {} {
+ set endpoint [soap::wsdl::build_endpoint $service]
+ set edit "edit-namespace?namespace_id=$namespace_id"
+ set delete "delete-namespace?namespace_id=$namespace_id"
+ set wsdl [soap::wsdl::build_wsdl_url $service]
+
+ # check for problems
+ set diffs [soap::diff_methods $service]
+ if { [llength $diffs] > 0 } {
+ set status "errors"
+ } else {
+ set status "ok"
+ }
+}
+
+# get permission for object
+
+# get registered users
+set users [acs_magic_object registered_users]
+
+# test for invoke privileges on package for Registered_users
+set ru_invoke [soap::server::has_permission -user_id $users $package_id [soap::server::get_invoke_permission_moniker]]
+
+# get public
+set public [acs_magic_object the_public]
+
+# test for public read access on WSDL
+set pu_read 1;#[soap::server::has_permission -user_id $public $package_id read]
+
+# create form
+template::form create new_namespace_form
+
+# change action attribute for form - not documented
+set new_namespace_form:properties(action) edit-namespace
+
+# create form
+template::form create init_workspace_form
+
+# change action attribute for form - not documented
+set init_workspace_form:properties(action) init-workspace
+
+# create form
+template::form create init_interop_form
+
+# change action attribute for form - not documented
+set init_interop_form:properties(action) init-interop
+
+# create unpublished rowset
+multirow create unpublished service
+
+# get unpublished
+foreach s [soap::query_services -unpublished 1 -published 0] {
+
+ # add to multirow
+ multirow append unpublished $s
+
+}
+
+# set context
+set context "Administation"
+
+# update caption
+set caption "admin"
+
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/admin/libraries-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/libraries-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/libraries-postgresql.xql 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,11 @@
+
+
+
+ postgresql7.1
+
+
+
+ select library_id, path from sg_libraries
+
+
+
\ No newline at end of file
Index: openacs-4/packages/soap-gateway/www/admin/libraries.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/libraries.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/libraries.adp 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,64 @@
+
+
+
+
+ Enter the locations of the source files that will be available for importing
+ into the soap-gateway.
+ Relative locations will be appended to the acs_root directory. Directory
+ watches will be converted
+ to wildcard notation and will not recurse; e.g., soap-gateway/lib/*.tcl. The
+ files are watched by the
+ Request Processor. Refresh to update status.
+Once the source files are loaded, go back to the admin and
+ import the services into the soap-gateway.
+
+
+
+
+ Path |
+ Status |
+ Watch |
+
+
+
+
+ @libraries.path@
+ |
+
+ @libraries.status;noquote@
+ |
+ remove |
+
+
+
+ |
+ |
+ add |
+
+
+
+
+
+ |
+ Status |
+ Meaning |
+
+
+ |
+ ??? |
+ Library path returned no tcl source files |
+
+
+ |
+ ok |
+ All file timestamps in the path spec. coincide with APM |
+
+
+ |
+ stale |
+ At least one file timestamp in the path spec. does not coincide with APM |
+
+
+
+ @stat@
+
Index: openacs-4/packages/soap-gateway/www/admin/libraries.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/admin/libraries.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/admin/libraries.tcl 17 Oct 2004 05:51:57 -0000 1.1
@@ -0,0 +1,122 @@
+# packages/soap-gateway/www/admin/libraries.tcl
+
+ad_page_contract {
+
+ @author WilliamB@ByrneLitho.com
+ @creation-date 2002-12-23
+ @cvs-id $Id: libraries.tcl,v 1.1 2004/10/17 05:51:57 ncarroll Exp $
+
+} {
+ library_id:integer,notnull,optional
+ {delete 0}
+ {path {}}
+ {update 0}
+ {force 0}
+}
+
+# get package id
+set package_id [ad_conn package_id]
+
+# require read permission
+ad_require_permission $package_id admin
+
+# clear status
+set stat {}
+
+# test for delete
+if [soap::server::lib::true $delete] {
+
+ # get current
+ set current [soap::server::lib::library_get_path $library_id]
+
+ # delete
+ soap::server::lib::library_delete $library_id
+
+ # stop watch
+ soap::server::lib::watch -stop 1 $current
+
+} elseif { $path != {} } {
+
+ # test for update
+ if [info exists library_id] {
+
+ # get current
+ set current [soap::server::lib::library_get_path $library_id]
+
+ # stop watch
+ soap::server::lib::watch -stop 1 $current
+
+ # update
+ soap::server::lib::library_update $library_id $path
+
+ # update - implicit watch
+ soap::server::lib::update_libraries [list $path]
+
+ } else {
+
+ if [catch {
+
+ # create new library
+ soap::server::lib::library_new $path
+
+ }] {
+
+ # report
+ set stat "Error creating new library path:
$path
Possible duplicate."
+
+ } else {
+
+ # update - implicit watch
+ soap::server::lib::update_libraries [list $path]
+
+ }
+ }
+
+} elseif [soap::server::lib::true $update] {
+
+ # get path from id
+ set path [soap::server::lib::library_get_path $library_id]
+
+ # update
+ soap::server::lib::update_libraries [list $path]
+
+}
+
+# query namespaces
+db_multirow -extend {status remove} libraries library_list {} {
+ set remove "libraries?library_id=$library_id&delete=1"
+ if ![soap::server::lib::is_library_valid $path] {
+ set status "???"
+ } elseif [soap::server::lib::is_library_dirty $path] {
+ #set status "stale"
+ set status "stale"
+ } else {
+ set status "ok"
+ }
+
+}
+
+# clear path
+set path {}
+
+# create form
+template::form create library_form
+
+# build path input field
+template::element create library_form path \
+ -datatype text \
+ -label "Path" \
+ -html { size "100%" } \
+ -value {};
+
+# set up path
+template::element set_value library_form path "packages//lib/.tcl"
+
+# set context
+set context "Administation"
+
+# update caption
+set caption "admin"
+
+# return template
+ad_return_template
Index: openacs-4/packages/soap-gateway/www/doc/folder.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/doc/folder.gif,v
diff -u
Binary files differ
Index: openacs-4/packages/soap-gateway/www/doc/html.bmp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/doc/html.bmp,v
diff -u
Binary files differ
Index: openacs-4/packages/soap-gateway/www/doc/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/soap-gateway/www/doc/index.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/soap-gateway/www/doc/index.adp 17 Oct 2004 05:52:00 -0000 1.1
@@ -0,0 +1,120 @@
+
+@context@
+@context_bar@
+
+soap-gateway
+
+William Byrne / WilliamB@ByrneLitho.com
+An experimental OpenACS SOAP package that may prove itself useful.
+Developed using the following system configuration:
+
+ - RedHat 7.3
+ - OpenACS 4.5 (nightly snapshot 10/3/2002)
+ - AOLServer 3.3ad13
+ - nsxml 1.4
+ - PostgreSQL 7.2.1
+
+
+Abstract
+The soap-gateway is a compilation of server side tcl procedures
+ and pages that provide Remote Procedure Call (RPC) capabilities to OpenACS servers
+ for clients using SOAP/HTTP. The implementation is relatively small and maintains
+ minimal conformity to current SOAP specifications. This document describes the
+ basic implementation.
+Table of Contents
+
+ - Overview
+ - Installation
+ - Samples
+ - References
+ - License
+
+Overview (toc)
+The Simple Object Access Protocol (SOAP) v1.1
+ was submitted to W3C on April 18, 2000. Its compatriot
+ Web Services Description Language (WSDL) was submitted
+ on March 14, 2001. Together they attempt to unify diverse systems using a form
+ of XML RPC. Most major software vendors are involved to some extent. Its future
+ looks bright.
+SOAP fits nicely into the Client/Server topology. Given a client that needs
+ some functionality available on a server, SOAP can be used to specify an operation
+ and its arguments to be submitted by the client to the server. At it's root,
+ the data representing the operation is fairly basic. If the connection between
+ the client and server were a TCP wire, a data trace would show about a page
+ of XML. The XML is not complex and is often decipherable at a glance. The XML
+ data is specified as a SOAP Envelope. An evolving SOAP
+ specification defines the Envelope and its progeny. The XML data transmitted
+ between the client and server is not arbitrary and should conform to a referenced
+ WSDL instance published by the server. It's the WSDL that defines the published
+ services and the invocation formats required for execution. The vast majority
+ of SOAP documentation demonstrates SOAP over HTTP. Another mentioned transport
+ is SMTP. In each case, the SOAP Envelope follows the respective header as an
+ XML Payload.
+Many web servers have been retrofitted to support a SOAP subsystem; e.g., Websphere,
+ Apache, iPlanet, IIS, etc. There are a handful of SOAP toolkits. To name a few,
+ MSSOAP Toolkit from Microsoft, AXIS
+ from Apache, and DataSnap from Borland. A stand alone
+ Tcl implementation, TclSOAP, is available at Source Forge.
+ In the Implementation section, I'll get into the
+ details of my retrofit for OpenACS; the soap-gateway package. Client SOAP examples
+ using MSSOAP and AXIS can be found in the Samples section.
+Installation
+ (toc)
+Here's a short list of steps required to enable SOAP/HTTP connectivity
+ to your server. The instructions are brief and assumes the reader has
+ administrative experience with OpenACS. More details will be available in
+ a subsequent release.
+
+ - Select the SOAP Gateway from the list of packages that are available for
+ installation. Install it.
+ - Create a sub-site under the Main site and call it 'soap'.
+ - Create a new application by selecting the SOAP Gateway.
+ - For now, call the new soap-gateway application SOAP Gateway.
+ - Refresh this page so this admin
+ hot link points to the soap-gateway admininistration pages.
+ - Under the Maintenance section, you should see unpublished services: 'workspace'
+ and 'interop'. Import both.
+ - In the same section, you may see a message that indicates 'Registered Users'
+ do not have 'invoke' access on the soap-gateway package. If so, go to the
+ permissions area for the soap-gateway
+ instance if you wish to grant 'invoke' rights to registered users.
+ - Go to the Samples section and try the test samples.
+ Take note of the https warning when https'ing.
+
+Note: Verify 'public' access to your installed 'soap-gateway'
+ using http and not https. Select the home
+ of your 'soap-gateway' subsite to retrieve a listing of available services.
+ Also verify the WSDL for each service can be returned without the need to authenticate
+ into your server. This will allow clients to enumerate the published services
+ and retrieve the functional specification for each. Eliminating the need to
+ authenticate with the server for the purpose of retrieving service WSDLs removes
+ binding complications for client side SOAP tools.
+When importing a tcl library into the soap-gateway (i.e., any public methods
+ under the ::sg::<my-service> namespace), the soap-gateway automatically
+ grants public 'invoke' rights to any method named 'login'. This gives the client
+ an opportunity to authenticate into the server before making any other calls.
+Service libraries shipped with the soap-gateway are located in packages/soap-gateway/lib.
+Samples (toc)
+Sample SOAP client applications can be found here.
+References (toc)
+
+License (toc)
+The SOAP Gateway package is subject to the Lesser General
+ Public License.
+