-- -- $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 ('%VError 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;