--
-- $Id$
--
-- This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
-- project.
--
-- Copyright (C) 1998-2014 OpenLink Software
--
-- This project is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the
-- Free Software Foundation; only version 2 of the License, dated June 1991.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along
-- with this program; if not, write to the Free Software Foundation, Inc.,
-- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
cl_exec ('registry_set (''fct_max_timeout'',''10000'')');
DB.DBA.VHOST_REMOVE (lpath=>'/fct/service');
DB.DBA.VHOST_DEFINE (lpath=>'/fct/service', ppath=>'/SOAP/Http/fct_svc', soap_user=>'dba');
create procedure fct_init ()
{
if (__proc_exists ('WS.WS.host_meta_add') is not null)
{
WS.WS.host_meta_add ('FCT.service', '');
WS.WS.host_meta_add ('FCT.browser', '');
WS.WS.host_meta_add ('FCT.describe',
'');
}
}
;
fct_init ();
create procedure fct_svc_log (in qr varchar, in lines varchar)
{
declare fname, ua any;
if (not (sys_dir_is_allowed ('fctlogs/') and file_stat ('fctlogs/') <> 0))
return;
ua := http_request_header (lines, 'User-Agent');
fname := sprintf ('fctlogs/fct%02d%02d%04d.log', dayofmonth(now ()), month (now()), year (now ()));
string_to_file (fname, sprintf ('***\n* %s\n* %s\n* %s\n* %s\n', date_rfc1123 (now ()), http_client_ip (), qr, ua), -1);
}
;
create procedure
fct_svc_exec (in tree any, in timeout int, in accept varchar, in lines any)
{
declare start_time int;
declare sqls, msg, qr, qr2, act varchar;
declare ret, md, res, xmlout any;
xmlout := 1;
if (accept like '%/sparql-results+%' or accept = 'application/json')
xmlout := 0;
set result_timeout = timeout;
sqls := '00000';
ret := '';
qr := fct_query (xpath_eval ('//query', tree, 1));
-- dbg_obj_print(qr);
if (xmlout)
qr2 := fct_xml_wrap (tree, qr);
else
qr2 := 'sparql define output:valmode "LONG" ' || qr;
start_time := msec_time ();
--http (qr2);
fct_svc_log (qr, lines);
exec (qr2, sqls, msg, vector (), 0, md, res);
act := db_activity ();
if (sqls <> '00000' and sqls <> 'S1TAT')
signal (sqls, msg);
set result_timeout = 0;
if (xmlout)
{
if (not isarray (res) or 0 = length (res) or not isarray (res[0]) or 0 = length (res[0]))
res := xtree_doc ('');
else
res := res[0][0];
ret := xmlelement ("facets", xmlelement ("sparql", qr), xmlelement ("time", msec_time () - start_time),
xmlelement ("complete", case when sqls = 'S1TAT' then 'no' else 'yes' end),
xmlelement ("timeout", timeout),
xmlelement ("db-activity", act), res);
ret := xslt (registry_get ('_fct_xslt_') || 'fct_resp.xsl', ret);
}
else
{
declare ses, tmp any;
ses := string_output ();
DB.DBA.SPARQL_RESULTS_WRITE (ses, md, res, accept, 1);
tmp := string_output_string (ses);
if (accept like '%/json' or accept like '%+json')
{
tmp := rtrim (tmp, '}');
tmp := tmp || sprintf (', "facets": { "sparql":"%s", "complete":"%s", "time":"%d", "timeout":"%d", "db-activity":"%s" } }',
replace (qr,'"', '\\"'), case when sqls = 'S1TAT' then 'no' else 'yes' end, msec_time () - start_time, timeout, act);
}
ret := tmp;
}
return ret;
}
;
create procedure fct_svc () __soap_http 'text/xml'
{
declare cnt, tp, ret, timeout, xt, xslt, maxt, tmp, lines, accept any;
lines := http_request_header ();
tp := http_request_header (lines, 'Content-Type');
accept := http_request_header_full (lines, 'Accept', '*/*');
accept := DB.DBA.HTTP_RDF_GET_ACCEPT_BY_Q (accept);
set http_charset='utf-8';
if (tp <> 'text/xml' and tp <> 'application/json')
{
http_status_set (500);
http_header ('Content-Type: text/plain\r\n');
return 'Invalid content type, supported are: application/json and text/xml';
}
cnt := http_body_read ();
if (tp = 'application/json')
cnt := json2xml (string_output_string (cnt));
-- dbg_obj_print ('fct_svc');
-- dbg_obj_print (string_output_string (cnt));
declare exit handler for sqlstate '*'
{
http_status_set (500);
ret := sprintf ('%V
Error while executing query%V',
__SQL_STATE, __SQL_MESSAGE);
goto ret;
};
xt := xtree_doc (cnt);
xslt := xslt (registry_get ('_fct_xslt_') || 'fct_req.xsl', xt);
tmp := cast (xpath_eval ('//query/@timeout', xslt) as varchar);
if (tmp is null)
timeout := atoi (registry_get ('fct_timeout_min'));
else
timeout := atoi (tmp);
maxt := atoi (registry_get ('fct_timeout_max'));
if (0 >= timeout or timeout > maxt)
timeout := maxt;
ret := fct_svc_exec (xslt, timeout, accept, lines);
ret:
if (tp = 'application/json')
{
http_header ('Content-Type: application/json\r\n');
ret := xml2json (ret);
}
return ret;
}
;
grant execute on fct_svc to dba;
DB.DBA.VHOST_REMOVE (lpath=>'/fct/soap');
DB.DBA.VHOST_DEFINE (lpath=>'/fct/soap', ppath=>'/SOAP/', soap_user=>'dba');
select DB.DBA.soap_dt_define ('',
'
');
select DB.DBA.soap_dt_define ('',
'
');
create procedure fct.fct.query (
in query XMLType __soap_type 'http://openlinksw.com/services/facets/1.0/:query',
in ws_soap_request any
)
__SOAP_DOC 'http://openlinksw.com/services/facets/1.0/:facets'
{
declare cnt, tp, ret, timeout, xt, xslt, maxt, tmp, lines, qr any;
lines := http_request_header ();
xt := xml_cut (xpath_eval ('/Envelope/Body/query', xml_tree_doc (ws_soap_request)));
xslt := xslt (registry_get ('_fct_xslt_') || 'fct_req.xsl', xt);
tmp := cast (xpath_eval ('//query/@timeout', xslt) as varchar);
if (tmp is null)
timeout := atoi (registry_get ('fct_timeout'));
else
timeout := atoi (tmp);
maxt := atoi (registry_get ('fct_max_timeout'));
if (timeout > maxt)
timeout := maxt;
qr := fct_query (xpath_eval ('//query', xslt, 1));
fct_svc_log (qr, lines);
ret := fct_exec (xslt, timeout);
ret := xslt (registry_get ('_fct_xslt_') || 'fct_resp.xsl', ret);
return ret;
}
;
grant execute on fct.fct.query to dba;