Merge pull request #649 from afs/fuseki-1794
JENA-1794: Look for rdf:type fuseki:Service if duplicate fuseki:name
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
index 1225718..3d5e3b8 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -27,11 +27,7 @@
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
@@ -66,11 +62,7 @@
import org.apache.jena.query.Dataset;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.rdf.model.*;
-import org.apache.jena.riot.Lang;
-import org.apache.jena.riot.RDFDataMgr;
-import org.apache.jena.riot.RDFLanguages;
-import org.apache.jena.riot.RDFParser;
-import org.apache.jena.riot.WebContent;
+import org.apache.jena.riot.*;
import org.apache.jena.riot.system.StreamRDF;
import org.apache.jena.riot.system.StreamRDFLib;
import org.apache.jena.shared.uuid.JenaUUID;
@@ -82,6 +74,7 @@
import org.apache.jena.update.UpdateAction;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;
+import org.apache.jena.vocabulary.RDF;
import org.apache.jena.web.HttpSC;
public class ActionDatasets extends ActionContainerItem {
@@ -169,21 +162,10 @@
RDFDataMgr.write(outCopy, model, Lang.TURTLE);
}
// ----
-
// Process configuration.
- Statement stmt = getOne(model, null, pServiceName, null);
- if ( stmt == null ) {
- StmtIterator sIter = model.listStatements(null, pServiceName, (RDFNode)null );
- if ( ! sIter.hasNext() )
- ServletOps.errorBadRequest("No name given in description of Fuseki service");
- sIter.next();
- if ( sIter.hasNext() )
- ServletOps.errorBadRequest("Multiple names given in description of Fuseki service");
- throw new InternalErrorException("Inconsistent: getOne didn't fail the second time");
- }
- if ( ! stmt.getObject().isLiteral() )
- ServletOps.errorBadRequest("Found "+FmtUtils.stringForRDFNode(stmt.getObject())+" : Service names are strings, then used to build the external URI");
+ // Returns the "service fu:name NAME" statement
+ Statement stmt = findService(model);
Resource subject = stmt.getSubject();
Literal object = stmt.getObject().asLiteral();
@@ -255,6 +237,45 @@
return null;
}
+ /** Find the service resource. There must be only one in the configuration. */
+ private Statement findService(Model model) {
+ // Try to find by unique pServiceName (max backwards compatibility)
+ // then try to find by rdf:type fuseki:Service.
+
+ // JENA-1794
+ Statement stmt = getOne(model, null, pServiceName, null);
+ // null means 0 or many, not one.
+
+ if ( stmt == null ) {
+ // This calculates { ?x rdf:type fu:Service ; ?x fu:name ?name }
+ // One and only one service.
+ Statement stmt2 = getOne(model, null, RDF.type, FusekiVocab.fusekiService);
+ if ( stmt2 == null ) {
+ int count = model.listStatements(null, RDF.type, FusekiVocab.fusekiService).toList().size();
+ if ( count == 0 )
+ ServletOps.errorBadRequest("No triple rdf:type fuseki:Service found");
+ else
+ ServletOps.errorBadRequest("Multiple Fuseki service descriptions");
+ }
+ Statement stmt3 = getOne(model, stmt2.getSubject(), pServiceName, null);
+ if ( stmt3 == null ) {
+ StmtIterator sIter = model.listStatements(stmt2.getSubject(), pServiceName, (RDFNode)null );
+ if ( ! sIter.hasNext() )
+ ServletOps.errorBadRequest("No name given in description of Fuseki service");
+ sIter.next();
+ if ( sIter.hasNext() )
+ ServletOps.errorBadRequest("Multiple names given in description of Fuseki service");
+ throw new InternalErrorException("Inconsistent: getOne didn't fail the second time");
+ }
+ stmt = stmt3;
+ }
+
+ if ( ! stmt.getObject().isLiteral() )
+ ServletOps.errorBadRequest("Found "+FmtUtils.stringForRDFNode(stmt.getObject())+" : Service names are strings, then used to build the external URI");
+
+ return stmt;
+ }
+
@Override
protected JsonValue execPostItem(HttpAction action) {
String name = getItemDatasetName(action);
@@ -312,7 +333,7 @@
String name = getItemDatasetName(action);
if ( name == null )
name = "";
- action.log.info(format("[%d] DELETE ds=%s", action.id, name));
+ action.log.info(format("[%d] DELETE dataset=%s", action.id, name));
if ( ! action.getDataAccessPointRegistry().isRegistered(name) )
ServletOps.errorNotFound("No such dataset registered: "+name);
diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java
index e29f90d..7516fa6 100644
--- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java
+++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java
@@ -55,7 +55,7 @@
public class TestAdmin extends AbstractFusekiTest {
// Name of the dataset in the assembler file.
- static String dsTest = "test-ds2";
+ static String dsTest = "test-ds1";
static String dsTestInf = "test-ds4";
static String fileBase = "testing/";
@@ -133,7 +133,7 @@
@Test public void add_delete_dataset_2() {
checkNotThere(dsTest);
- File f = new File(fileBase+"config-ds-plain.ttl");
+ File f = new File(fileBase+"config-ds-plain-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);
@@ -153,7 +153,7 @@
deleteDataset(dsTest);
}
- @Test public void add_delete_dataset_3() throws Exception {
+ @Test public void add_delete_dataset_3() {
checkNotThere(dsTest);
addTestDataset();
checkExists(dsTest);
@@ -164,7 +164,7 @@
deleteDataset(dsTest);
}
- @Test public void add_delete_dataset_4() throws Exception {
+ @Test public void add_delete_dataset_4() {
checkNotThere(dsTest);
checkNotThere(dsTestInf);
addTestDatasetInf();
@@ -178,6 +178,12 @@
deleteDataset(dsTestInf);
}
+ @Test public void add_delete_dataset_5() {
+ // New style operations : cause two fuseki:names
+ addTestDataset(fileBase+"config-ds-plain-2.ttl");
+ checkExists("test-ds2");
+ }
+
@Test public void add_error_1() {
FusekiTest.execWithHttpException(HttpSC.BAD_REQUEST_400,
()-> addTestDataset(fileBase+"config-ds-bad-name-1.ttl"));
@@ -354,7 +360,7 @@
// -- Add
private static void addTestDataset() {
- addTestDataset(fileBase+"config-ds-plain.ttl");
+ addTestDataset(fileBase+"config-ds-plain-1.ttl");
}
private static void addTestDatasetInf() {
diff --git a/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain.ttl b/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-1.ttl
similarity index 72%
rename from jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain.ttl
rename to jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-1.ttl
index aba5d82..f993f35 100644
--- a/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain.ttl
+++ b/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-1.ttl
@@ -1,3 +1,5 @@
+## 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#>
@@ -5,9 +7,9 @@
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-<#service1> rdf:type fuseki:Service ;
+<#service1> #rdf:type fuseki:Service ;
# URI of the dataset -- http://host:port/ds
- fuseki:name "test-ds2" ;
+ fuseki:name "test-ds1" ;
fuseki:serviceQuery "sparql" ;
fuseki:dataset <#emptyDataset> ;
.
diff --git a/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-2.ttl b/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-2.ttl
new file mode 100644
index 0000000..d4b3fc9
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-webapp/testing/config-ds-plain-2.ttl
@@ -0,0 +1,18 @@
+## 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 ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+
+<#service1> rdf:type fuseki:Service ;
+ fuseki:name "test-ds2" ;
+ fuseki:endpoint [
+ fuseki:operation fuseki:query ;
+ fuseki:name "sparql"
+ ] ;
+ fuseki:dataset <#emptyDataset> ;
+ .
+
+<#emptyDataset> rdf:type ja:MemoryDataset .