Skip to content

Commit 396c174

Browse files
karolina-telicentafs
authored andcommitted
apacheGH-2538: prefixes-service incorporated into Jena
1 parent 1fb4c11 commit 396c174

28 files changed

+2575
-8
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
2+
3+
PREFIX : <#>
4+
PREFIX fuseki: <http://jena.apache.org/fuseki#>
5+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
6+
PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
7+
PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
8+
9+
10+
:service rdf:type fuseki:Service ;
11+
fuseki:name "dataset" ;
12+
fuseki:endpoint [ fuseki:operation fuseki:query ; ] ;
13+
fuseki:endpoint [ fuseki:operation fuseki:update ; ] ;
14+
15+
fuseki:endpoint [ fuseki:operation fuseki:prefixes-r ; fuseki:name "prefixes" ] ;
16+
fuseki:endpoint [ fuseki:operation fuseki:prefixes-ws ; fuseki:name "updatePrefixes" ] ;
17+
fuseki:dataset :dataset ;
18+
.
19+
20+
:dataset rdf:type ja:MemoryDataset ;
21+
ja:data "example-data.trig";
22+
.

jena-fuseki2/jena-fuseki-core/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@
103103
<scope>test</scope>
104104
</dependency>
105105

106+
<dependency>
107+
<groupId>org.junit.jupiter</groupId>
108+
<artifactId>junit-jupiter</artifactId>
109+
<scope>test</scope>
110+
</dependency>
111+
106112
<!-- micrometer -->
107113
<dependency>
108114
<groupId>io.micrometer</groupId>

jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public class FusekiVocab
8989
public static final Resource opShacl = resource("shacl");
9090
public static final Resource opPatch = resource("patch");
9191

92+
public static final Resource opPREFIXES_R = resource("prefixes-r");
93+
public static final Resource opPREFIXES_RW = resource("prefixes-ws");
94+
9295
// Internal
9396
private static final String stateNameActive = DataServiceStatus.ACTIVE.name;
9497
private static final String stateNameOffline = DataServiceStatus.OFFLINE.name;

jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ static private Operation create(Node id, String shortName, String description) {
8787
public static final Operation Patch = alloc(FusekiVocab.opPatch.asNode(), "patch", "RDF Patch");
8888

8989
public static final Operation NoOp = alloc(FusekiVocab.opNoOp.asNode(), "no-op", "No Op");
90+
91+
public static final Operation PREFIXES_R = alloc(FusekiVocab.opPREFIXES_R.asNode(), "prefixes-r", "Read prefixes");
92+
public static final Operation PREFIXES_RW = alloc(FusekiVocab.opPREFIXES_RW.asNode(), "prefixes-ws", "Read-write prefixes");
93+
94+
9095
static {
9196
// Not everyone will remember "_" vs "-" so ...
9297
altName(FusekiVocab.opNoOp_alt, FusekiVocab.opNoOp);
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.jena.fuseki.servlets;
20+
21+
import com.google.gson.JsonArray;
22+
import org.apache.jena.atlas.logging.FmtLog;
23+
import org.apache.jena.riot.WebContent;
24+
import org.apache.jena.riot.web.HttpNames;
25+
26+
import org.apache.jena.fuseki.servlets.prefixes.ActionPrefixesBase;
27+
import org.apache.jena.fuseki.servlets.prefixes.PrefixUtils;
28+
import org.apache.jena.fuseki.servlets.prefixes.JsonObject;
29+
30+
import java.io.IOException;
31+
import java.util.List;
32+
import java.util.Map;
33+
import java.util.Optional;
34+
35+
public class ActionPrefixesR extends ActionPrefixesBase {
36+
37+
private static final String NO_PREFIX_NS = "";
38+
39+
public ActionPrefixesR() {}
40+
41+
@Override
42+
protected void doOptions(HttpAction action) {
43+
ActionLib.setCommonHeadersForOptions(action);
44+
action.setResponseHeader(HttpNames.hAllow, "GET,OPTIONS");
45+
ServletOps.success(action);
46+
}
47+
48+
public void validateGet(HttpAction action) {
49+
validate(action);
50+
// check if the combination of parameters is legal
51+
String prefix = action.getRequestParameter(PrefixUtils.PREFIX);
52+
String uri = action.getRequestParameter(PrefixUtils.URI);
53+
if(prefix != null && uri != null) {
54+
ServletOps.errorBadRequest("Provide only one of the prefix or uri parameters!");
55+
return;
56+
}
57+
}
58+
59+
enum ResponseTypes {
60+
GET_ALL,
61+
FETCH_URI,
62+
FETCH_PREFIX,
63+
BAD_REQUEST
64+
}
65+
66+
protected ResponseTypes chooseResponseType (String prefix, String uri) {
67+
if (prefix == null && uri == null)
68+
return ResponseTypes.GET_ALL;
69+
else if (prefix != null && uri == null) {
70+
if (prefix.isEmpty()) {
71+
ServletOps.errorBadRequest("Empty prefix!");
72+
return ResponseTypes.BAD_REQUEST;
73+
}
74+
else if (!PrefixUtils.prefixIsValid(prefix)) {
75+
ServletOps.errorBadRequest("Prefix contains illegal characters!");
76+
return ResponseTypes.BAD_REQUEST;
77+
}
78+
else
79+
return ResponseTypes.FETCH_URI;
80+
}
81+
else if (prefix == null && uri != null) {
82+
if (uri.isEmpty()) {
83+
ServletOps.errorBadRequest("Empty URI!");
84+
return ResponseTypes.BAD_REQUEST;
85+
}
86+
else if (!PrefixUtils.uriIsValid(uri)) {
87+
ServletOps.errorBadRequest("URI contains illegal characters!");
88+
return ResponseTypes.BAD_REQUEST;
89+
}
90+
else
91+
return ResponseTypes.FETCH_PREFIX;
92+
}
93+
return ResponseTypes.BAD_REQUEST;
94+
}
95+
96+
@Override
97+
protected void doGet(HttpAction action) {
98+
ActionLib.setCommonHeaders(action);
99+
validateGet(action);
100+
101+
action.beginRead();
102+
try {
103+
// Not null (valid request)
104+
String prefix = action.getRequestParameter(PrefixUtils.PREFIX);
105+
String uri = action.getRequestParameter(PrefixUtils.URI);
106+
107+
switch(chooseResponseType(prefix, uri)) {
108+
case GET_ALL -> {
109+
Map<String, String> allPairs = prefixes(action).getAll();
110+
JsonArray allJsonPairs = new JsonArray();
111+
allPairs.entrySet().stream()
112+
.forEach(entry -> {
113+
com.google.gson.JsonObject jsonObject = new com.google.gson.JsonObject();
114+
jsonObject.addProperty(PrefixUtils.PREFIX, entry.getKey());
115+
jsonObject.addProperty(PrefixUtils.URI, entry.getValue());
116+
allJsonPairs.add(jsonObject);
117+
FmtLog.info(action.log, "[%d] - %s", action.id, new JsonObject(entry.getKey(), entry.getValue()));
118+
});
119+
action.setResponseContentType(WebContent.contentTypeJSON);
120+
action.getResponseOutputStream().print(String.valueOf(allJsonPairs));
121+
122+
ServletOps.success(action);
123+
action.endRead();
124+
return;
125+
}
126+
case FETCH_URI -> {
127+
Optional<String> x = prefixes(action).fetchURI(prefix);
128+
String namespace = x.orElse(NO_PREFIX_NS);
129+
130+
JsonObject jsonObject = new JsonObject(prefix, namespace);
131+
132+
// Build the response.
133+
action.setResponseContentType(WebContent.contentTypeJSON);
134+
action.getResponseOutputStream().print(namespace);
135+
// Indicate success
136+
FmtLog.info(action.log, "[%d] %s -> %s", action.id, prefix, jsonObject.toString());
137+
action.commit();
138+
ServletOps.success(action);
139+
return;
140+
}
141+
case FETCH_PREFIX -> {
142+
List<String> prefixList =prefixes(action).fetchPrefix(uri);
143+
JsonArray prefixJsonArray = new JsonArray();
144+
for (String p : prefixList) {
145+
com.google.gson.JsonObject jsonObject2 = new com.google.gson.JsonObject();
146+
jsonObject2.addProperty(PrefixUtils.PREFIX, p);
147+
jsonObject2.addProperty(PrefixUtils.URI, uri);
148+
prefixJsonArray.add(jsonObject2);
149+
FmtLog.info(action.log, "[%d] - %s", action.id, new JsonObject(p, uri));
150+
}
151+
// Build the response.
152+
action.setResponseContentType(WebContent.contentTypeJSON);
153+
action.getResponseOutputStream().print(String.valueOf(prefixJsonArray));
154+
// Indicate success
155+
action.commit();
156+
ServletOps.success(action);
157+
action.endRead();
158+
return;
159+
}
160+
default -> {
161+
ServletOps.errorBadRequest("Bad request");
162+
return;
163+
}
164+
}
165+
} catch (RuntimeException | IOException ex) {
166+
try { action.abort(); }
167+
catch (Throwable th ) {
168+
FmtLog.warn(action.log, th, "[%d] GET prefix = %s", action.id);
169+
}
170+
ServletOps.errorOccurred(ex);
171+
} finally {
172+
action.endRead();
173+
}
174+
}
175+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.jena.fuseki.servlets;
20+
21+
import org.apache.jena.atlas.logging.FmtLog;
22+
import org.apache.jena.riot.WebContent;
23+
import org.apache.jena.riot.web.HttpNames;
24+
25+
import org.apache.jena.fuseki.servlets.prefixes.PrefixUtils;
26+
27+
import java.io.IOException;
28+
29+
public class ActionPrefixesRW extends ActionPrefixesR {
30+
31+
public ActionPrefixesRW() {}
32+
33+
@Override
34+
protected void doOptions(HttpAction action) {
35+
ActionLib.setCommonHeadersForOptions(action);
36+
action.setResponseHeader(HttpNames.hAllow, "GET,OPTIONS,POST,DELETE");
37+
ServletOps.success(action);
38+
}
39+
40+
public void validateDelete(HttpAction action) {
41+
validate(action);
42+
String prefixToRemove = action.getRequestParameter(PrefixUtils.PREFIX);
43+
if (prefixToRemove == null || prefixToRemove.isEmpty() || !PrefixUtils.prefixIsValid(prefixToRemove)) {
44+
ServletOps.errorBadRequest("Remove operation unsuccessful!");
45+
return;
46+
}
47+
}
48+
49+
@Override
50+
protected void doDelete(HttpAction action) {
51+
validateDelete(action);
52+
action.beginWrite();
53+
54+
try {
55+
String prefixToRemove = action.getRequestParameter(PrefixUtils.PREFIX);
56+
prefixes(action).removePrefix(prefixToRemove);
57+
FmtLog.info(action.log, "[%d] Remove %s:", action.id, prefixToRemove);
58+
59+
action.commit();
60+
61+
// Indicate success
62+
ServletOps.success(action);
63+
64+
// Build the response.
65+
action.setResponseContentType(WebContent.contentTypeJSON);
66+
action.getResponseOutputStream().print("");
67+
68+
} catch (RuntimeException | IOException ex) {
69+
try { action.abort(); }
70+
catch (Throwable th ) {
71+
FmtLog.warn(action.log, th, "[%d] POST prefix = %s", action.id);
72+
}
73+
ServletOps.errorOccurred(ex);
74+
} finally {
75+
action.end();
76+
}
77+
}
78+
79+
80+
public void validatePost(HttpAction action) {
81+
validate(action);
82+
String prefix = action.getRequestParameter(PrefixUtils.PREFIX);
83+
String uri = action.getRequestParameter(PrefixUtils.URI);
84+
85+
if (prefix.isEmpty() || uri.isEmpty()) {
86+
ServletOps.errorBadRequest("Empty operation - unsuccessful!");
87+
return;
88+
}
89+
else if (!PrefixUtils.prefixIsValid(prefix) || !PrefixUtils.uriIsValid(uri)) {
90+
ServletOps.errorBadRequest("Empty operation - unsuccessful!");
91+
return;
92+
}
93+
}
94+
95+
@Override
96+
protected void doPost(HttpAction action) {
97+
validatePost(action);
98+
action.beginWrite();
99+
100+
try {
101+
String prefix = action.getRequestParameter(PrefixUtils.PREFIX);
102+
String uri = action.getRequestParameter(PrefixUtils.URI);
103+
104+
prefixes(action).updatePrefix(prefix, uri);
105+
FmtLog.info(action.log, "[%d] Set %s: <%s>", action.id, prefix, uri);
106+
107+
action.commit();
108+
109+
// Indicate success
110+
ServletOps.success(action);
111+
112+
// Build the response.
113+
action.setResponseContentType(WebContent.contentTypeJSON);
114+
action.getResponseOutputStream().print("");
115+
116+
} catch (RuntimeException | IOException ex) {
117+
try { action.abort(); }
118+
catch (Throwable th ) {
119+
FmtLog.warn(action.log, th, "[%d] POST prefix = %s", action.id);
120+
}
121+
ServletOps.errorOccurred(ex);
122+
} finally {
123+
action.end();
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)