s-update 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. #!/usr/bin/env ruby
  2. # -*- coding: utf-8 -*-
  3. # Licensed to the Apache Software Foundation (ASF) under one
  4. # or more contributor license agreements. See the NOTICE file
  5. # distributed with this work for additional information
  6. # regarding copyright ownership. The ASF licenses this file
  7. # to you under the Apache License, Version 2.0 (the
  8. # "License"); you may not use this file except in compliance
  9. # with the License. You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS,
  15. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. # SPARQL HTTP Update, client.
  19. require 'optparse'
  20. require 'net/http'
  21. require 'openssl'
  22. require 'uri'
  23. require 'cgi'
  24. require 'pp'
  25. require 'ostruct'
  26. # ToDo
  27. # Allow a choice of media type for GET
  28. # --accept "content-type" (and abbreviations)
  29. # --header "Add:this"
  30. # --user, --password
  31. # Basic authentication: request.basic_auth("username", "password")
  32. # Follow redirects => 301: puts response["location"] # All headers are lowercase?
  33. SOH_NAME="SOH"
  34. SOH_VERSION="1.0.0"
  35. $proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new
  36. # What about direct naming?
  37. # Names
  38. $mtTurtle = 'text/turtle;charset=utf-8'
  39. $mtRDF = 'application/rdf+xml'
  40. $mtText = 'text/plain'
  41. $mtNTriples = 'application/n-triples'
  42. $mtNQuads = 'application/n-quads'
  43. $mtJSONLD = 'application/ld+json'
  44. $mtTriG = 'application/trig'
  45. $mtSparqlResultsX = 'application/sparql-results+xml'
  46. $mtSparqlResultsJ = 'application/sparql-results+json'
  47. $mtAppJSON = 'application/json'
  48. $mtAppXML = 'application/xml'
  49. $mtSparqlResultsTSV = 'application/sparql-results+tsv'
  50. $mtSparqlResultsCSV = 'application/sparql-results+csv'
  51. $mtSparqlUpdate = 'application/sparql-update'
  52. $mtWWWForm = 'application/x-www-form-urlencoded'
  53. $mtSparqlQuery = "application/sparql-query" ;
  54. # Global media type table.
  55. $fileMediaTypes = {}
  56. $fileMediaTypes['ttl'] = $mtTurtle
  57. $fileMediaTypes['n3'] = 'text/n3; charset=utf-8'
  58. $fileMediaTypes['nt'] = $mtText
  59. $fileMediaTypes['rdf'] = $mtRDF
  60. $fileMediaTypes['owl'] = $mtRDF
  61. $fileMediaTypes['nq'] = $mtNQuads
  62. $fileMediaTypes['trig'] = $mtTriG
  63. $fileMediaTypes['json-ld'] = $mtJSONLD
  64. $fileMediaTypes['jsonld'] = $mtJSONLD
  65. # Global charset : no entry means "don't set"
  66. $charsetUTF8 = 'utf-8'
  67. $charset = {}
  68. $charset[$mtTurtle] = 'utf-8'
  69. $charset[$mtText] = 'ascii'
  70. $charset[$mtTriG] = 'utf-8'
  71. $charset[$mtNQuads] = 'utf-8'
  72. # Headers
  73. $hContentType = 'Content-Type'
  74. # $hContentEncoding = 'Content-Encoding'
  75. $hContentLength = 'Content-Length'
  76. # $hContentLocation = 'Content-Location'
  77. # $hContentRange = 'Content-Range'
  78. $hAccept = 'Accept'
  79. $hAcceptCharset = 'Accept-Charset'
  80. $hAcceptEncoding = 'Accept-Encoding'
  81. $hAcceptRanges = 'Accept-Ranges'
  82. $headers = { "User-Agent" => "#{SOH_NAME}/Fuseki #{SOH_VERSION}"}
  83. $print_http = false
  84. # Default for GET
  85. # At least allow anything (and hope!)
  86. $accept_rdf="#{$mtTurtle} , #{$mtNTriples};q=0.9 , #{$mtRDF};q=0.8 , #{$mtJSONLD};q=0.5"
  87. # Datasets
  88. $accept_ds="#{$mtTrig} , #{$mtNQuads};q=0.9 , #{$mtJSONLD};q=0.5"
  89. # For SPARQL query
  90. $accept_results="#{$mtSparqlResultsJ} , #{$mtSparqlResultsX};q=0.9 , #{$accept_rdf}"
  91. # Accept any in case of trouble.
  92. $accept_rdf="#{$accept_rdf} , */*;q=0.1"
  93. $accept_results="#{$accept_results} , */*;q=0.1"
  94. # The media type usually forces the charset.
  95. $accept_charset=nil
  96. ## Who we are.
  97. ## Two styles:
  98. ## s-query .....
  99. ## soh query .....
  100. $cmd = File.basename($0)
  101. if $cmd == 'soh'
  102. then
  103. $cmd = (ARGV.size == 0) ? 'soh' : ARGV.shift
  104. end
  105. if ! $cmd.start_with?('s-') && $cmd != 'soh'
  106. $cmd = 's-'+$cmd
  107. end
  108. ## --------
  109. def GET(dataset, graph)
  110. print "GET #{dataset} #{graph}\n" if $verbose
  111. requestURI = target(dataset, graph)
  112. headers = {}
  113. headers.merge!($headers)
  114. headers[$hAccept] = $accept_rdf
  115. headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil?
  116. get_worker(requestURI, headers)
  117. end
  118. def get_worker(requestURI, headers)
  119. uri = URI.parse(requestURI)
  120. request = Net::HTTP::Get.new(uri.request_uri)
  121. request.initialize_http_header(headers)
  122. print_http_request(uri, request)
  123. response_print_body(uri, request)
  124. end
  125. def HEAD(dataset, graph)
  126. print "HEAD #{dataset} #{graph}\n" if $verbose
  127. requestURI = target(dataset, graph)
  128. headers = {}
  129. headers.merge!($headers)
  130. headers[$hAccept] = $accept_rdf
  131. headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil?
  132. uri = URI.parse(requestURI)
  133. request = Net::HTTP::Head.new(uri.request_uri)
  134. request.initialize_http_header(headers)
  135. print_http_request(uri, request)
  136. response_no_body(uri, request)
  137. end
  138. def PUT(dataset, graph, file)
  139. print "PUT #{dataset} #{graph} #{file}\n" if $verbose
  140. send_body(dataset, graph, file, Net::HTTP::Put)
  141. end
  142. def POST(dataset, graph, file)
  143. print "POST #{dataset} #{graph} #{file}\n" if $verbose
  144. send_body(dataset, graph, file, Net::HTTP::Post)
  145. end
  146. def DELETE(dataset, graph)
  147. print "DELETE #{dataset} #{graph}\n" if $verbose
  148. requestURI = target(dataset, graph)
  149. uri = URI.parse(requestURI)
  150. request = Net::HTTP::Delete.new(uri.request_uri)
  151. headers = {}
  152. headers.merge!($headers)
  153. request.initialize_http_header(headers)
  154. print_http_request(uri, request)
  155. response_no_body(uri, request)
  156. end
  157. def uri_escape(string)
  158. CGI.escape(string)
  159. end
  160. def target(dataset, graph)
  161. return dataset+"?default" if graph == "default"
  162. return dataset+"?graph="+uri_escape(graph)
  163. end
  164. def send_body(dataset, graph, file, method)
  165. mt = content_type(file)
  166. if mt.nil?
  167. warn_exit "Can't identify the content type of '#{file}'", 9
  168. end
  169. headers = {}
  170. headers.merge!($headers)
  171. headers[$hContentType] = mt
  172. headers[$hContentLength] = File.size(file).to_s
  173. ## p headers
  174. requestURI = target(dataset, graph)
  175. uri = URI.parse(requestURI)
  176. request = method.new(uri.request_uri)
  177. request.initialize_http_header(headers)
  178. print_http_request(uri, request)
  179. request.body_stream = File.open(file)
  180. response_no_body(uri, request)
  181. end
  182. def response_no_body(uri, request)
  183. http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port)
  184. http.read_timeout = nil
  185. if uri.scheme == 'https'
  186. http.use_ssl = uri.scheme == 'https'
  187. http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  188. end
  189. begin http.start do |http|
  190. response = http.request(request)
  191. print_http_response(response)
  192. case response
  193. when Net::HTTPSuccess, Net::HTTPRedirection
  194. # OK
  195. when Net::HTTPNotFound
  196. warn_exit "404 Not found: #{uri}", 9
  197. #print response.body
  198. else
  199. warn_exit "#{response.code} #{response.message} #{uri}", 9
  200. # Unreachable
  201. response.error!
  202. end
  203. end
  204. rescue Exception => e
  205. # puts e.message
  206. #puts e.backtrace.inspect
  207. warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3
  208. end
  209. end
  210. def response_print_body(uri, request)
  211. http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port)
  212. if uri.scheme == 'https'
  213. http.use_ssl = uri.scheme == 'https'
  214. http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  215. end
  216. begin http.start do |http|
  217. # Add a blank line if headers were output.
  218. print "\n" if $http_print ;
  219. response = http.request(request) { |res|
  220. print_http_response(res)
  221. #puts res.code
  222. res.read_body do |segment|
  223. print segment
  224. end
  225. }
  226. case response
  227. when Net::HTTPSuccess, Net::HTTPRedirection
  228. # OK
  229. when Net::HTTPNotFound
  230. warn_exit "404 Not found: #{uri}", 9
  231. #print response.body
  232. else
  233. warn_exit "#{response.code}: #{uri}", 9
  234. # Unreachable
  235. response.error!
  236. end
  237. end
  238. rescue Exception => e
  239. warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3
  240. end
  241. end
  242. def print_http_request(uri, request)
  243. return unless $print_http
  244. #print "Request\n"
  245. print request.method," ",uri, "\n"
  246. print_headers(" ",request)
  247. end
  248. def print_http_response(response)
  249. return unless $print_http
  250. #print "Response\n"
  251. print response.code, " ", response.message, "\n"
  252. print_headers(" ",response)
  253. end
  254. def print_headers(marker, headers)
  255. headers.each do |k,v|
  256. k = k.split('-').map{|w| w.capitalize}.join('-')+':'
  257. printf "%s%-20s %s\n",marker,k,v
  258. end
  259. end
  260. def content_type(file)
  261. file =~ /\.([^.]*)$/
  262. ext = $1
  263. mt = $fileMediaTypes[ext]
  264. cs = $charset[mt]
  265. mt = mt+';charset='+cs if ! cs.nil?
  266. return mt
  267. end
  268. def charset(content_type)
  269. return $charset[content_type]
  270. end
  271. def warn_exit(msg, rc)
  272. warn msg
  273. exit rc ;
  274. end
  275. def parseURI(uri_string)
  276. begin
  277. return URI.parse(uri_string).to_s
  278. rescue URI::InvalidURIError => err
  279. warn_exit "Bad URI: <#{uri_string}>", 2
  280. end
  281. end
  282. ## ---- Command
  283. def cmd_soh(command=nil)
  284. ## Command line
  285. options = {}
  286. optparse = OptionParser.new do |opts|
  287. # Set a banner, displayed at the top
  288. # of the help screen.
  289. case $cmd
  290. when "s-http", "sparql-http", "soh"
  291. banner="$cmd [get|post|put|delete] datasetURI graph [file]"
  292. when "s-get", "s-head", "s-delete"
  293. banner="$cmd datasetURI graph"
  294. end
  295. opts.banner = $banner
  296. # Define the options, and what they do
  297. options[:verbose] = false
  298. opts.on( '-v', '--verbose', 'Verbose' ) do
  299. options[:verbose] = true
  300. end
  301. options[:version] = false
  302. opts.on( '--version', 'Print version and exit' ) do
  303. print "#{SOH_NAME} #{SOH_VERSION}\n"
  304. exit
  305. end
  306. # This displays the help screen, all programs are
  307. # assumed to have this option.
  308. opts.on( '-h', '--help', 'Display this screen and exit' ) do
  309. puts opts
  310. exit
  311. end
  312. end
  313. begin optparse.parse!
  314. rescue OptionParser::InvalidArgument => e
  315. warn e
  316. exit
  317. end
  318. $verbose = options[:verbose]
  319. $print_http = $verbose
  320. if command.nil?
  321. if ARGV.size == 0
  322. warn "No command given: expected one of 'get', 'put', 'post', 'delete', 'query' or 'update'"
  323. exit 1
  324. end
  325. cmdPrint=ARGV.shift
  326. command=cmdPrint.upcase
  327. else
  328. cmdPrint=command
  329. end
  330. case command
  331. when "HEAD", "GET", "DELETE"
  332. requiredFile=false
  333. when "PUT", "POST"
  334. requiredFile=true
  335. when "QUERY"
  336. cmd_sparql_query
  337. when "UPDATE"
  338. cmd_sparql_update
  339. else
  340. warn_exit "Unknown command: #{command}", 2
  341. end
  342. if requiredFile
  343. then
  344. if ARGV.size != 3
  345. warn_exit "Required: dataset URI, graph URI (or 'default') and file", 1
  346. end
  347. else
  348. if ARGV.size != 2
  349. warn_exit "Required: dataset URI and graph URI (or 'default')", 1
  350. end
  351. end
  352. dataset=parseURI(ARGV.shift)
  353. # Relative URI?
  354. graph=parseURI(ARGV.shift)
  355. file=""
  356. if requiredFile
  357. then
  358. file = ARGV.shift if requiredFile
  359. if ! File.exist?(file)
  360. warn_exit "No such file: "+file, 3
  361. end
  362. if File.directory?(file)
  363. warn_exit "File is a directory: "+file, 3
  364. end
  365. end
  366. case command
  367. when "GET"
  368. GET(dataset, graph)
  369. when "HEAD"
  370. HEAD(dataset, graph)
  371. when "PUT"
  372. PUT(dataset, graph, file)
  373. when "DELETE"
  374. DELETE(dataset, graph)
  375. when "POST"
  376. POST(dataset, graph, file)
  377. else
  378. warn_exit "Internal error: Unknown command: #{cmd}", 2
  379. end
  380. exit 0
  381. end
  382. ## --------
  383. def string_or_file(arg)
  384. return arg if ! arg.match(/^@/)
  385. a=(arg[1..-1])
  386. open(a, 'rb'){|f| f.read}
  387. end
  388. ## -------- SPARQL Query
  389. ## Choose method
  390. def SPARQL_query(service, query, query_file, forcePOST=false, args2={})
  391. if ! query_file.nil?
  392. query = open(query_file, 'rb'){|f| f.read}
  393. end
  394. if forcePOST || query.length >= 2*1024
  395. SPARQL_query_POST(service, query, args2)
  396. else
  397. SPARQL_query_GET(service, query, args2)
  398. end
  399. end
  400. ## By GET
  401. def SPARQL_query_GET(service, query, args2)
  402. args = { "query" => query }
  403. args.merge!(args2)
  404. qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
  405. if service.include? "?"
  406. then
  407. action="#{service}&#{qs}"
  408. else
  409. action="#{service}?#{qs}"
  410. end
  411. headers={}
  412. headers.merge!($headers)
  413. headers[$hAccept]=$accept_results
  414. get_worker(action, headers)
  415. end
  416. ## By POST
  417. def SPARQL_query_POST(service, query, args2)
  418. # DRY - body/no body for each of request and response.
  419. post_params={ "query" => query }
  420. post_params.merge!(args2)
  421. uri = URI.parse(service)
  422. headers={}
  423. headers.merge!($headers)
  424. headers[$hAccept]=$accept_results
  425. execute_post_form_body(uri, headers, post_params)
  426. end
  427. def execute_post_form_body(uri, headers, post_params)
  428. request = Net::HTTP::Post.new(uri.request_uri)
  429. qs=post_params.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
  430. headers[$hContentType] = $mtWWWForm
  431. headers[$hContentLength] = qs.length.to_s
  432. request.initialize_http_header(headers)
  433. request.body = qs
  434. print_http_request(uri, request)
  435. response_print_body(uri, request)
  436. end
  437. # Usage: -v --help --file= --query=
  438. def cmd_sparql_query
  439. options={}
  440. optparse = OptionParser.new do |opts|
  441. opts.banner = "Usage: #{$cmd} [--query QUERY] [--service URI] [--post] 'query' | @file"
  442. opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri|
  443. options[:service]=uri
  444. end
  445. opts.on('--query=FILE','--file=FILE', 'Take query from a file') do |file|
  446. options[:file]=file
  447. end
  448. opts.on('--output=TYPE', [:json,:xml,:text,:csv,:tsv],
  449. 'Set the output argument') do |type|
  450. options[:output]=type
  451. end
  452. opts.on('--accept=TYPE', [:json,:xml,:text,:csv,:tsv],
  453. 'Set the accept header type') do |type|
  454. options[:accept]=type
  455. end
  456. options[:verbose] = false
  457. opts.on( '--post', 'Force use of POST' ) do
  458. options[:post] = true
  459. end
  460. opts.on( '-v', '--verbose', 'Verbose' ) do
  461. options[:verbose] = true
  462. end
  463. opts.on( '--version', 'Print version and exit' ) do
  464. print "#{SOH_NAME} #{SOH_VERSION}\n"
  465. exit
  466. end
  467. opts.on( '-h', '--help', 'Display this screen and exit' ) do
  468. puts opts
  469. exit
  470. end
  471. end
  472. begin optparse.parse!
  473. rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
  474. warn e
  475. exit 1
  476. end
  477. $verbose = options[:verbose]
  478. $print_http = $verbose
  479. usePOST = options[:post]
  480. service = options[:service]
  481. warn_exit 'No service specified. Required --service=URI',1 if service.nil?
  482. # Query
  483. query=nil
  484. query_file=options[:file]
  485. if query_file.nil? && ARGV.size == 0
  486. then
  487. warn_exit 'No query specified.',1
  488. end
  489. if query_file.nil?
  490. query = ARGV.shift
  491. if query.match(/^@/)
  492. query_file = query[1..-1]
  493. query = nil
  494. end
  495. end
  496. # --output ==> output= (non-standard)
  497. args={}
  498. case options[:output]
  499. when nil
  500. when "json","xml","text","csv","tsv"
  501. args['output'] = options[:output]
  502. when :json,:xml,:text,:csv,:tsv
  503. args['output'] = options[:output].to_s
  504. else
  505. warn_exit "Unrecognized output type: "+options[:output],2
  506. end
  507. # --accept
  508. # options[:accept]
  509. print "SPARQL #{service}\n" if $verbose
  510. #args={"output"=>"text"}
  511. SPARQL_query(service, query, query_file, usePOST, args)
  512. exit(0)
  513. end
  514. ## -------- SPARQL Update
  515. # Update sent as a WWW form.
  516. def SPARQL_update_by_form(service, update, args2={})
  517. args = {}
  518. args.merge!(args2)
  519. headers={}
  520. headers.merge!($headers)
  521. # args? encode?
  522. body="update="+uri_escape(update)
  523. headers[$hContentType] = $mtWWWForm
  524. headers[$hContentLength] = body.length.to_s
  525. uri = URI.parse(service)
  526. execute_post_form(uri, headers, body)
  527. end
  528. # DRY - query form.
  529. def execute_post_form(uri, headers, body)
  530. request = Net::HTTP::Post.new(uri.request_uri)
  531. request.initialize_http_header(headers)
  532. request.body = body
  533. print_http_request(uri, request)
  534. response_no_body(uri, request)
  535. end
  536. def SPARQL_update(service, update, args2={})
  537. args = {}
  538. args.merge!(args2)
  539. headers={}
  540. headers.merge!($headers)
  541. headers[$hContentType] = $mtSparqlUpdate
  542. uri = URI.parse(service)
  543. request = Net::HTTP::Post.new(uri.request_uri)
  544. request.initialize_http_header(headers)
  545. request.body = update
  546. print_http_request(uri, request)
  547. response_no_body(uri, request)
  548. end
  549. def cmd_sparql_update(by_raw_post=true)
  550. # Share with cmd_sparql_query
  551. options={}
  552. optparse = OptionParser.new do |opts|
  553. opts.banner = "Usage: #{$cmd} [--file REQUEST] [--service URI] 'request' | @file"
  554. opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri|
  555. options[:service]=uri
  556. end
  557. opts.on('--update=FILE', '--file=FILE', 'Take update from a file') do |file|
  558. options[:file]=file
  559. end
  560. options[:verbose] = false
  561. opts.on( '-v', '--verbose', 'Verbose' ) do
  562. options[:verbose] = true
  563. end
  564. opts.on( '--version', 'Print version and exit' ) do
  565. print "#{SOH_NAME} #{SOH_VERSION}\n"
  566. exit
  567. end
  568. opts.on( '-h', '--help', 'Display this screen and exit' ) do
  569. puts opts
  570. exit
  571. end
  572. end
  573. begin optparse.parse!
  574. rescue OptionParser::InvalidArgument => e
  575. warn e
  576. exit
  577. end
  578. $verbose = options[:verbose]
  579. $print_http = $verbose
  580. service = options[:service]
  581. warn_exit 'No service specified. Required --service=URI',1 if service.nil?
  582. update=nil
  583. update_file=options[:file]
  584. if update_file.nil? && ARGV.size == 0
  585. then
  586. warn_exit 'No update specified.',1
  587. end
  588. if update_file.nil?
  589. update = ARGV.shift
  590. if update.match(/^@/)
  591. update_file = update[1..-1]
  592. update = nil
  593. end
  594. end
  595. print "SPARQL-Update #{service}\n" if $verbose
  596. args={}
  597. # Reads in the file :-(
  598. if update.nil?
  599. then
  600. update = open(update_file, 'rb'){|f| f.read}
  601. else
  602. update = string_or_file(update)
  603. end
  604. if by_raw_post
  605. SPARQL_update(service, update, args)
  606. else
  607. SPARQL_update_by_form(service, update, args)
  608. end
  609. exit(0)
  610. end
  611. ## -------
  612. case $cmd
  613. when "s-http", "sparql-http", "soh"
  614. $banner="#{$cmd} [get|post|put|delete] datasetURI graph [file]"
  615. cmd_soh
  616. when "s-get", "s-head", "s-put", "s-delete", "s-post"
  617. case $cmd
  618. when "s-get", "s-head", "s-delete"
  619. $banner="#{$cmd} datasetURI graph"
  620. when "s-put", "s-post"
  621. $banner="#{$cmd} datasetURI graph file"
  622. end
  623. cmd2 = $cmd.sub(/^s-/, '').upcase
  624. cmd_soh cmd2
  625. when "s-query", "sparql-query"
  626. cmd_sparql_query
  627. when "s-update", "sparql-update"
  628. cmd_sparql_update true
  629. when "s-update-form", "sparql-update-form"
  630. cmd_sparql_update false
  631. else
  632. warn_exit "Unknown: "+$cmd, 1
  633. end