JENA-1795: HEAD for GSP operations
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
index efef1f3..606ab0f 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/GSP_R.java
@@ -33,9 +33,9 @@
import org.apache.jena.sparql.core.DatasetGraph;
public class GSP_R extends GSP_Base {
-
+
public GSP_R() {}
-
+
@Override
protected void doGet(HttpAction action) {
if ( isQuads(action) )
@@ -45,6 +45,7 @@
}
protected void execGetQuads(HttpAction action) {
+ ActionLib.setCommonHeaders(action.response);
MediaType mediaType = ActionLib.contentNegotationQuads(action);
ServletOutputStream output;
try { output = action.response.getOutputStream(); }
@@ -85,6 +86,7 @@
}
protected void execGetGSP(HttpAction action) {
+ ActionLib.setCommonHeaders(action.response);
MediaType mediaType = ActionLib.contentNegotationRDF(action);
ServletOutputStream output;
@@ -98,7 +100,6 @@
if ( action.verbose )
action.log.info(format("[%d] Get: Content-Type=%s, Charset=%s => %s",
action.id, mediaType.getContentType(), mediaType.getCharset(), lang.getName()));
- ActionLib.setCommonHeaders(action.response);
try {
DatasetGraph dsg = decideDataset(action);
GSPTarget target = determineTarget(dsg, action);
@@ -141,23 +142,37 @@
@Override
protected void doHead(HttpAction action) {
- action.beginRead();
+ if ( isQuads(action) )
+ execHeadQuads(action);
+ else
+ execHeadGSP(action);
+ }
+
+ protected void execHeadQuads(HttpAction action) {
ActionLib.setCommonHeaders(action.response);
+ MediaType mediaType = ActionLib.contentNegotationQuads(action);
+ if ( action.verbose )
+ action.log.info(format("[%d] Head: Content-Type=%s", action.id, mediaType.getContentType()));
+ ServletOps.success(action);
+ }
+
+ protected void execHeadGSP(HttpAction action) {
+ ActionLib.setCommonHeaders(action.response);
+ MediaType mediaType = ActionLib.contentNegotationRDF(action);
+ if ( action.verbose )
+ action.log.info(format("[%d] Head: Content-Type=%s", action.id, mediaType.getContentType()));
+ // Check graph not 404.
+ action.beginRead();
try {
DatasetGraph dsg = decideDataset(action);
GSPTarget target = determineTarget(dsg, action);
if ( action.log.isDebugEnabled() )
- action.log.debug("HEAD->" + target);
- if ( !target.exists() ) {
- ServletOps.successNotFound(action);
- return;
- }
- MediaType mediaType = ActionLib.contentNegotationRDF(action);
+ action.log.debug("HEAD->"+target);
+ boolean exists = target.exists();
+ if ( ! exists )
+ ServletOps.errorNotFound("No such graph: <"+target.name+">");
ServletOps.success(action);
- }
- finally {
- action.endRead();
- }
+ } finally { action.endRead(); }
}
@Override
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java
new file mode 100644
index 0000000..cceb07d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestHTTP.java
@@ -0,0 +1,161 @@
+/*
+ * 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.main;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.atlas.web.WebLib;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.web.HttpNames;
+import org.apache.jena.riot.web.HttpOp;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
+import org.apache.jena.sparql.sse.SSE;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Test HTTP level details */
+public class TestHTTP {
+ private static FusekiServer server = null;
+ private static int port;
+
+ private static Model data;
+ private static Dataset dataset;
+
+ private static String URL;
+
+ @BeforeClass
+ public static void beforeClass() {
+ port = WebLib.choosePort();
+ URL = "http://localhost:" + port + "/ds";
+ Graph graph = SSE.parseGraph(StrUtils.strjoinNL
+ ("(graph"
+ ," (:s :p 1)"
+ ,")"));
+ data = ModelFactory.createModelForGraph(graph);
+
+ DatasetGraph dsgData = DatasetGraphFactory.create();
+ dsgData.add(SSE.parseQuad("(:g :s :p 2 )"));
+ dataset = DatasetFactory.wrap(dsgData);
+
+ DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
+
+ FusekiServer server = FusekiServer.create()
+ .add("/ds", dsg)
+ .port(port)
+ .build();
+ server.start();
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ if ( server != null )
+ server.stop();
+ }
+
+ // GET
+
+ @Test public void gspGet_dataset_1() {
+ // Base URL, default content type => N-Quads (dump format)
+ HttpOp.execHttpGet(URL, null, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(Lang.NQUADS.getHeaderString(), h);
+ });
+ }
+
+
+ @Test public void gspGet_dataset_2() {
+ String ct = Lang.TRIG.getHeaderString();
+ HttpOp.execHttpGet(URL, ct, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(ct, h);
+ });
+ }
+
+ @Test public void gspGet_graph_1() {
+ String target = URL+"?default";
+ HttpOp.execHttpGet(target, null, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ // "Traditional default".
+ assertEquals(Lang.RDFXML.getHeaderString(), h);
+ });
+ }
+
+ @Test public void gspGet_graph_2() {
+ String target = URL+"?default";
+ String ct = Lang.TTL.getHeaderString();
+ HttpOp.execHttpGet(target, ct, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(ct, h);
+ });
+ }
+
+ // HEAD
+
+ @Test public void gspHead_dataset_1() {
+ // Base URL, default content type => N-Quads (dump format)
+ HttpOp.execHttpHead(URL, null, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(Lang.NQUADS.getHeaderString(), h);
+ });
+ }
+
+
+ @Test public void gspHead_dataset_2() {
+ String ct = Lang.TRIG.getHeaderString();
+ HttpOp.execHttpHead(URL, ct, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(ct, h);
+ });
+ }
+
+ @Test public void gspHead_graph_1() {
+ String target = URL+"?default";
+ HttpOp.execHttpHead(target, null, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ // "Traditional default".
+ assertEquals(Lang.RDFXML.getHeaderString(), h);
+ });
+ }
+
+ @Test public void gspHead_graph_2() {
+ String target = URL+"?default";
+ String ct = Lang.TTL.getHeaderString();
+ HttpOp.execHttpHead(target, ct, (base, response)->{
+ String h = response.getFirstHeader(HttpNames.hContentType).getValue();
+ assertNotNull(h);
+ assertEquals(ct, h);
+ });
+ }
+}