You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2015/01/14 11:31:12 UTC
[10/93] [abbrv] [partial] jena git commit: Maven modules for Fuseki2
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/webapp/manage.html
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/manage.html b/jena-fuseki2/jena-fuseki-core/src/main/webapp/manage.html
new file mode 100644
index 0000000..3ee53f4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/manage.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Apache Jena Fuseki - manage dataset</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
+ <link href="css/font-awesome.min.css" rel="stylesheet" media="screen">
+ <link href="css/codemirror.css" rel="stylesheet" media="screen">
+ <link href="css/qonsole.css" rel="stylesheet" media="screen">
+ <link href="css/jquery.dataTables.css" rel="stylesheet" media="screen">
+ <link href="css/fui.css" rel="stylesheet" media="screen">
+
+ <script data-main="js/app/main.manage.js" src="js/lib/require.min.js"></script>
+
+ <!--[if lt IE 9]>
+ <script src="js/lib/html5shiv.js"></script>
+ <script src="js/lib/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+ <nav class="navbar navbar-default" role="navigation">
+ <div class="container">
+ <div class="row">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="index.html">
+ <img src="images/jena-logo-notext-small.png" alt="Apache Jena logo" title="Apache Jena" />
+ <div>Apache<br />Jena<br /><strong>Fuseki</strong></div>
+ </a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse navbar-ex1-collapse">
+ <ul class="nav navbar-nav">
+ <li class=""><a href="index.html"><i class="fa fa-home"></i></a></li>
+ <li class=""><a href="dataset.html"><i class="fa fa-database"></i> dataset</a></li>
+ <li class="active"><a href="manage.html"><i class="fa fa-cogs"></i> manage datasets</a></li>
+ <li class=""><a href="services.html"><i class="fa fa-wrench"></i> services</a></li>
+ <li class=""><a href="documentation.html"><i class="fa fa-info-circle"></i> help</a></li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="status-indicator">
+ <div>Server<br />status:</div>
+ </li>
+ <li class="status-indicator">
+ <a class="" href="admin/server-log.html" id="server-status-light" title="current server status">
+ <span class="server-up"></span>
+ </a>
+ </li>
+ </ul>
+ </div><!-- /.navbar-collapse -->
+ </div><!-- /row -->
+ </div><!-- /container -->
+ </nav>
+
+ <div class="container">
+
+ <div class="row">
+ <div class="col-md-12">
+ <h2>
+ Manage datasets
+ </h2>
+ <p>Perform management actions on existing datasets, including backup,
+ or add a new dataset.
+ </p>
+ </div>
+ </div> <!-- /.row -->
+
+ <div class="row">
+ <div class="col-md-12">
+ <div class="dataset-selector-container"></div>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <div class="content-frame">
+ <ul class="nav nav-tabs">
+ <li><a href="#datasets" data-toggle="tab"><i class='fa fa-database'></i> existing datasets</a></li>
+ <li><a href="#new-dataset" data-toggle="tab"><i class='fa fa-plus-circle'></i> add new dataset</a></li>
+ </ul>
+
+ <!-- Tab panes -->
+ <div class="tab-content">
+ <div class="tab-pane" id="datasets">
+ <div id="dataset-management"></div>
+ </div> <!-- /.tab-pane -->
+
+ <div class="tab-pane" id="new-dataset">
+ <div id="dataset-simple-create"></div>
+ </div> <!-- /.tab-pane -->
+ </div> <!-- /.tab-content -->
+ </div> <!-- /.content-frame -->
+
+ </div> <!-- /.col-md-12 -->
+ </div> <!-- /.row -->
+ </div> <!--/.container -->
+
+
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/webapp/services.html
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/services.html b/jena-fuseki2/jena-fuseki-core/src/main/webapp/services.html
new file mode 100644
index 0000000..b0020fb
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/services.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Apache Jena Fuseki - services</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
+ <link href="css/font-awesome.min.css" rel="stylesheet" media="screen">
+ <link href="css/codemirror.css" rel="stylesheet" media="screen">
+ <link href="css/qonsole.css" rel="stylesheet" media="screen">
+ <link href="css/jquery.dataTables.css" rel="stylesheet" media="screen">
+ <link href="css/fui.css" rel="stylesheet" media="screen">
+
+ <script data-main="js/app/main.index.js" src="js/lib/require.min.js"></script>
+
+ <!--[if lt IE 9]>
+ <script src="js/lib/html5shiv.js"></script>
+ <script src="js/lib/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+ <nav class="navbar navbar-default" role="navigation">
+ <div class="container">
+ <div class="row">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="index.html">
+ <img src="images/jena-logo-notext-small.png" alt="Apache Jena logo" title="Apache Jena" />
+ <div>Apache<br />Jena<br /><strong>Fuseki</strong></div>
+ </a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse navbar-ex1-collapse">
+ <ul class="nav navbar-nav">
+ <li class=""><a href="index.html"><i class="fa fa-home"></i></a></li>
+ <li class=""><a href="dataset.html"><i class="fa fa-database"></i> dataset</a></li>
+ <li class=""><a href="manage.html"><i class="fa fa-cogs"></i> manage datasets</a></li>
+ <li class="active"><a href="services.html"><i class="fa fa-wrench"></i> services</a></li>
+ <li class=""><a href="documentation.html"><i class="fa fa-info-circle"></i> help</a></li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="status-indicator">
+ <div>Server<br />status:</div>
+ </li>
+ <li class="status-indicator">
+ <a class="" href="admin/server-log.html" id="server-status-light" title="current server status">
+ <span class="server-up"></span>
+ </a>
+ </li>
+ </ul>
+ </div><!-- /.navbar-collapse -->
+ </div><!-- /row -->
+ </div><!-- /container -->
+ </nav>
+
+ <div class="container">
+
+ <div class="row">
+ <div class="col-md-12">
+ <h2>
+ Inspect dataset
+ </h2>
+ </div>
+ </div>
+
+ </div>
+
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/webapp/test/test-fuseki-config.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/test/test-fuseki-config.ttl b/jena-fuseki2/jena-fuseki-core/src/main/webapp/test/test-fuseki-config.ttl
new file mode 100644
index 0000000..190676a
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/test/test-fuseki-config.ttl
@@ -0,0 +1,27 @@
+# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+
+@prefix : <#> .
+@prefix fuseki: <http://jena.apache.org/fuseki#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
+@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
+
+## ---------------------------------------------------------------
+## Updatable in-memory dataset.
+
+<#service1> rdf:type fuseki:Service ;
+ # URI of the dataset -- http://host:port/ds
+ fuseki:name "test-service" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceUpdate "update" ;
+ fuseki:serviceUpload "upload" ;
+ fuseki:serviceReadWriteGraphStore "data" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#dataset> ;
+ .
+
+## In-memory, initially empty.
+<#dataset> rdf:type ja:RDFDataset .
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/webapp/validate.html
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/webapp/validate.html b/jena-fuseki2/jena-fuseki-core/src/main/webapp/validate.html
new file mode 100644
index 0000000..82b13e2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/webapp/validate.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Apache Jena Fuseki - validation</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
+ <link href="css/font-awesome.min.css" rel="stylesheet" media="screen">
+ <link href="css/codemirror.css" rel="stylesheet" media="screen">
+ <link href="css/qonsole.css" rel="stylesheet" media="screen">
+ <link href="css/jquery.dataTables.css" rel="stylesheet" media="screen">
+ <link href="css/fui.css" rel="stylesheet" media="screen">
+
+ <script data-main="js/app/main.validation.js" src="js/lib/require.min.js"></script>
+
+ <!--[if lt IE 9]>
+ <script src="../js/lib/html5shiv.js"></script>
+ <script src="../js/lib/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+ <nav class="navbar navbar-default" role="navigation">
+ <div class="container">
+ <div class="row">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="index.html">
+ <img src="images/jena-logo-notext-small.png" alt="Apache Jena logo" title="Apache Jena" />
+ <div>Apache<br />Jena<br /><strong>Fuseki</strong></div>
+ </a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse navbar-ex1-collapse">
+ <ul class="nav navbar-nav">
+ <li class=""><a href="index.html"><i class="fa fa-home"></i></a></li>
+ <li class=""><a href="query.html"><i class="fa fa-question-circle"></i> query</a></li>
+ <li class="active"><a href="validate.html"><i class="fa fa-check-circle"></i> validate</a></li>
+ <li class="admin"><a href="admin-data-management.html"><i class="fa fa-cogs"></i> administer</a></li>
+ <li class="admin"><a href="admin-stats.html"><i class="fa fa-dashboard"></i> stats</a></li>
+ <li class="admin"><a href="admin-logs.html"><i class="fa fa-book"></i> logs</a></li>
+ <li class=""><a href="documentation.html"><i class="fa fa-info-circle"></i> help</a></li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="status-indicator">
+ <div>Server<br />status:</div>
+ </li>
+ <li class="status-indicator">
+ <a class="" href="admin/server-log.html" id="server-status-light" title="current server status">
+ <span class="server-up"></span>
+ </a>
+ </li>
+ </ul>
+ </div><!-- /.navbar-collapse -->
+ </div><!-- /row -->
+ </div><!-- /container -->
+ </nav>
+
+ <div class="container">
+ <div class="row">
+ <h1>Fuseki – validation</h1>
+ <p>Use this page to validate SPARQL queries or RDF data.</p>
+ <p class="text-danger">Forthcoming feature – not yet working.</p>
+
+
+ <div class="validation qonsole">
+ <div class="col-md-12 well">
+ <div class="query-edit">
+ <div id="query-edit-cm" class=""></div>
+ </div>
+ <div class="query-chrome">
+ <form class="form-inline" role="form">
+ <div class="validate-as-options options-list">
+ <h2>Validate as:</h2>
+ <ul class="list-inline">
+ <li><a class="btn btn-custom2 btn-sm active validate-as-option" data-toggle="button" data-validate-as="sparql">SPARQL</a></li>
+ <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="arq">SPARQL extended syntax</a></li>
+ <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="Turtle">Turtle</a></li>
+ <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="TriG">TriG</a></li>
+ <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="N-Triples">N-Triples</a></li>
+ <li><a class="btn btn-custom2 btn-sm validate-as-option" data-toggle="button" data-validate-as="N-Quads">N-Quads</a></li>
+ </ul>
+ </div><!-- /.validate-as-options -->
+
+ <div class="output-format-options options-list">
+ <h2>Output format:</h2>
+ <ul class="list-inline">
+ <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="formatted">SPARQL</a></li>
+ <li><a class="btn btn-custom2 btn-sm active" data-toggle="button" data-output-format="algebra">SPARQL algebra</a></li>
+ <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-quads">SPARQL algebra (quads)</a></li>
+ <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-opt">SPARQL algebra (with optimizations)</a></li>
+ <li><a class="btn btn-custom2 btn-sm" data-toggle="button" data-output-format="algebra-opt-quads">SPARQL algebra (quads, with optimizations)</a></li>
+ </ul>
+ </div><!-- /.output-format-options -->
+
+ <div class="row">
+ <div class="col-md-3 col-md-offset-1">
+ <a href="#" class="btn btn-success perform-validation">perform validation</a>
+ </div>
+ </div>
+
+ </form>
+ </div>
+ </div>
+
+ <!-- results -->
+ <div id="results-block" class="row validation-output">
+ <div class="col-md-12">
+ <div class="well">
+ <div class="row">
+ <div class="col-md-12">
+ <span class="loadingSpinner hidden">
+ <img src="images/wait30.gif" alt="waiting for server action to complete" />
+ </span>
+ <span class="timeTaken hidden"></span>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12" id="results">
+ <h2 class="col-md-12">Validation output</h2>
+ <div class="query-edit">
+ <div id="validation-output-cm" class=""></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row clearfix"></div>
+
+ <footer>
+ </footer>
+ </div><!-- /.validation-->
+ </div><!-- /.row -->
+ </div><!-- /.container -->
+
+ <script src="../js/lib/jquery-1.10.2.min.js"></script>
+ <script src="../js/lib/bootstrap.min.js"></script>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java
new file mode 100644
index 0000000..3f1aa17
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/AbstractFusekiTest.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.AfterClass ;
+import org.junit.Before ;
+import org.junit.BeforeClass ;
+
+/** Framework for tests using client-side operation onto a forked Fuseki server.
+ * Not general - some test sets set up their own environment for
+ * different, additional requirements.
+ */
+
+public class AbstractFusekiTest extends BaseTest
+{
+ @BeforeClass
+ public static void allocServerForSuite() {
+ ServerTest.allocServer() ;
+ }
+
+ @AfterClass
+ public static void freeServerForSuite() {
+ ServerTest.freeServer() ;
+ }
+
+ @Before public void resetServer() {
+ ServerTest.resetServer() ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/FileSender.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/FileSender.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/FileSender.java
new file mode 100644
index 0000000..8381ab5
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/FileSender.java
@@ -0,0 +1,87 @@
+/**
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import java.io.IOException ;
+import java.io.PrintStream ;
+import java.net.HttpURLConnection ;
+import java.net.URL ;
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.UUID ;
+
+import org.apache.jena.atlas.io.IO ;
+
+public class FileSender {
+ // HttpClient 4.3 has MultipartEntity but the 4.2->4.3 change is less
+ // than trivial (and it seems some environment fix the HttpClient)
+ // so here's some code for testing support.
+// MultipartEntity entity = new MultipartEntity();
+// entity.addPart(...)
+// HttpPost request = new HttpPost(url);
+// request.setEntity(entity);
+// HttpClient client = new DefaultHttpClient();
+// HttpResponse response = client.execute(request);
+
+ class Entry {
+ String fileName ;
+ String content ;
+ String contentType ;
+ }
+
+ private List<Entry> items = new ArrayList<Entry>() ;
+
+ private String url ;
+
+ public FileSender(String url ) { this.url = url ; }
+
+ public void add(String filename, String content, String type) {
+ Entry e = new Entry() ;
+ e.fileName = filename ;
+ e.content = content ;
+ e.contentType = type ;
+ items.add(e) ;
+ }
+
+ public void send(String method) {
+ try {
+ String WNL = "\r\n" ; // Web newline
+ String boundary = UUID.randomUUID().toString() ;
+
+ HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
+ connection.setRequestMethod(method);
+ connection.setDoOutput(true) ;
+ connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
+ try ( PrintStream ps = new PrintStream(connection.getOutputStream()) ; ) {
+ for ( Entry e : items ) {
+ ps.print("--" + boundary+WNL) ;
+ ps.print("Content-Disposition: form-data; name=\"FILE\"; filename=\""+e.fileName+"\""+WNL) ;
+ ps.print("Content-Type: "+e.contentType+";charset=UTF-8"+WNL) ;
+ ps.print(WNL);
+ ps.print(e.content) ;
+ ps.print(WNL);
+ }
+ ps.print("--" + boundary + "--"+WNL);
+ }
+ connection.connect();
+ int responseCode = connection.getResponseCode();
+ } catch (IOException ex) { IO.exception(ex); }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerTest.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerTest.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerTest.java
new file mode 100644
index 0000000..1a70869
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki ;
+
+import java.nio.file.Paths ;
+import java.util.Collection ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.fuseki.server.* ;
+import org.apache.jena.fuseki.jetty.JettyServerConfig ;
+import org.apache.jena.fuseki.jetty.JettyFuseki ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.modify.request.Target ;
+import com.hp.hpl.jena.sparql.modify.request.UpdateDrop ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+import com.hp.hpl.jena.tdb.base.file.Location ;
+import com.hp.hpl.jena.update.Update ;
+import com.hp.hpl.jena.update.UpdateExecutionFactory ;
+import com.hp.hpl.jena.update.UpdateProcessor ;
+
+/**
+ * Manage a server for testing. Example for one server per test suite:
+ *
+ * <pre>
+ * \@BeforeClass public static void beforeClass() { ServerTest.allocServer() ; }
+ * \@AfterClass public static void afterClass() { ServerTest.freeServer() ; }
+ * \@Before public void beforeTest() { ServerTest.resetServer() ; }
+ * </pre>
+ */
+public class ServerTest {
+ // Abstraction that runs a SPARQL server for tests.
+
+ public static final int port = 3535 ;
+ public static final String urlRoot = "http://localhost:" + port + "/" ;
+ public static final String datasetPath = "/dataset" ;
+ public static final String urlDataset = "http://localhost:" + port + datasetPath ;
+ public static final String serviceUpdate = urlDataset + "/update" ;
+ public static final String serviceQuery = urlDataset + "/query" ;
+ public static final String serviceREST = urlDataset + "/data" ;
+
+ public static final String gn1 = "http://graph/1" ;
+ public static final String gn2 = "http://graph/2" ;
+ public static final String gn99 = "http://graph/99" ;
+
+ public static final Node n1 = NodeFactory.createURI("http://graph/1") ;
+ public static final Node n2 = NodeFactory.createURI("http://graph/2") ;
+ public static final Node n99 = NodeFactory.createURI("http://graph/99") ;
+
+ public static final Graph graph1 = SSE.parseGraph("(base <http://example/> (graph (<x> <p> 1)))") ;
+ public static final Graph graph2 = SSE.parseGraph("(base <http://example/> (graph (<x> <p> 2)))") ;
+
+ public static final Model model1 = ModelFactory.createModelForGraph(graph1) ;
+ public static final Model model2 = ModelFactory.createModelForGraph(graph2) ;
+
+ private static JettyFuseki server = null ;
+
+ // reference count of start/stop server
+ private static int countServer = 0 ;
+
+ // This will cause there to be one server over all tests.
+ // Must be after initialization of counters
+ // static { allocServer() ; }
+
+ static public void allocServer() {
+ if ( countServer == 0 )
+ setupServer() ;
+ countServer++ ;
+ }
+
+ static public void freeServer() {
+ if ( countServer >= 0 ) {
+ countServer-- ;
+ if ( countServer == 0 )
+ teardownServer() ;
+ }
+ }
+
+ protected static void setupServer() {
+ FusekiEnv.FUSEKI_HOME = Paths.get(TS_Fuseki.FusekiTestHome).toAbsolutePath() ;
+ FileOps.ensureDir("target");
+ FileOps.ensureDir(TS_Fuseki.FusekiTestHome);
+ FileOps.ensureDir(TS_Fuseki.FusekiTestBase) ;
+ FusekiEnv.FUSEKI_BASE = Paths.get(TS_Fuseki.FusekiTestBase).toAbsolutePath() ;
+ setupServer(null) ;
+ }
+
+ protected static void setupServer(String authConfigFile) {
+ SystemState.location = Location.mem() ;
+ SystemState.init$() ;
+
+ ServerInitialConfig params = new ServerInitialConfig() ;
+ DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+ params.dsg = dsg ;
+ params.datasetPath = ServerTest.datasetPath ;
+ params.allowUpdate = true ;
+ FusekiServerListener.initialSetup = params ;
+
+ JettyServerConfig config = make(true, true) ;
+ config.authConfigFile = authConfigFile ;
+ JettyFuseki.initializeServer(config);
+ JettyFuseki.instance.start() ;
+ server = JettyFuseki.instance ;
+ }
+
+ public static JettyServerConfig make(boolean allowUpdate, boolean listenLocal) {
+ JettyServerConfig config = new JettyServerConfig() ;
+ // Avoid any persistent record.
+ config.port = ServerTest.port ;
+ config.contextPath = "/" ;
+ config.loopback = listenLocal ;
+ config.jettyConfigFile = null ;
+ config.pages = Fuseki.PagesStatic ;
+ config.enableCompression = true ;
+ config.verboseLogging = false ;
+ return config ;
+ }
+
+ protected static void teardownServer() {
+ if ( server != null )
+ server.stop() ;
+ server = null ;
+ // Clear out the registry.
+ Collection<String> keys = Iter.toList(DataAccessPointRegistry.get().keys()) ;
+ for (String k : keys)
+ DataAccessPointRegistry.get().remove(k) ;
+ }
+
+ public static void resetServer() {
+ Update clearRequest = new UpdateDrop(Target.ALL) ;
+ UpdateProcessor proc = UpdateExecutionFactory.createRemote(clearRequest, ServerTest.serviceUpdate) ;
+ proc.execute() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
new file mode 100644
index 0000000..db8a4aa
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.fuseki.http.TestDatasetAccessorHTTP ;
+import org.apache.jena.fuseki.http.TestDatasetGraphAccessorHTTP ;
+import org.apache.jena.fuseki.http.TestHttpOp ;
+import org.apache.jena.fuseki.server.FusekiEnv ;
+import org.junit.BeforeClass ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestHttpOp.class
+ , TestSPARQLProtocol.class
+ , TestDatasetGraphAccessorHTTP.class
+ , TestDatasetAccessorHTTP.class
+ , TestQuery.class
+ , TestAuth.class
+ , TestDatasetOps.class
+ , TestFileUpload.class
+ , TestAdmin.class
+})
+
+
+
+
+public class TS_Fuseki extends ServerTest
+{
+ public static final String FusekiTestHome = "target/FusekiHome" ;
+ public static final String FusekiTestBase = FusekiTestHome+"/run" ;
+
+ @BeforeClass public static void setupForFusekiServer() {
+ FileOps.ensureDir(FusekiTestHome);
+ FileOps.clearDirectory(FusekiTestHome);
+ System.setProperty("FUSEKI_HOME", FusekiTestHome) ;
+ FusekiEnv.setEnvironment() ;
+ FusekiLogging.setLogging();
+
+ org.apache.log4j.Level WARN1 = org.apache.log4j.Level.WARN ;
+ java.util.logging.Level WARN2 = java.util.logging.Level.WARNING ;
+
+ // Occasionally log4j.properties gets out of step.
+ LogCtl.logLevel("org.apache.shiro", WARN1, WARN2);
+ LogCtl.logLevel("org.eclipse.jetty", WARN1, WARN2);
+
+ LogCtl.logLevel(Fuseki.serverLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.configLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.adminLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.builderLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.actionLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.requestLogName, WARN1, WARN2);
+ LogCtl.logLevel(Fuseki.servletRequestLogName, WARN1, WARN2);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
new file mode 100644
index 0000000..d5e6ddb
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAdmin.java
@@ -0,0 +1,538 @@
+/**
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import static org.apache.jena.fuseki.ServerTest.datasetPath ;
+import static org.apache.jena.fuseki.ServerTest.urlRoot ;
+import static org.apache.jena.fuseki.mgt.MgtConst.opDatasets ;
+import static org.apache.jena.fuseki.mgt.MgtConst.opPing ;
+import static org.apache.jena.fuseki.mgt.MgtConst.opServer ;
+import static org.apache.jena.fuseki.mgt.MgtConst.opStats ;
+import static org.apache.jena.riot.web.HttpOp.execHttpDelete ;
+import static org.apache.jena.riot.web.HttpOp.execHttpGet ;
+import static org.apache.jena.riot.web.HttpOp.execHttpPost ;
+
+import java.io.File ;
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.http.HttpEntity ;
+import org.apache.http.HttpResponse ;
+import org.apache.http.NameValuePair ;
+import org.apache.http.client.entity.UrlEncodedFormEntity ;
+import org.apache.http.entity.FileEntity ;
+import org.apache.http.message.BasicNameValuePair ;
+import org.apache.jena.atlas.json.JSON ;
+import org.apache.jena.atlas.json.JsonArray ;
+import org.apache.jena.atlas.json.JsonObject ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.web.HttpException ;
+import org.apache.jena.atlas.web.TypedInputStream ;
+import org.apache.jena.fuseki.mgt.JsonConst ;
+import org.apache.jena.riot.WebContent ;
+import org.apache.jena.riot.web.HttpOp ;
+import org.apache.jena.riot.web.HttpResponseHandler ;
+import org.apache.jena.web.HttpSC ;
+import org.junit.AfterClass ;
+import org.junit.Before ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+/** Tests of the admin functionality */
+public class TestAdmin extends BaseTest {
+
+ // Name of the dataset in the assembler file.
+ static String dsTest = "test-ds2" ;
+
+ @BeforeClass
+ public static void beforeClass() {
+ ServerTest.allocServer() ;
+ ServerTest.resetServer() ;
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ ServerTest.freeServer() ;
+ }
+
+ @Before public void beforeTest() {
+ ServerTest.resetServer() ;
+ }
+
+ // --- Ping
+
+ @Test public void ping_1() {
+ execHttpGet(ServerTest.urlRoot+"$/"+opPing) ;
+ }
+
+ @Test public void ping_2() {
+ execHttpPost(ServerTest.urlRoot+"$/"+opPing, null) ;
+ }
+
+ // --- Server status
+
+ @Test public void server_1() {
+ JsonValue jv = httpGetJson(ServerTest.urlRoot+"$/"+opServer) ;
+ JsonObject obj = jv.getAsObject() ;
+ assertTrue(obj.hasKey(JsonConst.admin)) ;
+ assertTrue(obj.hasKey(JsonConst.datasets)) ;
+ assertTrue(obj.hasKey(JsonConst.uptime)) ;
+ assertTrue(obj.hasKey(JsonConst.startDT)) ;
+ }
+
+ @Test public void server_2() {
+ execHttpPost(ServerTest.urlRoot+"$/"+opServer, null) ;
+ }
+
+ // --- List all datasets
+
+ @Test public void list_datasets_1() {
+ try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets) ; ) { }
+ }
+
+ @Test public void list_datasets_2() {
+ try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets) ) {
+ assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ;
+ JsonValue v = JSON.parseAny(in) ;
+ assertNotNull(v.getAsObject().get("datasets")) ;
+ checkJsonDatasetsAll(v);
+ }
+ }
+
+ // Specific dataset
+ @Test public void list_datasets_3() {
+ checkExists(datasetPath) ;
+ }
+
+ // Specific dataset
+ @Test public void list_datasets_4() {
+ try {
+ getDatasetDescription("does-not-exist") ;
+ } catch (HttpException ex) {
+ assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ;
+ }
+ }
+
+ // Specific dataset
+ @Test public void list_datasets_5() {
+ JsonValue v = getDatasetDescription(datasetPath) ;
+ checkJsonDatasetsOne(v.getAsObject()) ;
+ }
+
+ private static JsonValue getDatasetDescription(String dsName) {
+ try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets+"/"+dsName) ) {
+ assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ;
+ JsonValue v = JSON.parse(in) ;
+ return v ;
+ }
+ }
+
+ // -- Add
+
+ private static void addTestDataset() {
+ File f = new File("testing/config-ds-1.ttl") ;
+ org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ;
+ HttpEntity e = new FileEntity(f, ct) ;
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ;
+ }
+
+ private static void deleteDataset(String name) {
+ execHttpDelete(ServerTest.urlRoot+"$/"+opDatasets+"/"+name) ;
+ }
+
+ // Specific dataset
+ @Test public void add_delete_dataset_1() {
+ checkNotThere(dsTest) ;
+
+ addTestDataset() ;
+
+ // Check exists.
+ checkExists(dsTest) ;
+
+ // Remove it.
+ deleteDataset(dsTest) ;
+ checkNotThere(dsTest) ;
+ }
+
+ // Try to add twice
+ @Test public void add_delete_dataset_2() {
+ checkNotThere(dsTest) ;
+
+ File f = new File("testing/config-ds-1.ttl") ;
+ {
+ org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ;
+ HttpEntity e = new FileEntity(f, ct) ;
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ;
+ }
+ // Check exists.
+ checkExists(dsTest) ;
+ try {
+ org.apache.http.entity.ContentType ct = org.apache.http.entity.ContentType.parse(WebContent.contentTypeTurtle+"; charset="+WebContent.charsetUTF8) ;
+ HttpEntity e = new FileEntity(f, ct) ;
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ;
+ } catch (HttpException ex) {
+ assertEquals(HttpSC.CONFLICT_409, ex.getResponseCode()) ;
+ }
+ // Check exists.
+ checkExists(dsTest) ;
+ deleteDataset(dsTest) ;
+ }
+
+ @Test public void add_delete_dataset_3() throws Exception {
+ String name = "MEMTEST" ;
+ //String args = "dbType=mem&dbName="+name ;
+
+ List<NameValuePair> args = new ArrayList<NameValuePair>() ;
+ args.add(new BasicNameValuePair("dbType", "mem")) ;
+ args.add(new BasicNameValuePair("dbName", name)) ;
+
+ HttpEntity e = new UrlEncodedFormEntity(args) ;
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets, e) ;
+ checkExists(name) ;
+ deleteDataset(name) ;
+ }
+
+ @Test public void delete_dataset_1() {
+ String name = "NoSuchDataset" ;
+ try {
+ execHttpDelete(ServerTest.urlRoot+"$/"+opDatasets+"/"+name) ;
+ fail("delete did not cause an Http Exception") ;
+ } catch ( HttpException ex ) {
+ assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ;
+ }
+ }
+
+ // ---- Active/Offline.
+
+ @Test public void state_1() {
+ // Add one
+ addTestDataset() ;
+ checkExists(dsTest) ;
+
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=offline", null) ;
+
+ checkExistsNotActive(dsTest);
+
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=active", null) ;
+
+ checkExists(dsTest) ;
+ deleteDataset(dsTest) ;
+ }
+
+ @Test public void state_2() {
+ addTestDataset() ;
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/"+dsTest+"?state=offline", null) ;
+ deleteDataset(dsTest) ;
+ checkNotThere(dsTest) ;
+ }
+
+ @Test public void state_3() {
+ addTestDataset() ;
+ try {
+ execHttpPost(ServerTest.urlRoot+"$/"+opDatasets+"/DoesNotExist?state=offline", null) ;
+ } catch (HttpException ex) { assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ; }
+ deleteDataset(dsTest) ;
+ }
+
+ // ---- Backup
+
+ // ---- Server
+
+ // ---- Stats
+
+ @Test public void stats_1() {
+ JsonValue v = execGetJSON(urlRoot+"$/"+opStats) ;
+ checkJsonStatsAll(v);
+ }
+
+ @Test public void stats_2() {
+ addTestDataset() ;
+ JsonValue v = execGetJSON(urlRoot+"$/"+opStats+datasetPath) ;
+ checkJsonStatsAll(v);
+ deleteDataset(dsTest) ;
+ }
+
+ @Test public void stats_3() {
+ addTestDataset() ;
+ try {
+ JsonValue v = execGetJSON(urlRoot+"$/"+opStats+"/DoesNotExist") ;
+ checkJsonStatsAll(v);
+ } catch (HttpException ex) { assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()); }
+ deleteDataset(dsTest) ;
+ }
+
+ // Sync task testing
+
+ @Test public void task_1() {
+ String x = execSleepTask(null, 10) ;
+ assertNotNull(x) ;
+ Integer.parseInt(x) ;
+ }
+
+ @Test public void task_2() {
+ String x = "NoSuchTask" ;
+ String url = urlRoot+"$/tasks/"+x ;
+ try {
+ httpGetJson(url) ;
+ } catch (HttpException ex) {
+ assertEquals(404, ex.getResponseCode()) ;
+ }
+ try {
+ checkInTasks(x) ;
+ fail("No failure!") ;
+ } catch (AssertionError ex) {}
+ }
+
+
+ @Test public void task_3() {
+ // Timing dependent.
+ // Create a "long" running task so we can find it.
+ String x = execSleepTask(null, 100) ;
+ checkTask(x) ;
+ checkInTasks(x) ;
+ assertNotNull(x) ;
+ Integer.parseInt(x) ;
+ }
+
+ @Test public void task_4() {
+ // Timing dependent.
+ // Create a "short" running task
+ String x = execSleepTask(null, 1) ;
+ // Check exists in the list of all tasks (should be "finished")
+ checkInTasks(x) ;
+ String url = urlRoot+"$/tasks/"+x ;
+
+ boolean finished = false ;
+ for ( int i = 0 ; i < 10 ; i++ ) {
+ if ( i != 0 )
+ Lib.sleep(25) ;
+ JsonValue v = httpGetJson(url) ;
+ checkTask(v) ;
+ if ( v.getAsObject().hasKey("finished") ) {
+ finished = true ;
+ break ;
+ }
+ }
+ if ( ! finished )
+ fail("Task has not finished") ;
+ }
+
+ @Test public void task_5() {
+ // Short ruuning task - still in info API call.
+ String x = execSleepTask(null, 1) ;
+ checkInTasks(x) ;
+ }
+
+ private JsonValue getTask(String taskId) {
+ String url = urlRoot+"$/tasks/"+taskId ;
+ return httpGetJson(url) ;
+ }
+
+
+ static class JsonResponseHandler implements HttpResponseHandler {
+
+ private JsonValue result = null ;
+
+ public JsonValue getJSON() {
+ return result ;
+ }
+
+ @Override
+ public void handle(String baseIRI, HttpResponse response) throws IOException {
+ try ( InputStream in = response.getEntity().getContent() ) {
+ result = JSON.parseAny(in) ;
+ }
+ }
+
+ }
+
+
+
+ private String execSleepTask(String name, int millis) {
+ String url = urlRoot+"$/sleep" ;
+ if ( name != null ) {
+ if ( name.startsWith("/") )
+ name = name.substring(1) ;
+ url = url + "/"+name ;
+ }
+
+ JsonResponseHandler x = new JsonResponseHandler() ;
+ HttpOp.execHttpPost(url+"?interval="+millis, null, WebContent.contentTypeJSON, x) ;
+ JsonValue v = x.getJSON() ;
+ String id = v.getAsObject().get("taskId").getAsString().value() ;
+ return id ;
+ }
+
+ private JsonValue httpGetJson(String url) {
+ JsonResponseHandler x = new JsonResponseHandler() ;
+ HttpOp.execHttpGet(url, WebContent.contentTypeJSON, x) ;
+ return x.getJSON() ;
+ }
+
+ private void checkTask(String x) {
+ String url = urlRoot+"$/tasks/"+x ;
+ JsonValue v = httpGetJson(url) ;
+ checkTask(v) ;
+ }
+
+ private void checkTask(JsonValue v) {
+ assertNotNull(v) ;
+ assertTrue(v.isObject()) ;
+ //System.out.println(v) ;
+ JsonObject obj = v.getAsObject() ;
+ try {
+ assertTrue(obj.hasKey("task")) ;
+ assertTrue(obj.hasKey("taskId")) ;
+ // Not present until it runs : "started"
+ } catch (AssertionError ex) {
+ System.out.println(obj) ;
+ throw ex ;
+ }
+ }
+
+ private void checkInTasks(String x) {
+ String url = urlRoot+"$/tasks" ;
+ JsonValue v = httpGetJson(url) ;
+ assertTrue(v.isArray()) ;
+ JsonArray array = v.getAsArray() ;
+ int found = 0 ;
+ for ( int i = 0 ; i < array.size() ; i++ ) {
+ JsonValue jv = array.get(i) ;
+ assertTrue(jv.isObject()) ;
+ JsonObject obj = jv.getAsObject() ;
+ checkTask(obj) ;
+ if ( obj.get("taskId").getAsString().value().equals(x) ) {
+ found++ ;
+ }
+ }
+ assertEquals("Occurence of taskId count", 1, found) ;
+ }
+
+ // Auxilary
+
+ private static void askPing(String name) {
+ if ( name.startsWith("/") )
+ name = name.substring(1) ;
+ try ( TypedInputStream in = execHttpGet(urlRoot+name+"/sparql?query=ASK%7B%7D") ) {}
+ }
+
+ private static void adminPing(String name) {
+ try ( TypedInputStream in = execHttpGet(urlRoot+"$/"+opDatasets+"/"+name) ) {}
+ }
+
+ private static void checkExists(String name) {
+ adminPing(name) ;
+ askPing(name) ;
+ }
+
+ private static void checkExistsNotActive(String name) {
+ adminPing(name) ;
+ try { askPing(name) ;
+ fail("askPing did not cause an Http Exception") ;
+ } catch ( HttpException ex ) {}
+ JsonValue v = getDatasetDescription(name) ;
+ assertFalse(v.getAsObject().get("ds.state").getAsBoolean().value()) ;
+ }
+
+ private static void checkNotThere(String name) {
+ if ( name.startsWith("/") )
+ name = name.substring(1) ;
+ // Check gone exists.
+ try { adminPing(name) ; }
+ catch (HttpException ex) {
+ assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ;
+ }
+
+ try { askPing(name) ; }
+ catch (HttpException ex) {
+ assertEquals(HttpSC.NOT_FOUND_404, ex.getResponseCode()) ;
+ }
+ }
+
+ private static void checkJsonDatasetsAll(JsonValue v) {
+ assertNotNull(v.getAsObject().get("datasets")) ;
+ JsonArray a = v.getAsObject().get("datasets").getAsArray() ;
+ for ( JsonValue v2 : a )
+ checkJsonDatasetsOne(v2) ;
+ }
+
+ private static void checkJsonDatasetsOne(JsonValue v) {
+ assertTrue(v.isObject()) ;
+ JsonObject obj = v.getAsObject() ;
+ assertNotNull(obj.get("ds.name")) ;
+ assertNotNull(obj.get("ds.services")) ;
+ assertNotNull(obj.get("ds.state")) ;
+ assertTrue(obj.get("ds.services").isArray()) ;
+ }
+
+ private static void checkJsonStatsAll(JsonValue v) {
+ assertNotNull(v.getAsObject().get("datasets")) ;
+ JsonObject a = v.getAsObject().get("datasets").getAsObject() ;
+ for ( String dsname : a.keys() ) {
+ JsonValue obj = a.get(dsname).getAsObject() ;
+ checkJsonStatsOne(obj);
+ }
+ }
+
+ private static void checkJsonStatsOne(JsonValue v) {
+ checkJsonStatsCounters(v) ;
+ JsonObject obj1 = v.getAsObject().get("endpoints").getAsObject() ;
+ for ( String srvName : obj1.keys() ) {
+ JsonObject obj2 = obj1.get(srvName).getAsObject() ;
+ assertTrue(obj2.hasKey("description"));
+ assertTrue(obj2.hasKey("operation"));
+ checkJsonStatsCounters(obj2);
+ }
+ }
+
+ private static void checkJsonStatsCounters(JsonValue v) {
+ JsonObject obj = v.getAsObject() ;
+ assertTrue(obj.hasKey("Requests")) ;
+ assertTrue(obj.hasKey("RequestsGood")) ;
+ assertTrue(obj.hasKey("RequestsBad")) ;
+ }
+
+ private static JsonValue execGetJSON(String url) {
+ try ( TypedInputStream in = execHttpGet(url) ) {
+ assertEqualsIgnoreCase(WebContent.contentTypeJSON, in.getContentType()) ;
+ return JSON.parse(in) ;
+ }
+ }
+
+ /*
+ GET /$/ping
+ POST /$/ping
+ POST /$/datasets/
+ GET /$/datasets/
+ DELETE /$/datasets/*{name}*
+ GET /$/datasets/*{name}*
+ POST /$/datasets/*{name}*?state=offline
+ POST /$/datasets/*{name}*?state=active
+ POST /$/backup/*{name}*
+ GET /$/server
+ POST /$/server/shutdown
+ GET /$/stats/
+ GET /$/stats/*{name}*
+ */
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAuth.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAuth.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAuth.java
new file mode 100644
index 0000000..0deb01d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestAuth.java
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import java.io.File ;
+import java.io.FileWriter ;
+import java.io.IOException ;
+import java.net.URI ;
+import java.net.URISyntaxException ;
+import java.util.HashMap ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.atlas.web.HttpException ;
+import org.apache.jena.atlas.web.auth.PreemptiveBasicAuthenticator ;
+import org.apache.jena.atlas.web.auth.ScopedAuthenticator ;
+import org.apache.jena.atlas.web.auth.ServiceAuthenticator ;
+import org.apache.jena.atlas.web.auth.SimpleAuthenticator ;
+import org.junit.AfterClass ;
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.query.DatasetAccessor ;
+import com.hp.hpl.jena.query.DatasetAccessorFactory ;
+import com.hp.hpl.jena.query.QueryExecutionFactory ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ;
+import com.hp.hpl.jena.sparql.engine.http.QueryExceptionHTTP ;
+import com.hp.hpl.jena.sparql.engine.http.Service ;
+import com.hp.hpl.jena.sparql.modify.UpdateProcessRemoteBase ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.update.UpdateExecutionFactory ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+/**
+ * Tests Fuseki operation with authentication enabled
+ */
+public class TestAuth extends ServerTest {
+
+ private static File realmFile;
+
+ /**
+ * Sets up the authentication for tests
+ * @throws IOException
+ */
+ @BeforeClass
+ public static void setup() throws IOException {
+ realmFile = File.createTempFile("realm", ".properties");
+
+ try ( FileWriter writer = new FileWriter(realmFile); ) {
+ writer.write("allowed: password, fuseki\n");
+ writer.write("forbidden: password, other");
+ }
+
+ LogCtl.logLevel(Fuseki.serverLog.getName(), org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING);
+ LogCtl.logLevel(Fuseki.actionLog.getName(), org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING);
+ LogCtl.logLevel("org.eclipse.jetty", org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING);
+
+ ServerTest.setupServer(realmFile.getAbsolutePath());
+ }
+
+ /**
+ * Tears down authentication test setup
+ */
+ @AfterClass
+ public static void teardown() {
+ ServerTest.teardownServer();
+ realmFile.delete();
+ }
+
+ @Test(expected = QueryExceptionHTTP.class)
+ public void query_with_auth_01() {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ // No auth credentials should result in an error
+ qe.execAsk();
+ }
+
+ @Test(expected = QueryExceptionHTTP.class)
+ public void query_with_auth_02() {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ // Auth credentials for valid user with bad password
+ qe.setBasicAuthentication("allowed", "incorrect".toCharArray());
+ qe.execAsk();
+ }
+
+ @Test
+ public void query_with_auth_03() {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ // Auth credentials for valid user with correct password
+ qe.setBasicAuthentication("allowed", "password".toCharArray());
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test(expected = QueryExceptionHTTP.class)
+ public void query_with_auth_04() {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ // Auth credentials for valid user with correct password BUT not in
+ // correct role
+ qe.setBasicAuthentication("forbidden", "password".toCharArray());
+ qe.execAsk();
+ }
+
+ @Test
+ public void query_with_auth_05() {
+ // Uses auth and enables compression
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ qe.setAllowDeflate(true);
+ qe.setAllowGZip(true);
+
+ // Auth credentials for valid user with correct password
+ qe.setBasicAuthentication("allowed", "password".toCharArray());
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test(expected = QueryExceptionHTTP.class)
+ public void query_with_auth_06() {
+ // Uses auth and enables compression
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+ qe.setAllowDeflate(true);
+ qe.setAllowGZip(true);
+
+ // Auth credentials for valid user with bad password
+ qe.setBasicAuthentication("allowed", "incorrect".toCharArray());
+ qe.execAsk();
+ }
+
+ @Test(expected = QueryExceptionHTTP.class)
+ public void query_with_auth_07() throws URISyntaxException {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password but scoped to
+ // wrong URI
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://example"), "allowed",
+ "password".toCharArray());
+ qe.setAuthenticator(authenticator);
+ qe.execAsk();
+ }
+
+ @Test
+ public void query_with_auth_08() throws URISyntaxException {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password and scoped to
+ // correct URI
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceQuery), "allowed", "password".toCharArray());
+ qe.setAuthenticator(authenticator);
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test
+ public void query_with_auth_09() throws URISyntaxException {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password using
+ // pre-emptive auth
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceQuery), "allowed", "password".toCharArray());
+ qe.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator));
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test
+ public void query_with_auth_10() {
+ Context ctx = ARQ.getContext();
+ try {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password and scoped
+ // to correct URI
+ // Provided via Service Context and its associated authenticator
+ Map<String, Context> serviceContext = new HashMap<String, Context>();
+ Context authContext = new Context();
+ authContext.put(Service.queryAuthUser, "allowed");
+ authContext.put(Service.queryAuthPwd, "password");
+ serviceContext.put(serviceQuery, authContext);
+ ctx.put(Service.serviceContext, serviceContext);
+
+ qe.setAuthenticator(new ServiceAuthenticator());
+ Assert.assertTrue(qe.execAsk());
+ } finally {
+ ctx.remove(Service.serviceContext);
+ }
+ }
+
+ @Test
+ public void query_with_auth_11() {
+ Context ctx = ARQ.getContext();
+ try {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password and scoped
+ // to base URI of the actual service URL
+ // Provided via Service Context and its associated authenticator
+ Map<String, Context> serviceContext = new HashMap<String, Context>();
+ Context authContext = new Context();
+ authContext.put(Service.queryAuthUser, "allowed");
+ authContext.put(Service.queryAuthPwd, "password");
+ serviceContext.put(urlRoot, authContext);
+ ctx.put(Service.serviceContext, serviceContext);
+
+ qe.setAuthenticator(new ServiceAuthenticator());
+ Assert.assertTrue(qe.execAsk());
+ } finally {
+ ctx.remove(Service.serviceContext);
+ }
+ }
+
+ @Test
+ public void query_with_auth_12() {
+ ARQ.getContext().remove(Service.serviceContext);
+
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password
+ // Use service authenticator with fallback credentials.
+ qe.setAuthenticator(new ServiceAuthenticator("allowed", "password".toCharArray()));
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test
+ public void query_with_auth_13() throws URISyntaxException {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password and scoped to
+ // base URI of the actual service URL
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(urlRoot), "allowed", "password".toCharArray());
+ qe.setAuthenticator(authenticator);
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test
+ public void query_with_auth_14() throws URISyntaxException {
+ QueryEngineHTTP qe = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+ // Auth credentials for valid user with correct password and scoped to
+ // base URI of the actual service URL
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://localhost:" + port), "allowed", "password".toCharArray());
+ qe.setAuthenticator(authenticator);
+ Assert.assertTrue(qe.execAsk());
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_01() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+ // No auth credentials should result in an error
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_02() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+ // Auth credentials for valid user with bad password
+ ue.setAuthentication("allowed", "incorrect".toCharArray());
+ ue.execute();
+ }
+
+ @Test
+ public void update_with_auth_03() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+ // Auth credentials for valid user with correct password
+ ue.setAuthentication("allowed", "password".toCharArray());
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_04() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+ // Auth credentials for valid user with correct password BUT not in
+ // correct role
+ ue.setAuthentication("forbidden", "password".toCharArray());
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_05() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+ // No auth credentials should result in an error
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_06() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+ // Auth credentials for valid user with bad password
+ ue.setAuthentication("allowed", "incorrect".toCharArray());
+ ue.execute();
+ }
+
+ @Test
+ public void update_with_auth_07() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+ // Auth credentials for valid user with correct password
+ ue.setAuthentication("allowed", "password".toCharArray());
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_08() {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+ // Auth credentials for valid user with correct password BUT not in
+ // correct role
+ ue.setAuthentication("forbidden", "password".toCharArray());
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void update_with_auth_09() throws URISyntaxException {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+ // Auth credentials for valid user with correct password but scoped to
+ // wrong URI
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI("http://example"), "allowed",
+ "password".toCharArray());
+ ue.setAuthenticator(authenticator);
+ ue.execute();
+ }
+
+ @Test
+ public void update_with_auth_10() throws URISyntaxException {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+ // Auth credentials for valid user with correct password scoped to
+ // correct URI
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceUpdate), "allowed", "password".toCharArray());
+ ue.setAuthenticator(authenticator);
+ ue.execute();
+ }
+
+ @Test
+ public void update_with_auth_11() throws URISyntaxException {
+ UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH <http://graph>");
+ UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+ // Auth credentials for valid user with correct password scoped to
+ // correct URI
+ // Also using pre-emptive auth
+ ScopedAuthenticator authenticator = new ScopedAuthenticator(new URI(serviceUpdate), "allowed", "password".toCharArray());
+ ue.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator));
+ ue.execute();
+ }
+
+ @Test(expected = HttpException.class)
+ public void graphstore_with_auth_01() {
+ // No auth credentials
+ DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST);
+ accessor.getModel();
+ }
+
+ @Test(expected = HttpException.class)
+ public void graphstore_with_auth_02() {
+ // Incorrect auth credentials
+ DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new SimpleAuthenticator("allowed", "incorrect".toCharArray()));
+ accessor.getModel();
+ }
+
+ @Test
+ public void graphstore_with_auth_03() {
+ // Correct auth credentials
+ DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new SimpleAuthenticator("allowed", "password".toCharArray()));
+ Model m = accessor.getModel();
+ Assert.assertTrue(m.isEmpty());
+ }
+
+ @Test(expected = HttpException.class)
+ public void graphstore_with_auth_04() throws URISyntaxException {
+ // Correct auth credentials scoped to wrong URI
+ DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new URI("http://example.org/"), "allowed", "password".toCharArray()));
+ accessor.getModel();
+ }
+
+ @Test
+ public void graphstore_with_auth_05() throws URISyntaxException {
+ // Correct auth credentials scoped to correct URI
+ DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new URI(serviceREST), "allowed", "password".toCharArray()));
+ accessor.getModel();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java
new file mode 100644
index 0000000..a5c2fc6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestDatasetOps.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import static org.apache.jena.fuseki.ServerTest.serviceQuery ;
+import static org.apache.jena.fuseki.ServerTest.serviceREST ;
+import static org.apache.jena.fuseki.ServerTest.urlDataset ;
+
+import java.io.IOException ;
+import java.io.OutputStream ;
+
+import org.apache.http.HttpEntity ;
+import org.apache.http.entity.ContentProducer ;
+import org.apache.http.entity.EntityTemplate ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.atlas.web.HttpException ;
+import org.apache.jena.atlas.web.TypedInputStream ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFFormat ;
+import org.apache.jena.riot.WebContent ;
+import org.apache.jena.riot.system.StreamRDF ;
+import org.apache.jena.riot.system.StreamRDFLib ;
+import org.apache.jena.riot.web.HttpOp ;
+import org.apache.jena.web.HttpSC ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+/** TestDatasetAccessorHTTP does most of the GSP testing.
+ * This class adds the testing of Fuseki extras.
+ */
+public class TestDatasetOps extends AbstractFusekiTest
+{
+ static DatasetGraph data = SSE.parseDatasetGraph(StrUtils.strjoinNL
+ ("(prefix ((: <http://example/>))",
+ " (dataset",
+ " (graph (_:x :p 1) (_:x :p 2))" ,
+ " (graph :g (_:x :p 3))",
+ "))"
+ )) ;
+
+ /** Create an HttpEntity for the graph */
+ protected HttpEntity datasetToHttpEntity(final DatasetGraph dsg) {
+
+ final RDFFormat syntax = RDFFormat.NQUADS ;
+ ContentProducer producer = new ContentProducer() {
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ RDFDataMgr.write(out, dsg, syntax) ;
+ }
+ } ;
+ EntityTemplate entity = new EntityTemplate(producer) ;
+ String ct = syntax.getLang().getContentType().getContentType() ;
+ entity.setContentType(ct) ;
+ return entity ;
+ }
+
+ @Test public void gsp_x_01() {
+ gsp_x(urlDataset, urlDataset) ;
+ }
+
+ @Test public void gsp_x_02() {
+ gsp_x(urlDataset, serviceREST) ;
+ }
+
+ @Test public void gsp_x_03() {
+ gsp_x(serviceREST, urlDataset) ;
+ }
+
+ @Test public void gsp_x_04() {
+ gsp_x(serviceREST, urlDataset) ;
+ }
+
+ private void gsp_x(String outward, String inward) {
+ HttpEntity e = datasetToHttpEntity(data) ;
+ HttpOp.execHttpPut(outward, e);
+ DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+ RDFDataMgr.read(dsg, inward) ;
+// String x = HttpOp.execHttpGetString(inward, "application/n-quads") ;
+// RDFDataMgr.read(dsg, new StringReader(x), null, Lang.NQUADS) ;
+ assertEquals(2, dsg.getDefaultGraph().size()) ;
+ }
+
+ // Get dataset. Tests conneg.
+ @Test
+ public void gsp_x_10() {
+ gsp_x_ct(urlDataset, WebContent.contentTypeNQuads, WebContent.contentTypeNQuads) ;
+ }
+
+ @Test
+ public void gsp_x_11() {
+ gsp_x_ct(urlDataset, WebContent.contentTypeNQuadsAlt1, WebContent.contentTypeNQuads) ;
+ }
+
+ @Test
+ public void gsp_x_12() {
+ gsp_x_ct(urlDataset, WebContent.contentTypeTriG, WebContent.contentTypeTriG) ;
+ }
+
+ @Test
+ public void gsp_x_13() {
+ gsp_x_ct(urlDataset, WebContent.contentTypeTriGAlt1, WebContent.contentTypeTriG) ;
+ }
+
+ @Test
+ public void gsp_x_14() {
+ gsp_x_ct(urlDataset, WebContent.defaultDatasetAcceptHeader, WebContent.contentTypeTriG) ;
+ }
+
+ @Test
+ public void gsp_x_15() {
+ // Anything!
+ gsp_x_ct(urlDataset, WebContent.defaultRDFAcceptHeader, WebContent.contentTypeTriG) ;
+ }
+
+ private void gsp_x_ct(String urldataset, String acceptheader, String contentTypeResponse) {
+ HttpEntity e = datasetToHttpEntity(data) ;
+ HttpOp.execHttpPut(urlDataset, e);
+ TypedInputStream in = HttpOp.execHttpGet(urlDataset, acceptheader) ;
+ assertEqualsIgnoreCase(in.getContentType(), contentTypeResponse) ;
+ DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+ StreamRDF dest = StreamRDFLib.dataset(dsg) ;
+ RDFDataMgr.parse(dest, in) ;
+ }
+
+ @Test
+ public void gsp_x_20()
+ {
+ HttpEntity e = datasetToHttpEntity(data) ;
+ try {
+ HttpOp.execHttpPost(serviceQuery, e);
+ } catch (HttpException ex) {
+ assertTrue(HttpSC.isClientError(ex.getResponseCode())) ;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestFileUpload.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestFileUpload.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestFileUpload.java
new file mode 100644
index 0000000..4fa95d9
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestFileUpload.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import static org.apache.jena.fuseki.ServerTest.serviceREST ;
+import org.apache.jena.atlas.web.TypedInputStream ;
+import org.apache.jena.fuseki.http.TestDatasetAccessorHTTP ;
+import org.apache.jena.fuseki.http.TestHttpOp ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.web.HttpOp ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.DatasetAccessor ;
+import com.hp.hpl.jena.query.DatasetAccessorFactory ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+
+/** Additional tests for the SPARQL Graph Store protocol,
+ * mainly for HTTP file upload. See {@linkplain TestDatasetAccessorHTTP}
+ * and {@linkplain TestHttpOp} for tests that exercise direct GSp functionality
+ *
+ * @see TestDatasetAccessorHTTP
+ * @see TestHttpOp
+ */
+public class TestFileUpload extends AbstractFusekiTest
+{
+ @Test public void upload_gsp_01()
+ {
+ FileSender x = new FileSender(ServerTest.serviceREST+"?default") ;
+ x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/turtle") ;
+ x.send("POST") ;
+
+ Model m = ModelFactory.createDefaultModel() ;
+ TypedInputStream in = HttpOp.execHttpGet(serviceREST, "text/turtle") ;
+ RDFDataMgr.read(m, in, RDFLanguages.contentTypeToLang(in.getMediaType()) ) ;
+ // which is is effectively :
+// DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+// Model m = du.getModel() ;
+ assertEquals(1, m.size()) ;
+ }
+
+ @Test public void upload_gsp_02()
+ {
+ FileSender x = new FileSender(ServerTest.serviceREST+"?default") ;
+ x.add("D.ttl", "<http://example/s> <http://example/p> 123 .", "text/turtle") ;
+ x.add("D.nt", "<http://example/s> <http://example/p> <http://example/o-456> .", "application/n-triples") ;
+ x.send("PUT") ;
+
+ // BUG
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel() ;
+ assertEquals(2, m.size()) ;
+ }
+
+ // Extension of GSP - no graph selector => dataset
+ @Test public void upload_gsp_03()
+ {
+ FileSender x = new FileSender(ServerTest.serviceREST) ;
+ x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/turtle") ;
+ x.add("D.trig", "<http://example/g> { <http://example/s> <http://example/p> <http://example/o> }", "text/trig") ;
+ x.send("POST") ;
+
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel() ;
+ assertEquals(1, m.size()) ;
+ }
+
+ @Test public void upload_gsp_04()
+ {
+ {
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel() ;
+ assertEquals(0, m.size()) ;
+ }
+ FileSender x = new FileSender(ServerTest.urlDataset) ;
+ x.add("D.ttl", "<http://example/s> <http://example/p> <http://example/o> .", "text/plain") ;
+ x.add("D.trig", "<http://example/g> { <http://example/s> <http://example/p> 123,456 }", "text/plain") ;
+ x.send("POST") ;
+
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel() ;
+ assertEquals(1, m.size()) ;
+ m = du.getModel("http://example/g") ;
+ assertEquals(2, m.size()) ;
+ }
+
+ // Via DatasetAccessor
+
+ @Test public void dataset_accessor_01() {
+ FileSender x = new FileSender(ServerTest.urlDataset) ;
+ x.add("D.nq", "", "application/-n-quads") ;
+ x.send("PUT") ;
+
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel() ;
+ assertEquals(0, m.size()) ;
+ }
+
+ @Test public void dataset_accessor_02() {
+ FileSender x = new FileSender(ServerTest.urlDataset) ;
+ x.add("D.nq", "<http://example/s> <http://example/p> <http://example/o-456> <http://example/g> .", "application/n-quads") ;
+ x.send("PUT") ;
+
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ Model m = du.getModel("http://example/g") ;
+ assertEquals(1, m.size()) ;
+ m = du.getModel() ;
+ assertEquals(0, m.size()) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
new file mode 100644
index 0000000..7b021f4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+package org.apache.jena.fuseki;
+
+import java.io.IOException ;
+import java.net.HttpURLConnection ;
+import java.net.URL ;
+
+import static org.apache.jena.fuseki.ServerTest.* ;
+
+import org.junit.AfterClass ;
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import com.hp.hpl.jena.query.* ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.engine.binding.Binding ;
+import com.hp.hpl.jena.sparql.resultset.ResultSetCompare ;
+import com.hp.hpl.jena.sparql.sse.Item ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+import com.hp.hpl.jena.sparql.sse.builders.BuilderResultSet ;
+import com.hp.hpl.jena.sparql.util.Convert ;
+
+public class TestQuery extends BaseTest
+{
+ protected static ResultSet rs1 = null ;
+ static {
+ Item item = SSE.parseItem("(resultset (?s ?p ?o) (row (?s <x>)(?p <p>)(?o 1)))") ;
+ rs1 = BuilderResultSet.build(item) ;
+ }
+
+ @BeforeClass public static void beforeClass()
+ {
+ ServerTest.allocServer() ;
+ ServerTest.resetServer() ;
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ du.putModel(model1) ;
+ du.putModel(gn1, model2) ;
+ }
+
+ @AfterClass public static void afterClass()
+ {
+ DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+ du.deleteDefault() ;
+ ServerTest.freeServer() ;
+ }
+
+ @Test public void query_01()
+ {
+ execQuery("SELECT * {?s ?p ?o}", 1) ;
+ }
+
+ @Test public void query_recursive_01()
+ {
+ String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s ?p ?o . BIND(?o AS ?x) } }";
+ try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query) ) {
+ ResultSet rs = qExec.execSelect();
+ Var x = Var.alloc("x");
+ while (rs.hasNext()) {
+ Binding b = rs.nextBinding();
+ Assert.assertNotNull(b.get(x));
+ }
+ }
+ }
+
+ @Test public void query_with_params_01()
+ {
+ String query = "ASK { }";
+ try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query) ) {
+ boolean result = qExec.execAsk();
+ Assert.assertTrue(result);
+ }
+ }
+
+ @Test public void request_id_header_01() throws IOException
+ {
+ String qs = Convert.encWWWForm("ASK{}") ;
+ URL u = new URL(serviceQuery+"?query="+qs);
+ HttpURLConnection conn = (HttpURLConnection) u.openConnection();
+ Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null);
+ }
+
+ private void execQuery(String queryString, int exceptedRowCount)
+ {
+ QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ;
+ ResultSet rs = qExec.execSelect() ;
+ int x = ResultSetFormatter.consume(rs) ;
+ assertEquals(exceptedRowCount, x) ;
+ }
+
+ private void execQuery(String queryString, ResultSet expectedResultSet)
+ {
+ QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ;
+ ResultSet rs = qExec.execSelect() ;
+ boolean b = ResultSetCompare.equalsByTerm(rs, expectedResultSet) ;
+ assertTrue("Result sets different", b) ;
+ }
+}