http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pages/sparql.tpl ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pages/sparql.tpl b/jena-fuseki1/pages/sparql.tpl new file mode 100644 index 0000000..2cd5241 --- /dev/null +++ b/jena-fuseki1/pages/sparql.tpl @@ -0,0 +1,96 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<html> + <head> + <title>Fuseki</title> + <link rel="stylesheet" type="text/css" href="fuseki.css" /> + </head> + <body> +#set( $ds = $mgt.dataset($request, "") ) +#set( $srvQuery = $mgt.serviceQuery($ds) ) +#set( $srvUpdate = $mgt.serviceUpdate($ds) ) +#set( $srvUpload= $mgt.serviceUpload($ds) ) +#set( $srvGraphR = $mgt.serviceGraphRead($ds) ) +#set( $srvGraphRW = $mgt.serviceGraphReadWrite($ds) ) + +<!-- error case ... --> +<!-- Debug +<ul> + <li>${ds}</li> + <li>$srvQuery</li> + <li>$srvUpdate</li> + <li>$srvUpload</li> + <li>$srvGraphR</li> + <li>$srvGraphRW</li> +</ul> +--> + + <h1>Fuseki Query</h1> + Dataset: ${ds} + <hr/> + + <p><b>SPARQL Query</b></p> + <div class="moreindent"> + <form action="${ds}/${srvQuery}" method="GET" accept-charset="UTF-8"> + <textarea name="query" cols="70" rows="10"></textarea> + <br/> + + Output: <select name="output"> + <option value="text">Text</option> + <option value="json">JSON</option> + <option value="xml">XML</option> + <option value="csv">CSV</option> + <option value="tsv">TSV</option> + </select> + <br/> + If XML output, add XSLT style sheet (blank for none): + <select name="stylesheet"> + <option value=""></option> + <option value="/xml-to-html.xsl">xml-to-html</option> + <option value="/xml-to-html-links.xsl">xml-to-html-links</option> + <option value="/xml-to-html-plain.xsl">xml-to-html-plain</option> + </select> + <br/> + <input type="checkbox" name="force-accept" value="text/plain"/> + Force the accept header to <tt>text/plain</tt> regardless. + <br/> + <input type="submit" value="Get Results" /> + </form> + </div> + <hr/> + + <p><b>SPARQL Update</b></p> + <div class="moreindent"> + <form action="${ds}/${srvUpdate}" method="post" accept-charset="UTF-8"> + <textarea name="update" cols="70" rows="10"></textarea> + <br/> + <input type="submit" value="Perform update" /> + </form> + </div> + <hr/> + <p><b>File upload</b></p> + <div class="moreindent"> + <form action="${ds}/${srvUpload}" enctype="multipart/form-data" method="post"> + File: <input type="file" name="UNSET FILE NAME" size="40" multiple=""><br/> + Graph: <input name="graph" size="20" value="default"/><br/> + <input type="submit" value="Upload"> + </form> + </div> + <hr/> + </body> +</html>
http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pages/update-validator.html ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pages/update-validator.html b/jena-fuseki1/pages/update-validator.html new file mode 100644 index 0000000..92f21bc --- /dev/null +++ b/jena-fuseki1/pages/update-validator.html @@ -0,0 +1,62 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><title>SPARQLer Update Validator</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <link rel="stylesheet" type="text/css" href="fuseki.css" /> + + </head> + <body> + <h1>SPARQLer Update Validator</h1> + + <div class="moreindent"> + + + <form action="validate/update" method="post" accept-charset="UTF-8"> + <textarea name="update" cols="70" rows="30"> +PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> +PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> +PREFIX owl: <http://www.w3.org/2002/07/owl#> +PREFIX fn: <http://www.w3.org/2005/xpath-functions#> +PREFIX apf: <http://jena.hpl.hp.com/ARQ/property#> + +</textarea> +<br/> + Input syntax: + <input type="radio" name="languageSyntax" value="SPARQL" checked="checked"/>SPARQL + <input type="radio" name="languageSyntax" value="ARQ"/>SPARQL extended syntax + <br/> +<!-- +Output syntax: + <input type="checkbox" name="outputFormat" value="sparql" checked="checked"/>SPARQL + <input type="checkbox" name="outputFormat" value="algebra"/>SPARQL algebra + <input type="checkbox" name="outputFormat" value="quads"/>SPARQL algebra (quads) + <br/> +--> + Line numbers: + <input type="radio" name="linenumbers" value="true" checked="checked"/>Yes + <input type="radio" name="linenumbers" value="false"/>No + <br/> + + <input type="submit" value="Validate SPARQL Update" /> + </form> + + <hr/> + </div> + </body> +</html> http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pages/xml-to-html-links.xsl ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pages/xml-to-html-links.xsl b/jena-fuseki1/pages/xml-to-html-links.xsl new file mode 100644 index 0000000..66b04eb --- /dev/null +++ b/jena-fuseki1/pages/xml-to-html-links.xsl @@ -0,0 +1,227 @@ +<?xml version="1.0"?> + +<!-- + +XSLT script to format SPARQL Query Results XML Format into xhtml + +Copyright é 2004, 2005 World Wide Web Consortium, (Massachusetts +Institute of Technology, European Research Consortium for +Informatics and Mathematics, Keio University). All Rights +Reserved. This work is distributed under the W3Cî Software +License [1] 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. + +[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +Version 1 : Dave Beckett (DAWG) +Version 2 : Jeen Broekstra (DAWG) +Customization for SPARQler: Andy Seaborne +URIs as hrefs in results : Bob DuCharme & Andy Seaborne + +> - <xsl:for-each select="//res:head/res:variable"> +> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + +--> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/1999/xhtml" + xmlns:res="http://www.w3.org/2005/sparql-results#" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + exclude-result-prefixes="res xsl"> + + <!-- + <xsl:output + method="html" + media-type="text/html" + doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" + indent="yes" + encoding="UTF-8"/> + --> + + <!-- or this? --> + + <xsl:output + method="xml" + indent="yes" + encoding="UTF-8" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + omit-xml-declaration="no" /> + + <xsl:template match="res:link"> + <p>Link to <xsl:value-of select="@href"/></p> + </xsl:template> + + <xsl:template name="header"> + <div> + <h2>Header</h2> + <xsl:apply-templates select="res:head/res:link"/> + </div> + </xsl:template> + + <xsl:template name="boolean-result"> + <div> + <p>ASK => <xsl:value-of select="res:boolean"/></p> + </div> + </xsl:template> + + + <xsl:template name="vb-result"> + <div> + <table> + <xsl:text> + </xsl:text> + <tr> + <xsl:for-each select="res:head/res:variable"> + <th><xsl:value-of select="@name"/></th> + </xsl:for-each> + </tr> + <xsl:text> + </xsl:text> + <xsl:for-each select="res:results/res:result"> + <tr> + <xsl:apply-templates select="."/> + </tr> + </xsl:for-each> + </table> + </div> + </xsl:template> + + <xsl:template match="res:result"> + <xsl:variable name="current" select="."/> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + <xsl:variable name="name" select="@name"/> + <td> + <xsl:choose> + <xsl:when test="$current/res:binding[@name=$name]"> + <!-- apply template for the correct value type (bnode, uri, literal) --> + <xsl:apply-templates select="$current/res:binding[@name=$name]"/> + </xsl:when> + <xsl:otherwise> + <!-- no binding available for this variable in this solution --> + </xsl:otherwise> + </xsl:choose> + </td> + </xsl:for-each> + </xsl:template> + + <xsl:template match="res:bnode"> + <xsl:text>_:</xsl:text> + <xsl:value-of select="text()"/> + </xsl:template> + + <xsl:template name="replace-string"> + <xsl:param name="text"/> + <xsl:param name="replace"/> + <xsl:param name="with"/> + <xsl:choose> + <xsl:when test="contains($text,$replace)"> + <xsl:value-of select="substring-before($text,$replace)"/> + <xsl:value-of select="$with"/> + <xsl:call-template name="replace-string"> + <xsl:with-param name="text" + select="substring-after($text,$replace)"/> + <xsl:with-param name="replace" select="$replace"/> + <xsl:with-param name="with" select="$with"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$text"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template match="res:uri"> + <!-- MUST be XSLT 1.0 :-( --> + + <!-- Roughly: SELECT ($uri AS ?subject) ?predicate ?object { $uri ?predicate ?object } --> + <!-- XSLT 2.0 + <xsl:variable name="x"><xsl:value-of select="fn:encode-for-uri(.)"/></xsl:variable> + --> + + <xsl:variable name="x"><xsl:value-of select="."/></xsl:variable> + <xsl:variable name="q">SELECT%20%28%3C<xsl:value-of select="$x"/>%3E%20AS%20%3Fsubject%29%20%3Fpredicate%20%3Fobject%20%7B%3C<xsl:value-of select="$x"/>%3E%20%3Fpredicate%20%3Fobject%20%7D</xsl:variable> + + <!-- Escape any # --> + <xsl:variable name="q2"> + <xsl:call-template name="replace-string"> + <xsl:with-param name="text" select="$q"/> + <xsl:with-param name="replace" select="'#'" /> + <xsl:with-param name="with" select="'%23'"/> + </xsl:call-template> + </xsl:variable> + + <!-- XSLT 2.0 + <xsl:value-of select="fn:replace('$q','#','%25')"/> + --> + + <xsl:text><</xsl:text> + <a href="?query={$q2}&output=xml&stylesheet=%2Fxml-to-html-links.xsl"> + <xsl:text></xsl:text> + <xsl:value-of select="."/> + </a> + <xsl:text>></xsl:text> + </xsl:template> + + <xsl:template match="res:literal"> + <xsl:text>"</xsl:text> + <xsl:value-of select="text()"/> + <xsl:text>"</xsl:text> + + <xsl:choose> + <xsl:when test="@datatype"> + <!-- datatyped literal value --> + ^^<<xsl:value-of select="@datatype"/>> + </xsl:when> + <xsl:when test="@xml:lang"> + <!-- lang-string --> + @<xsl:value-of select="@xml:lang"/> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="res:sparql"> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + <head> + <title>SPARQLer Query Results</title> + <style> + <![CDATA[ + h1 { font-size: 150% ; } + h2 { font-size: 125% ; } + table { border-collapse: collapse ; border: 1px solid black ; } + td, th + { border: 1px solid black ; + padding-left:0.5em; padding-right: 0.5em; + padding-top:0.2ex ; padding-bottom:0.2ex + } + ]]> + </style> + </head> + <body> + + + <h1>SPARQLer Query Results</h1> + + <xsl:if test="res:head/res:link"> + <xsl:call-template name="header"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="res:boolean"> + <xsl:call-template name="boolean-result" /> + </xsl:when> + + <xsl:when test="res:results"> + <xsl:call-template name="vb-result" /> + </xsl:when> + + </xsl:choose> + + + </body> + </html> + </xsl:template> +</xsl:stylesheet> http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pages/xml-to-html-plain.xsl ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pages/xml-to-html-plain.xsl b/jena-fuseki1/pages/xml-to-html-plain.xsl new file mode 100644 index 0000000..1878ab0 --- /dev/null +++ b/jena-fuseki1/pages/xml-to-html-plain.xsl @@ -0,0 +1,187 @@ +<?xml version="1.0"?> + +<!-- + +XSLT script to format SPARQL Query Results XML Format into xhtml + +Copyright © 2004, 2005 World Wide Web Consortium, (Massachusetts +Institute of Technology, European Research Consortium for +Informatics and Mathematics, Keio University). All Rights +Reserved. This work is distributed under the W3C® Software +License [1] 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. + +[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +Version 1 : Dave Beckett (DAWG) +Version 2 : Jeen Broekstra (DAWG) +Customization for SPARQler: Andy Seaborne +Fix: + +> - <xsl:for-each select="//res:head/res:variable"> +> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + +--> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/1999/xhtml" + xmlns:res="http://www.w3.org/2005/sparql-results#" + exclude-result-prefixes="res xsl"> + + <!-- + <xsl:output + method="html" + media-type="text/html" + doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" + indent="yes" + encoding="UTF-8"/> + --> + + <!-- or this? --> + + <xsl:output + method="xml" + indent="yes" + encoding="UTF-8" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + omit-xml-declaration="no" /> + + + <xsl:template name="header"> + <div> + <h2>Header</h2> + <xsl:for-each select="res:head/res:link"> + <p>Link to <xsl:value-of select="@href"/></p> + </xsl:for-each> + </div> + </xsl:template> + + <xsl:template name="boolean-result"> + <div> + <!-- + <h2>Boolean Result</h2> + --> + <p>ASK => <xsl:value-of select="res:boolean"/></p> + </div> + </xsl:template> + + + <xsl:template name="vb-result"> + <div> + <!-- + <h2>Variable Bindings Result</h2> + <p>Ordered: <xsl:value-of select="res:results/@ordered"/></p> + <p>Distinct: <xsl:value-of select="res:results/@distinct"/></p> + --> + + <table> + <xsl:text> + </xsl:text> + <tr> + <xsl:for-each select="res:head/res:variable"> + <th><xsl:value-of select="@name"/></th> + </xsl:for-each> + </tr> + <xsl:text> + </xsl:text> + <xsl:for-each select="res:results/res:result"> + <tr> + <xsl:apply-templates select="."/> + </tr> + </xsl:for-each> + </table> + </div> + </xsl:template> + + <xsl:template match="res:result"> + <xsl:variable name="current" select="."/> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + <xsl:variable name="name" select="@name"/> + <td> + <xsl:choose> + <xsl:when test="$current/res:binding[@name=$name]"> + <!-- apply template for the correct value type (bnode, uri, literal) --> + <xsl:apply-templates select="$current/res:binding[@name=$name]"/> + </xsl:when> + <xsl:otherwise> + <!-- no binding available for this variable in this solution --> + </xsl:otherwise> + </xsl:choose> + </td> + </xsl:for-each> + </xsl:template> + + <xsl:template match="res:bnode"> + <xsl:text>_:</xsl:text> + <xsl:value-of select="text()"/> + </xsl:template> + + <xsl:template match="res:uri"> + <xsl:variable name="uri" select="text()"/> + <xsl:text><</xsl:text> + <xsl:value-of select="$uri"/> + <xsl:text>></xsl:text> + </xsl:template> + + <xsl:template match="res:literal"> + <xsl:text>"</xsl:text> + <xsl:value-of select="text()"/> + <xsl:text>"</xsl:text> + + <xsl:choose> + <xsl:when test="@datatype"> + <!-- datatyped literal value --> + ^^<<xsl:value-of select="@datatype"/>> + </xsl:when> + <xsl:when test="@xml:lang"> + <!-- lang-string --> + @<xsl:value-of select="@xml:lang"/> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="res:sparql"> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + <head> + <title>SPARQLer Query Results</title> + <style> + <![CDATA[ + h1 { font-size: 150% ; } + h2 { font-size: 125% ; } + table { border-collapse: collapse ; border: 1px solid black ; } + td, th + { border: 1px solid black ; + padding-left:0.5em; padding-right: 0.5em; + padding-top:0.2ex ; padding-bottom:0.2ex + } + ]]> + </style> + </head> + <body> + + + <h1>SPARQLer Query Results</h1> + + <xsl:if test="res:head/res:link"> + <xsl:call-template name="header"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="res:boolean"> + <xsl:call-template name="boolean-result" /> + </xsl:when> + + <xsl:when test="res:results"> + <xsl:call-template name="vb-result" /> + </xsl:when> + + </xsl:choose> + + + </body> + </html> + </xsl:template> +</xsl:stylesheet> http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pages/xml-to-html.xsl ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pages/xml-to-html.xsl b/jena-fuseki1/pages/xml-to-html.xsl new file mode 100644 index 0000000..1878ab0 --- /dev/null +++ b/jena-fuseki1/pages/xml-to-html.xsl @@ -0,0 +1,187 @@ +<?xml version="1.0"?> + +<!-- + +XSLT script to format SPARQL Query Results XML Format into xhtml + +Copyright © 2004, 2005 World Wide Web Consortium, (Massachusetts +Institute of Technology, European Research Consortium for +Informatics and Mathematics, Keio University). All Rights +Reserved. This work is distributed under the W3C® Software +License [1] 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. + +[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +Version 1 : Dave Beckett (DAWG) +Version 2 : Jeen Broekstra (DAWG) +Customization for SPARQler: Andy Seaborne +Fix: + +> - <xsl:for-each select="//res:head/res:variable"> +> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + +--> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/1999/xhtml" + xmlns:res="http://www.w3.org/2005/sparql-results#" + exclude-result-prefixes="res xsl"> + + <!-- + <xsl:output + method="html" + media-type="text/html" + doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" + indent="yes" + encoding="UTF-8"/> + --> + + <!-- or this? --> + + <xsl:output + method="xml" + indent="yes" + encoding="UTF-8" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + omit-xml-declaration="no" /> + + + <xsl:template name="header"> + <div> + <h2>Header</h2> + <xsl:for-each select="res:head/res:link"> + <p>Link to <xsl:value-of select="@href"/></p> + </xsl:for-each> + </div> + </xsl:template> + + <xsl:template name="boolean-result"> + <div> + <!-- + <h2>Boolean Result</h2> + --> + <p>ASK => <xsl:value-of select="res:boolean"/></p> + </div> + </xsl:template> + + + <xsl:template name="vb-result"> + <div> + <!-- + <h2>Variable Bindings Result</h2> + <p>Ordered: <xsl:value-of select="res:results/@ordered"/></p> + <p>Distinct: <xsl:value-of select="res:results/@distinct"/></p> + --> + + <table> + <xsl:text> + </xsl:text> + <tr> + <xsl:for-each select="res:head/res:variable"> + <th><xsl:value-of select="@name"/></th> + </xsl:for-each> + </tr> + <xsl:text> + </xsl:text> + <xsl:for-each select="res:results/res:result"> + <tr> + <xsl:apply-templates select="."/> + </tr> + </xsl:for-each> + </table> + </div> + </xsl:template> + + <xsl:template match="res:result"> + <xsl:variable name="current" select="."/> + <xsl:for-each select="/res:sparql/res:head/res:variable"> + <xsl:variable name="name" select="@name"/> + <td> + <xsl:choose> + <xsl:when test="$current/res:binding[@name=$name]"> + <!-- apply template for the correct value type (bnode, uri, literal) --> + <xsl:apply-templates select="$current/res:binding[@name=$name]"/> + </xsl:when> + <xsl:otherwise> + <!-- no binding available for this variable in this solution --> + </xsl:otherwise> + </xsl:choose> + </td> + </xsl:for-each> + </xsl:template> + + <xsl:template match="res:bnode"> + <xsl:text>_:</xsl:text> + <xsl:value-of select="text()"/> + </xsl:template> + + <xsl:template match="res:uri"> + <xsl:variable name="uri" select="text()"/> + <xsl:text><</xsl:text> + <xsl:value-of select="$uri"/> + <xsl:text>></xsl:text> + </xsl:template> + + <xsl:template match="res:literal"> + <xsl:text>"</xsl:text> + <xsl:value-of select="text()"/> + <xsl:text>"</xsl:text> + + <xsl:choose> + <xsl:when test="@datatype"> + <!-- datatyped literal value --> + ^^<<xsl:value-of select="@datatype"/>> + </xsl:when> + <xsl:when test="@xml:lang"> + <!-- lang-string --> + @<xsl:value-of select="@xml:lang"/> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="res:sparql"> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + <head> + <title>SPARQLer Query Results</title> + <style> + <![CDATA[ + h1 { font-size: 150% ; } + h2 { font-size: 125% ; } + table { border-collapse: collapse ; border: 1px solid black ; } + td, th + { border: 1px solid black ; + padding-left:0.5em; padding-right: 0.5em; + padding-top:0.2ex ; padding-bottom:0.2ex + } + ]]> + </style> + </head> + <body> + + + <h1>SPARQLer Query Results</h1> + + <xsl:if test="res:head/res:link"> + <xsl:call-template name="header"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="res:boolean"> + <xsl:call-template name="boolean-result" /> + </xsl:when> + + <xsl:when test="res:results"> + <xsl:call-template name="vb-result" /> + </xsl:when> + + </xsl:choose> + + + </body> + </html> + </xsl:template> +</xsl:stylesheet> http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/pom.xml ---------------------------------------------------------------------- diff --git a/jena-fuseki1/pom.xml b/jena-fuseki1/pom.xml new file mode 100644 index 0000000..c1d19d3 --- /dev/null +++ b/jena-fuseki1/pom.xml @@ -0,0 +1,374 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>jena-fuseki</artifactId> + <packaging>jar</packaging> + <name>Apache Jena - Fuseki1 (SPARQL 1.1 Server)</name> + <version>1.1.2-SNAPSHOT</version> + <description>Fuseki is a SPARQL 1.1 Server which provides query, update and graph store protocol endpoints that can be used to expose triple store(s) over HTTP</description> + <url>http://jena.apache.org/</url> + + <parent> + <groupId>org.apache.jena</groupId> + <artifactId>jena-parent</artifactId> + <version>12-SNAPSHOT</version> + <relativePath>../jena-parent</relativePath> + </parent> + + <!-- Need if the parent is a snapshot --> + <repositories> + <repository> + <id>apache.snapshots</id> + <name>Apache Snapshot Repository</name> + <url>http://repository.apache.org/snapshots</url> + <releases> + <enabled>false</enabled> + </releases> + </repository> + </repositories> + + <organization> + <name>Apache Jena</name> + <url>http://jena.apache.org/</url> + </organization> + + <licenses> + <license> + <name>Apache 2.0 License</name> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + </license> + </licenses> + + <properties> + <this.root>${project.artifactId}-${project.version}</this.root> + <server.jar.name>${this.root}-server</server.jar.name> + + <!-- + <assembly.soh.name>${this.root}</assembly.soh.name> + --> + + <ver.jetty>8.1.14.v20131031</ver.jetty> + <ver.velocity>1.7</ver.velocity> + + <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ssZ</maven.build.timestamp.format> + <build.time.xsd>${maven.build.timestamp}</build.time.xsd> + + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-arq</artifactId> + <version>2.13.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-arq</artifactId> + <version>2.13.0-SNAPSHOT</version> + <classifier>tests</classifier> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-core</artifactId> + <version>2.13.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-tdb</artifactId> + <version>1.1.2-SNAPSHOT</version> + </dependency> + + <!-- + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>sdb</artifactId> + <version>${ver.sdb}</version> + <optional>true</optional> + </dependency> + --> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-text</artifactId> + <version>1.1.2-SNAPSHOT</version> + <exclusions> + <!-- + Get this via commons-fileupload and also via jena-text/sol4j + Choose the commons-fileupload route + --> + <exclusion> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </exclusion> + </exclusions> + + </dependency> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-spatial</artifactId> + <version>1.1.2-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <exclusions> + <!-- Replace with slf4j adapter --> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>commons-fileupload</groupId> + <artifactId>commons-fileupload</artifactId> + </dependency> + + <!-- ?? Use one of the combined artifacts for Jetty --> + <!-- jetty-webapp + jetty-util --> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <!-- used ? - -> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + <version>${ver.jetty}</version> + </dependency> + --> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlets</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-xml</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + <version>${ver.jetty}</version> + </dependency> + + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity</artifactId> + <version>${ver.velocity}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </dependency> + + <!-- Needed because the Fuseki test suite resets logging levels --> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>false</filtering> + <directory>src/main/resources</directory> + <excludes> + <exclude>org/apache/jena/fuseki/fuseki-properties.xml</exclude> + </excludes> + </resource> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + <includes> + <include>org/apache/jena/fuseki/fuseki-properties.xml</include> + </includes> + </resource> + </resources> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <version>true</version> + <show>public</show> + <quiet>true</quiet> + <encoding>UTF-8</encoding> + <windowtitle>Apache Jena Fuseki</windowtitle> + <doctitle>Apache Jena Fuseki ${project.version}</doctitle> + <bottom>Licenced under the Apache License, Version 2.0</bottom> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <includes> + <include>**/TS_*.java</include> + </includes> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.1</version> + <configuration> + <shadedArtifactAttached>true</shadedArtifactAttached> + <shadedClassifierName>server</shadedClassifierName> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>org.apache.jena.fuseki.FusekiCmd</mainClass> + </transformer> + <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> + <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" /> + <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer"> + <addHeader>false</addHeader> + </transformer> + </transformers> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <!-- Some jars are signed but shading breaks that. + Don't include signing files. + --> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <!-- After shared jar - same phase --> + <executions> + <!-- + <execution> + <id>create-soh-assembly</id> + <phase>package</phase> + <goals><goal>single</goal></goals> + <configuration> + <finalName>${assembly.soh.name}</finalName> + <!- -<appendAssemblyId>false</appendAssemblyId> - -> + <descriptors> + <descriptor>assembly-soh.xml</descriptor> + </descriptors> + </configuration> + </execution> + --> + + <execution> + <id>create-zip-assembly</id> + <phase>package</phase> + <goals><goal>single</goal></goals> + <configuration> + <descriptors> + <descriptor>assembly-dist.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <configuration> + <encoding>UTF-8</encoding> + </configuration> + </plugin> + + </plugins> + + </build> + +</project> http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/run-fuseki ---------------------------------------------------------------------- diff --git a/jena-fuseki1/run-fuseki b/jena-fuseki1/run-fuseki new file mode 100755 index 0000000..98b0d45 --- /dev/null +++ b/jena-fuseki1/run-fuseki @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +## Run Fuseki, include development code if it looks like it's available. +## Or --pages= + +export FUSEKI_HOME=${FUSEKI_HOME:-$HOME/Jena/jena-fuseki} +if [ ! -e $FUSEKI_HOME ] +then + echo "$FUSEKI_HOME does not exist" 1>&2 + exit 1 + fi +if [ ! -d $FUSEKI_HOME ] +then + echo "$FUSEKI_HOME exists but is not a directory" 1>&2 + exit 1 + fi + +CP="$(. $FUSEKI_HOME/run_cp)" + +if [ -e "$FUSEKI_HOME/classes" ] +then + CP="$FUSEKI_HOME/classes:$CP" +elif [ -e "$FUSEKI_HOME/target/classes" ] +then + CP="$FUSEKI_HOME/target/classes:$CP" +else + echo "No Fuseki1 classes" 2>&1 +fi + +# Prepend any development directories here +DEVDIRS="jena-core jena-tdb jena-arq jena-text" +for X in $DEVDIRS +do + CPX="$FUSEKI_HOME/../$X/classes" + if [ -e "$CPX" ] + then + CP="$CPX:$CP" + fi +done + +FUSEKI_LOG=${FUSEKI_LOG:-} +JVM_ARGS="${JVM_ARGS:--Xmx1200M}" +#JVM_ARGS="$JVM_ARGS -XX:MaxDirectMemorySize=1G" + +#echo $CP + +exec java -cp "$CP" $JVM_ARGS $FUSEKI_LOG org.apache.jena.fuseki.FusekiCmd \ + --home="$FUSEKI_HOME" "$@" http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/s-delete ---------------------------------------------------------------------- diff --git a/jena-fuseki1/s-delete b/jena-fuseki1/s-delete new file mode 100755 index 0000000..4f6590d --- /dev/null +++ b/jena-fuseki1/s-delete @@ -0,0 +1,713 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# SPARQL HTTP Update, client. + +require 'optparse' +require 'net/http' +require 'uri' +require 'cgi' +require 'pp' +require 'ostruct' + +# ToDo +# Allow a choice of media type for GET +# --accept "content-type" (and abbreviations) +# --header "Add:this" +# --user, --password +# Basic authentication: request.basic_auth("username", "password") +# Follow redirects => 301: puts response["location"] # All headers are lowercase? + +SOH_NAME="SOH" +SOH_VERSION="0.0.0" + +$proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new + +# What about direct naming? + +# Names +$mtTurtle = 'text/turtle;charset=utf-8' +$mtRDF = 'application/rdf+xml' +$mtText = 'text/plain' +$mtNTriples = 'application/n-triples' +$mtNQuads = 'application/n-quads' +$mtJSONLD = 'application/ld+json' +$mtTriG = 'application/trig' +$mtSparqlResultsX = 'application/sparql-results+xml' +$mtSparqlResultsJ = 'application/sparql-results+json' +$mtAppJSON = 'application/json' +$mtAppXML = 'application/xml' +$mtSparqlResultsTSV = 'application/sparql-results+tsv' +$mtSparqlResultsCSV = 'application/sparql-results+csv' +$mtSparqlUpdate = 'application/sparql-update' +$mtWWWForm = 'application/x-www-form-urlencoded' +$mtSparqlQuery = "application/sparql-query" ; + +# Global media type table. +$fileMediaTypes = {} +$fileMediaTypes['ttl'] = $mtTurtle +$fileMediaTypes['n3'] = 'text/n3; charset=utf-8' +$fileMediaTypes['nt'] = $mtText +$fileMediaTypes['rdf'] = $mtRDF +$fileMediaTypes['owl'] = $mtRDF +$fileMediaTypes['nq'] = $mtNQuads +$fileMediaTypes['trig'] = $mtTriG +$fileMediaTypes['json-ld'] = $mtJSONLD +$fileMediaTypes['jsonld'] = $mtJSONLD + +# Global charset : no entry means "don't set" +$charsetUTF8 = 'utf-8' +$charset = {} +$charset[$mtTurtle] = 'utf-8' +$charset[$mtText] = 'ascii' +$charset[$mtTriG] = 'utf-8' +$charset[$mtNQuads] = 'utf-8' + +# Headers + +$hContentType = 'Content-Type' +# $hContentEncoding = 'Content-Encoding' +$hContentLength = 'Content-Length' +# $hContentLocation = 'Content-Location' +# $hContentRange = 'Content-Range' + +$hAccept = 'Accept' +$hAcceptCharset = 'Accept-Charset' +$hAcceptEncoding = 'Accept-Encoding' +$hAcceptRanges = 'Accept-Ranges' + +$headers = { "User-Agent" => "#{SOH_NAME}/Fuseki #{SOH_VERSION}"} +$print_http = false + +# Default for GET +# At least allow anything (and hope!) +$accept_rdf="#{$mtTurtle} , #{$mtNTriples};q=0.9 , #{$mtRDF};q=0.8 , #{$mtJSONLD};q=0.5" +# Datasets +$accept_ds="#{$mtTrig} , #{$mtNQuads};q=0.9 , #{$mtJSONLD};q=0.5" +# For SPARQL query +$accept_results="#{$mtSparqlResultsJ} , #{$mtSparqlResultsX};q=0.9 , #{$accept_rdf}" + +# Accept any in case of trouble. +$accept_rdf="#{$accept_rdf} , */*;q=0.1" +$accept_results="#{$accept_results} , */*;q=0.1" + +# The media type usually forces the charset. +$accept_charset=nil + +## Who we are. +## Two styles: +## s-query ..... +## soh query ..... + +$cmd = File.basename($0) +if $cmd == 'soh' +then + $cmd = (ARGV.size == 0) ? 'soh' : ARGV.shift +end + +if ! $cmd.start_with?('s-') && $cmd != 'soh' + $cmd = 's-'+$cmd +end + +## -------- + +def GET(dataset, graph) + print "GET #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + headers = {} + headers.merge!($headers) + headers[$hAccept] = $accept_rdf + headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil? + get_worker(requestURI, headers) +end + +def get_worker(requestURI, headers) + uri = URI.parse(requestURI) + request = Net::HTTP::Get.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_print_body(uri, request) +end + +def HEAD(dataset, graph) + print "HEAD #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + headers = {} + headers.merge!($headers) + headers[$hAccept] = $accept_rdf + headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil? + uri = URI.parse(requestURI) + request = Net::HTTP::Head.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_no_body(uri, request) +end + +def PUT(dataset, graph, file) + print "PUT #{dataset} #{graph} #{file}\n" if $verbose + send_body(dataset, graph, file, Net::HTTP::Put) +end + +def POST(dataset, graph, file) + print "POST #{dataset} #{graph} #{file}\n" if $verbose + send_body(dataset, graph, file, Net::HTTP::Post) +end + +def DELETE(dataset, graph) + print "DELETE #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + uri = URI.parse(requestURI) + request = Net::HTTP::Delete.new(uri.request_uri) + headers = {} + headers.merge!($headers) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_no_body(uri, request) +end + +def uri_escape(string) + CGI.escape(string) +end + +def target(dataset, graph) + return dataset+"?default" if graph == "default" + return dataset+"?graph="+uri_escape(graph) +end + +def send_body(dataset, graph, file, method) + mt = content_type(file) + headers = {} + headers.merge!($headers) + headers[$hContentType] = mt + headers[$hContentLength] = File.size(file).to_s + ## p headers + + requestURI = target(dataset, graph) + uri = URI.parse(requestURI) + + request = method.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + request.body_stream = File.open(file) + response_no_body(uri, request) +end + +def response_no_body(uri, request) + http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port) + http.read_timeout = nil + # check we can connect. + begin http.start + rescue Exception => e + # puts e.message + #puts e.backtrace.inspect + warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3 + end + response = http.request(request) + print_http_response(response) + case response + when Net::HTTPSuccess, Net::HTTPRedirection + # OK + when Net::HTTPNotFound + warn_exit "404 Not found: #{uri}", 9 + #print response.body + else + warn_exit "#{response.code} #{response.message} #{uri}", 9 + # Unreachable + response.error! + end + # NO BODY IN RESPONSE +end + +def response_print_body(uri, request) + http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port) + http.read_timeout = nil + # check we can connect. + begin http.start + rescue => e + #puts e.backtrace.inspect + #print e.class + warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3 + end + + # Add a blank line if headers were output. + print "\n" if $http_print ; + + begin + response = http.request(request) { |res| + print_http_response(res) + #puts res.code + res.read_body do |segment| + print segment + end + } + case response + when Net::HTTPSuccess, Net::HTTPRedirection + # OK + when Net::HTTPNotFound + warn_exit "404 Not found: #{uri}", 9 + #print response.body + else + warn_exit "#{response.code}: #{uri}", 9 + # Unreachable + response.error! + end + rescue EOFError => e + warn_exit "IO Error: "+e.message, 3 + end +end + +def print_http_request(uri, request) + return unless $print_http + #print "Request\n" + print request.method," ",uri, "\n" + print_headers(" ",request) +end + +def print_http_response(response) + return unless $print_http + #print "Response\n" + print response.code, " ", response.message, "\n" + print_headers(" ",response) +end + +def print_headers(marker, headers) + headers.each do |k,v| + k = k.split('-').map{|w| w.capitalize}.join('-')+':' + printf "%s%-20s %s\n",marker,k,v + end +end + +def content_type(file) + file =~ /\.([^.]*)$/ + ext = $1 + mt = $fileMediaTypes[ext] + cs = $charset[mt] + mt = mt+';charset='+cs if ! cs.nil? + return mt +end + +def charset(content_type) + return $charset[content_type] +end + +def warn_exit(msg, rc) + warn msg + exit rc ; +end + +def parseURI(uri_string) + begin + return URI.parse(uri_string).to_s + rescue URI::InvalidURIError => err + warn_exit "Bad URI: <#{uri_string}>", 2 + end +end + +## ---- Command + +def cmd_soh(command=nil) + ## Command line + options = {} + optparse = OptionParser.new do |opts| + # Set a banner, displayed at the top + # of the help screen. + case $cmd + when "s-http", "sparql-http", "soh" + banner="$cmd [get|post|put|delete] datasetURI graph [file]" + when "s-get", "s-head", "s-delete" + banner="$cmd datasetURI graph" + end + + opts.banner = $banner + # Define the options, and what they do + + options[:verbose] = false + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + + options[:version] = false + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + + # This displays the help screen, all programs are + # assumed to have this option. + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument => e + warn e + exit + end + + $verbose = options[:verbose] + $print_http = $verbose + + if command.nil? + if ARGV.size == 0 + warn "No command given: expected one of 'get', 'put', 'post', 'delete', 'query' or 'update'" + exit 1 + end + cmdPrint=ARGV.shift + command=cmdPrint.upcase + else + cmdPrint=command + end + + case command + when "HEAD", "GET", "DELETE" + requiredFile=false + when "PUT", "POST" + requiredFile=true + when "QUERY" + cmd_sparql_query + when "UPDATE" + cmd_sparql_update + else + warn_exit "Unknown command: #{command}", 2 + end + + if requiredFile + then + if ARGV.size != 3 + warn_exit "Required: dataset URI, graph URI (or 'default') and file", 1 + end + else + if ARGV.size != 2 + warn_exit "Required: dataset URI and graph URI (or 'default')", 1 + end + end + + dataset=parseURI(ARGV.shift) + # Relative URI? + graph=parseURI(ARGV.shift) + file="" + if requiredFile + then + file = ARGV.shift if requiredFile + if ! File.exist?(file) + warn_exit "No such file: "+file, 3 + end + if File.directory?(file) + warn_exit "File is a directory: "+file, 3 + end + end + + case command + when "GET" + GET(dataset, graph) + when "HEAD" + HEAD(dataset, graph) + when "PUT" + PUT(dataset, graph, file) + when "DELETE" + DELETE(dataset, graph) + when "POST" + POST(dataset, graph, file) + else + warn_exit "Internal error: Unknown command: #{cmd}", 2 + end + exit 0 +end + +## -------- +def string_or_file(arg) + return arg if ! arg.match(/^@/) + a=(arg[1..-1]) + open(a, 'rb'){|f| f.read} +end + +## -------- SPARQL Query + +## Choose method +def SPARQL_query(service, query, query_file, forcePOST=false, args2={}) + if ! query_file.nil? + query = open(query_file, 'rb'){|f| f.read} + end + if forcePOST || query.length >= 2*1024 + SPARQL_query_POST(service, query, args2) + else + SPARQL_query_GET(service, query, args2) + end +end + +## By GET + +def SPARQL_query_GET(service, query, args2) + args = { "query" => query } + args.merge!(args2) + qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&') + action="#{service}?#{qs}" + headers={} + headers.merge!($headers) + headers[$hAccept]=$accept_results + get_worker(action, headers) +end + +## By POST + +def SPARQL_query_POST(service, query, args2) + # DRY - body/no body for each of request and response. + post_params={ "query" => query } + post_params.merge!(args2) + uri = URI.parse(service) + headers={} + headers.merge!($headers) + headers[$hAccept]=$accept_results + execute_post_form_body(uri, headers, post_params) +end + +def execute_post_form_body(uri, headers, post_params) + request = Net::HTTP::Post.new(uri.request_uri) + qs=post_params.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&') + headers[$hContentType] = $mtWWWForm + headers[$hContentLength] = qs.length.to_s + request.initialize_http_header(headers) + request.body = qs + print_http_request(uri, request) + response_print_body(uri, request) +end + +# Usage: -v --help --file= --query= +def cmd_sparql_query + options={} + optparse = OptionParser.new do |opts| + opts.banner = "Usage: #{$cmd} [--query QUERY] [--service URI] [--post] 'query' | @file" + opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri| + options[:service]=uri + end + opts.on('--query=FILE','--file=FILE', 'Take query from a file') do |file| + options[:file]=file + end + opts.on('--output=TYPE', [:json,:xml,:text,:csv,:tsv], + 'Set the output argument') do |type| + options[:output]=type + end + opts.on('--accept=TYPE', [:json,:xml,:text,:csv,:tsv], + 'Set the accept header type') do |type| + options[:accept]=type + end + options[:verbose] = false + opts.on( '--post', 'Force use of POST' ) do + options[:post] = true + end + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e + warn e + exit 1 + end + + $verbose = options[:verbose] + $print_http = $verbose + usePOST = options[:post] + + service = options[:service] + warn_exit 'No service specified. Required --service=URI',1 if service.nil? + + # Query + query=nil + query_file=options[:file] + if query_file.nil? && ARGV.size == 0 + then + warn_exit 'No query specified.',1 + end + if query_file.nil? + query = ARGV.shift + if query.match(/^@/) + query_file = query[1..-1] + query = nil + end + end + + # --output ==> output= (non-standard) + args={} + case options[:output] + when nil + when "json","xml","text","csv","tsv" + args['output'] = options[:output] + when :json,:xml,:text,:csv,:tsv + args['output'] = options[:output].to_s + else + warn_exit "Unrecognized output type: "+options[:output],2 + end + + # --accept + # options[:accept] + + print "SPARQL #{service}\n" if $verbose + #args={"output"=>"text"} + SPARQL_query(service, query, query_file, usePOST, args) + exit(0) +end + +## -------- SPARQL Update + +# Update sent as a WWW form. +def SPARQL_update_by_form(service, update, args2={}) + args = {} + args.merge!(args2) + headers={} + headers.merge!($headers) + # args? encode? + body="update="+uri_escape(update) + headers[$hContentType] = $mtWWWForm + headers[$hContentLength] = body.length.to_s + uri = URI.parse(service) + execute_post_form(uri, headers, body) +end + +# DRY - query form. +def execute_post_form(uri, headers, body) + request = Net::HTTP::Post.new(uri.request_uri) + request.initialize_http_header(headers) + request.body = body + print_http_request(uri, request) + response_no_body(uri, request) +end + +def SPARQL_update(service, update, args2={}) + args = {} + args.merge!(args2) + headers={} + headers.merge!($headers) + headers[$hContentType] = $mtSparqlUpdate + uri = URI.parse(service) + request = Net::HTTP::Post.new(uri.request_uri) + request.initialize_http_header(headers) + request.body = update + print_http_request(uri, request) + response_no_body(uri, request) +end + +def cmd_sparql_update(by_raw_post=true) + # Share with cmd_sparql_query + options={} + optparse = OptionParser.new do |opts| + opts.banner = "Usage: #{$cmd} [--file REQUEST] [--service URI] 'request' | @file" + opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri| + options[:service]=uri + end + opts.on('--update=FILE', '--file=FILE', 'Take update from a file') do |file| + options[:file]=file + end + options[:verbose] = false + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument => e + warn e + exit + end + + $verbose = options[:verbose] + $print_http = $verbose + + service = options[:service] + warn_exit 'No service specified. Required --service=URI',1 if service.nil? + + update=nil + update_file=options[:file] + + if update_file.nil? && ARGV.size == 0 + then + warn_exit 'No update specified.',1 + end + if update_file.nil? + update = ARGV.shift + if update.match(/^@/) + update_file = update[1..-1] + update = nil + end + end + + print "SPARQL-Update #{service}\n" if $verbose + args={} + + # Reads in the file :-( + if update.nil? + then + update = open(update_file, 'rb'){|f| f.read} + else + update = string_or_file(update) + end + + if by_raw_post + SPARQL_update(service, update, args) + else + SPARQL_update_by_form(service, update, args) + end + exit(0) +end + +## ------- + +case $cmd +when "s-http", "sparql-http", "soh" + $banner="#{$cmd} [get|post|put|delete] datasetURI graph [file]" + cmd_soh +when "s-get", "s-head", "s-put", "s-delete", "s-post" + + case $cmd + when "s-get", "s-head", "s-delete" + $banner="#{$cmd} datasetURI graph" + when "s-put", "s-post" + $banner="#{$cmd} datasetURI graph file" + end + cmd2 = $cmd.sub(/^s-/, '').upcase + cmd_soh cmd2 + +when "s-query", "sparql-query" + cmd_sparql_query +when "s-update", "sparql-update" + cmd_sparql_update true +when "s-update-form", "sparql-update-form" + cmd_sparql_update false +else + warn_exit "Unknown: "+$cmd, 1 +end http://git-wip-us.apache.org/repos/asf/jena/blob/662cf71d/jena-fuseki1/s-get ---------------------------------------------------------------------- diff --git a/jena-fuseki1/s-get b/jena-fuseki1/s-get new file mode 100755 index 0000000..4f6590d --- /dev/null +++ b/jena-fuseki1/s-get @@ -0,0 +1,713 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# SPARQL HTTP Update, client. + +require 'optparse' +require 'net/http' +require 'uri' +require 'cgi' +require 'pp' +require 'ostruct' + +# ToDo +# Allow a choice of media type for GET +# --accept "content-type" (and abbreviations) +# --header "Add:this" +# --user, --password +# Basic authentication: request.basic_auth("username", "password") +# Follow redirects => 301: puts response["location"] # All headers are lowercase? + +SOH_NAME="SOH" +SOH_VERSION="0.0.0" + +$proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new + +# What about direct naming? + +# Names +$mtTurtle = 'text/turtle;charset=utf-8' +$mtRDF = 'application/rdf+xml' +$mtText = 'text/plain' +$mtNTriples = 'application/n-triples' +$mtNQuads = 'application/n-quads' +$mtJSONLD = 'application/ld+json' +$mtTriG = 'application/trig' +$mtSparqlResultsX = 'application/sparql-results+xml' +$mtSparqlResultsJ = 'application/sparql-results+json' +$mtAppJSON = 'application/json' +$mtAppXML = 'application/xml' +$mtSparqlResultsTSV = 'application/sparql-results+tsv' +$mtSparqlResultsCSV = 'application/sparql-results+csv' +$mtSparqlUpdate = 'application/sparql-update' +$mtWWWForm = 'application/x-www-form-urlencoded' +$mtSparqlQuery = "application/sparql-query" ; + +# Global media type table. +$fileMediaTypes = {} +$fileMediaTypes['ttl'] = $mtTurtle +$fileMediaTypes['n3'] = 'text/n3; charset=utf-8' +$fileMediaTypes['nt'] = $mtText +$fileMediaTypes['rdf'] = $mtRDF +$fileMediaTypes['owl'] = $mtRDF +$fileMediaTypes['nq'] = $mtNQuads +$fileMediaTypes['trig'] = $mtTriG +$fileMediaTypes['json-ld'] = $mtJSONLD +$fileMediaTypes['jsonld'] = $mtJSONLD + +# Global charset : no entry means "don't set" +$charsetUTF8 = 'utf-8' +$charset = {} +$charset[$mtTurtle] = 'utf-8' +$charset[$mtText] = 'ascii' +$charset[$mtTriG] = 'utf-8' +$charset[$mtNQuads] = 'utf-8' + +# Headers + +$hContentType = 'Content-Type' +# $hContentEncoding = 'Content-Encoding' +$hContentLength = 'Content-Length' +# $hContentLocation = 'Content-Location' +# $hContentRange = 'Content-Range' + +$hAccept = 'Accept' +$hAcceptCharset = 'Accept-Charset' +$hAcceptEncoding = 'Accept-Encoding' +$hAcceptRanges = 'Accept-Ranges' + +$headers = { "User-Agent" => "#{SOH_NAME}/Fuseki #{SOH_VERSION}"} +$print_http = false + +# Default for GET +# At least allow anything (and hope!) +$accept_rdf="#{$mtTurtle} , #{$mtNTriples};q=0.9 , #{$mtRDF};q=0.8 , #{$mtJSONLD};q=0.5" +# Datasets +$accept_ds="#{$mtTrig} , #{$mtNQuads};q=0.9 , #{$mtJSONLD};q=0.5" +# For SPARQL query +$accept_results="#{$mtSparqlResultsJ} , #{$mtSparqlResultsX};q=0.9 , #{$accept_rdf}" + +# Accept any in case of trouble. +$accept_rdf="#{$accept_rdf} , */*;q=0.1" +$accept_results="#{$accept_results} , */*;q=0.1" + +# The media type usually forces the charset. +$accept_charset=nil + +## Who we are. +## Two styles: +## s-query ..... +## soh query ..... + +$cmd = File.basename($0) +if $cmd == 'soh' +then + $cmd = (ARGV.size == 0) ? 'soh' : ARGV.shift +end + +if ! $cmd.start_with?('s-') && $cmd != 'soh' + $cmd = 's-'+$cmd +end + +## -------- + +def GET(dataset, graph) + print "GET #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + headers = {} + headers.merge!($headers) + headers[$hAccept] = $accept_rdf + headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil? + get_worker(requestURI, headers) +end + +def get_worker(requestURI, headers) + uri = URI.parse(requestURI) + request = Net::HTTP::Get.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_print_body(uri, request) +end + +def HEAD(dataset, graph) + print "HEAD #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + headers = {} + headers.merge!($headers) + headers[$hAccept] = $accept_rdf + headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil? + uri = URI.parse(requestURI) + request = Net::HTTP::Head.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_no_body(uri, request) +end + +def PUT(dataset, graph, file) + print "PUT #{dataset} #{graph} #{file}\n" if $verbose + send_body(dataset, graph, file, Net::HTTP::Put) +end + +def POST(dataset, graph, file) + print "POST #{dataset} #{graph} #{file}\n" if $verbose + send_body(dataset, graph, file, Net::HTTP::Post) +end + +def DELETE(dataset, graph) + print "DELETE #{dataset} #{graph}\n" if $verbose + requestURI = target(dataset, graph) + uri = URI.parse(requestURI) + request = Net::HTTP::Delete.new(uri.request_uri) + headers = {} + headers.merge!($headers) + request.initialize_http_header(headers) + print_http_request(uri, request) + response_no_body(uri, request) +end + +def uri_escape(string) + CGI.escape(string) +end + +def target(dataset, graph) + return dataset+"?default" if graph == "default" + return dataset+"?graph="+uri_escape(graph) +end + +def send_body(dataset, graph, file, method) + mt = content_type(file) + headers = {} + headers.merge!($headers) + headers[$hContentType] = mt + headers[$hContentLength] = File.size(file).to_s + ## p headers + + requestURI = target(dataset, graph) + uri = URI.parse(requestURI) + + request = method.new(uri.request_uri) + request.initialize_http_header(headers) + print_http_request(uri, request) + request.body_stream = File.open(file) + response_no_body(uri, request) +end + +def response_no_body(uri, request) + http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port) + http.read_timeout = nil + # check we can connect. + begin http.start + rescue Exception => e + # puts e.message + #puts e.backtrace.inspect + warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3 + end + response = http.request(request) + print_http_response(response) + case response + when Net::HTTPSuccess, Net::HTTPRedirection + # OK + when Net::HTTPNotFound + warn_exit "404 Not found: #{uri}", 9 + #print response.body + else + warn_exit "#{response.code} #{response.message} #{uri}", 9 + # Unreachable + response.error! + end + # NO BODY IN RESPONSE +end + +def response_print_body(uri, request) + http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port) + http.read_timeout = nil + # check we can connect. + begin http.start + rescue => e + #puts e.backtrace.inspect + #print e.class + warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3 + end + + # Add a blank line if headers were output. + print "\n" if $http_print ; + + begin + response = http.request(request) { |res| + print_http_response(res) + #puts res.code + res.read_body do |segment| + print segment + end + } + case response + when Net::HTTPSuccess, Net::HTTPRedirection + # OK + when Net::HTTPNotFound + warn_exit "404 Not found: #{uri}", 9 + #print response.body + else + warn_exit "#{response.code}: #{uri}", 9 + # Unreachable + response.error! + end + rescue EOFError => e + warn_exit "IO Error: "+e.message, 3 + end +end + +def print_http_request(uri, request) + return unless $print_http + #print "Request\n" + print request.method," ",uri, "\n" + print_headers(" ",request) +end + +def print_http_response(response) + return unless $print_http + #print "Response\n" + print response.code, " ", response.message, "\n" + print_headers(" ",response) +end + +def print_headers(marker, headers) + headers.each do |k,v| + k = k.split('-').map{|w| w.capitalize}.join('-')+':' + printf "%s%-20s %s\n",marker,k,v + end +end + +def content_type(file) + file =~ /\.([^.]*)$/ + ext = $1 + mt = $fileMediaTypes[ext] + cs = $charset[mt] + mt = mt+';charset='+cs if ! cs.nil? + return mt +end + +def charset(content_type) + return $charset[content_type] +end + +def warn_exit(msg, rc) + warn msg + exit rc ; +end + +def parseURI(uri_string) + begin + return URI.parse(uri_string).to_s + rescue URI::InvalidURIError => err + warn_exit "Bad URI: <#{uri_string}>", 2 + end +end + +## ---- Command + +def cmd_soh(command=nil) + ## Command line + options = {} + optparse = OptionParser.new do |opts| + # Set a banner, displayed at the top + # of the help screen. + case $cmd + when "s-http", "sparql-http", "soh" + banner="$cmd [get|post|put|delete] datasetURI graph [file]" + when "s-get", "s-head", "s-delete" + banner="$cmd datasetURI graph" + end + + opts.banner = $banner + # Define the options, and what they do + + options[:verbose] = false + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + + options[:version] = false + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + + # This displays the help screen, all programs are + # assumed to have this option. + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument => e + warn e + exit + end + + $verbose = options[:verbose] + $print_http = $verbose + + if command.nil? + if ARGV.size == 0 + warn "No command given: expected one of 'get', 'put', 'post', 'delete', 'query' or 'update'" + exit 1 + end + cmdPrint=ARGV.shift + command=cmdPrint.upcase + else + cmdPrint=command + end + + case command + when "HEAD", "GET", "DELETE" + requiredFile=false + when "PUT", "POST" + requiredFile=true + when "QUERY" + cmd_sparql_query + when "UPDATE" + cmd_sparql_update + else + warn_exit "Unknown command: #{command}", 2 + end + + if requiredFile + then + if ARGV.size != 3 + warn_exit "Required: dataset URI, graph URI (or 'default') and file", 1 + end + else + if ARGV.size != 2 + warn_exit "Required: dataset URI and graph URI (or 'default')", 1 + end + end + + dataset=parseURI(ARGV.shift) + # Relative URI? + graph=parseURI(ARGV.shift) + file="" + if requiredFile + then + file = ARGV.shift if requiredFile + if ! File.exist?(file) + warn_exit "No such file: "+file, 3 + end + if File.directory?(file) + warn_exit "File is a directory: "+file, 3 + end + end + + case command + when "GET" + GET(dataset, graph) + when "HEAD" + HEAD(dataset, graph) + when "PUT" + PUT(dataset, graph, file) + when "DELETE" + DELETE(dataset, graph) + when "POST" + POST(dataset, graph, file) + else + warn_exit "Internal error: Unknown command: #{cmd}", 2 + end + exit 0 +end + +## -------- +def string_or_file(arg) + return arg if ! arg.match(/^@/) + a=(arg[1..-1]) + open(a, 'rb'){|f| f.read} +end + +## -------- SPARQL Query + +## Choose method +def SPARQL_query(service, query, query_file, forcePOST=false, args2={}) + if ! query_file.nil? + query = open(query_file, 'rb'){|f| f.read} + end + if forcePOST || query.length >= 2*1024 + SPARQL_query_POST(service, query, args2) + else + SPARQL_query_GET(service, query, args2) + end +end + +## By GET + +def SPARQL_query_GET(service, query, args2) + args = { "query" => query } + args.merge!(args2) + qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&') + action="#{service}?#{qs}" + headers={} + headers.merge!($headers) + headers[$hAccept]=$accept_results + get_worker(action, headers) +end + +## By POST + +def SPARQL_query_POST(service, query, args2) + # DRY - body/no body for each of request and response. + post_params={ "query" => query } + post_params.merge!(args2) + uri = URI.parse(service) + headers={} + headers.merge!($headers) + headers[$hAccept]=$accept_results + execute_post_form_body(uri, headers, post_params) +end + +def execute_post_form_body(uri, headers, post_params) + request = Net::HTTP::Post.new(uri.request_uri) + qs=post_params.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&') + headers[$hContentType] = $mtWWWForm + headers[$hContentLength] = qs.length.to_s + request.initialize_http_header(headers) + request.body = qs + print_http_request(uri, request) + response_print_body(uri, request) +end + +# Usage: -v --help --file= --query= +def cmd_sparql_query + options={} + optparse = OptionParser.new do |opts| + opts.banner = "Usage: #{$cmd} [--query QUERY] [--service URI] [--post] 'query' | @file" + opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri| + options[:service]=uri + end + opts.on('--query=FILE','--file=FILE', 'Take query from a file') do |file| + options[:file]=file + end + opts.on('--output=TYPE', [:json,:xml,:text,:csv,:tsv], + 'Set the output argument') do |type| + options[:output]=type + end + opts.on('--accept=TYPE', [:json,:xml,:text,:csv,:tsv], + 'Set the accept header type') do |type| + options[:accept]=type + end + options[:verbose] = false + opts.on( '--post', 'Force use of POST' ) do + options[:post] = true + end + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e + warn e + exit 1 + end + + $verbose = options[:verbose] + $print_http = $verbose + usePOST = options[:post] + + service = options[:service] + warn_exit 'No service specified. Required --service=URI',1 if service.nil? + + # Query + query=nil + query_file=options[:file] + if query_file.nil? && ARGV.size == 0 + then + warn_exit 'No query specified.',1 + end + if query_file.nil? + query = ARGV.shift + if query.match(/^@/) + query_file = query[1..-1] + query = nil + end + end + + # --output ==> output= (non-standard) + args={} + case options[:output] + when nil + when "json","xml","text","csv","tsv" + args['output'] = options[:output] + when :json,:xml,:text,:csv,:tsv + args['output'] = options[:output].to_s + else + warn_exit "Unrecognized output type: "+options[:output],2 + end + + # --accept + # options[:accept] + + print "SPARQL #{service}\n" if $verbose + #args={"output"=>"text"} + SPARQL_query(service, query, query_file, usePOST, args) + exit(0) +end + +## -------- SPARQL Update + +# Update sent as a WWW form. +def SPARQL_update_by_form(service, update, args2={}) + args = {} + args.merge!(args2) + headers={} + headers.merge!($headers) + # args? encode? + body="update="+uri_escape(update) + headers[$hContentType] = $mtWWWForm + headers[$hContentLength] = body.length.to_s + uri = URI.parse(service) + execute_post_form(uri, headers, body) +end + +# DRY - query form. +def execute_post_form(uri, headers, body) + request = Net::HTTP::Post.new(uri.request_uri) + request.initialize_http_header(headers) + request.body = body + print_http_request(uri, request) + response_no_body(uri, request) +end + +def SPARQL_update(service, update, args2={}) + args = {} + args.merge!(args2) + headers={} + headers.merge!($headers) + headers[$hContentType] = $mtSparqlUpdate + uri = URI.parse(service) + request = Net::HTTP::Post.new(uri.request_uri) + request.initialize_http_header(headers) + request.body = update + print_http_request(uri, request) + response_no_body(uri, request) +end + +def cmd_sparql_update(by_raw_post=true) + # Share with cmd_sparql_query + options={} + optparse = OptionParser.new do |opts| + opts.banner = "Usage: #{$cmd} [--file REQUEST] [--service URI] 'request' | @file" + opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri| + options[:service]=uri + end + opts.on('--update=FILE', '--file=FILE', 'Take update from a file') do |file| + options[:file]=file + end + options[:verbose] = false + opts.on( '-v', '--verbose', 'Verbose' ) do + options[:verbose] = true + end + opts.on( '--version', 'Print version and exit' ) do + print "#{SOH_NAME} #{SOH_VERSION}\n" + exit + end + opts.on( '-h', '--help', 'Display this screen and exit' ) do + puts opts + exit + end + end + + begin optparse.parse! + rescue OptionParser::InvalidArgument => e + warn e + exit + end + + $verbose = options[:verbose] + $print_http = $verbose + + service = options[:service] + warn_exit 'No service specified. Required --service=URI',1 if service.nil? + + update=nil + update_file=options[:file] + + if update_file.nil? && ARGV.size == 0 + then + warn_exit 'No update specified.',1 + end + if update_file.nil? + update = ARGV.shift + if update.match(/^@/) + update_file = update[1..-1] + update = nil + end + end + + print "SPARQL-Update #{service}\n" if $verbose + args={} + + # Reads in the file :-( + if update.nil? + then + update = open(update_file, 'rb'){|f| f.read} + else + update = string_or_file(update) + end + + if by_raw_post + SPARQL_update(service, update, args) + else + SPARQL_update_by_form(service, update, args) + end + exit(0) +end + +## ------- + +case $cmd +when "s-http", "sparql-http", "soh" + $banner="#{$cmd} [get|post|put|delete] datasetURI graph [file]" + cmd_soh +when "s-get", "s-head", "s-put", "s-delete", "s-post" + + case $cmd + when "s-get", "s-head", "s-delete" + $banner="#{$cmd} datasetURI graph" + when "s-put", "s-post" + $banner="#{$cmd} datasetURI graph file" + end + cmd2 = $cmd.sub(/^s-/, '').upcase + cmd_soh cmd2 + +when "s-query", "sparql-query" + cmd_sparql_query +when "s-update", "sparql-update" + cmd_sparql_update true +when "s-update-form", "sparql-update-form" + cmd_sparql_update false +else + warn_exit "Unknown: "+$cmd, 1 +end
