You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2013/08/17 11:57:06 UTC
svn commit: r1514974 - in
/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki:
FusekiLib.java servlets/SPARQL_Query.java servlets/SPARQL_REST.java
servlets/SPARQL_REST_RW.java servlets/SPARQL_Update.java
servlets/SPARQL_Upload.java
Author: andy
Date: Sat Aug 17 09:57:06 2013
New Revision: 1514974
URL: http://svn.apache.org/r1514974
Log:
JENA-516
Clean up Graph Store Protocol PUT and POST with streaming transactions.
Structure upload better - this not streaming due to limitations of HTTP;
the graph name can come after the data in the multi-part body.
Modified:
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java
jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java Sat Aug 17 09:57:06 2013
@@ -24,7 +24,10 @@ import javax.servlet.http.HttpServletReq
import org.apache.commons.lang.StringUtils ;
import org.apache.jena.atlas.lib.MultiMap ;
-import org.apache.jena.atlas.web.MediaType ;
+import org.apache.jena.atlas.web.ContentType ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.WebContent ;
import com.hp.hpl.jena.graph.Graph ;
import com.hp.hpl.jena.graph.Node ;
@@ -34,64 +37,76 @@ import com.hp.hpl.jena.sparql.core.Datas
import com.hp.hpl.jena.sparql.core.Quad ;
import com.hp.hpl.jena.sparql.util.Convert ;
-public class FusekiLib
-{
- public static MediaType contentType(HttpServletRequest request)
- {
- String x = request.getHeader(HttpNames.hContentType) ;
- if ( x == null )
+public class FusekiLib {
+ /** Get the content type of an action or return the default.
+ * @param action
+ * @return ContentType
+ */
+ public static ContentType getContentType(HttpAction action) {
+ return getContentType(action.request) ;
+ }
+
+ /** Get the content type of an action or return the default.
+ * @param request
+ * @return ContentType
+ */
+ public static ContentType getContentType(HttpServletRequest request) {
+ String contentTypeHeader = request.getContentType() ;
+ if ( contentTypeHeader == null )
return null ;
- return MediaType.create(x) ;
+ return ContentType.create(contentTypeHeader) ;
+ }
+
+ /** Get the incoming Lang based on Content-Type of an action.
+ * @param action
+ * @param dft Default if no "Content-Type:" found.
+ * @return ContentType
+ */
+ public static Lang getLangFromAction(HttpAction action, Lang dft) {
+ String contentTypeHeader = action.request.getContentType() ;
+ if ( contentTypeHeader == null )
+ return dft ;
+ return WebContent.contentTypeToLang(contentTypeHeader) ;
}
- static String fmtRequest(HttpServletRequest request)
- {
+ static String fmtRequest(HttpServletRequest request) {
StringBuffer sbuff = new StringBuffer() ;
sbuff.append(request.getMethod()) ;
sbuff.append(" ") ;
- sbuff.append(Convert.decWWWForm(request.getRequestURL()));
-
- String qs = request.getQueryString();
- if (qs != null)
- {
+ sbuff.append(Convert.decWWWForm(request.getRequestURL())) ;
+
+ String qs = request.getQueryString() ;
+ if ( qs != null ) {
String tmp = request.getQueryString() ;
tmp = Convert.decWWWForm(tmp) ;
tmp = tmp.replace('\n', ' ') ;
tmp = tmp.replace('\r', ' ') ;
- sbuff.append("?").append(tmp);
+ sbuff.append("?").append(tmp) ;
}
return sbuff.toString() ;
}
- /** Parse the query string - do not process the body even for a form */
- public static MultiMap<String, String> parseQueryString(HttpServletRequest req)
- {
+ /** Parse the query string - do not process the body even for a form */
+ public static MultiMap<String, String> parseQueryString(HttpServletRequest req) {
MultiMap<String, String> map = MultiMap.createMapList() ;
-
+
// Don't use ServletRequest.getParameter or getParamterNames
- // as that reads form data. This code parses just the query string.
- if ( req.getQueryString() != null )
- {
+ // as that reads form data. This code parses just the query string.
+ if ( req.getQueryString() != null ) {
String[] params = req.getQueryString().split("&") ;
- for ( int i = 0 ; i < params.length ; i++ )
- {
+ for (int i = 0; i < params.length; i++) {
String p = params[i] ;
- String[] x = p.split("=",2) ;
+ String[] x = p.split("=", 2) ;
String name = null ;
String value = null ;
-
- if ( x.length == 0 )
- { // No "="
+
+ if ( x.length == 0 ) { // No "="
name = p ;
value = "" ;
- }
- else if ( x.length == 1 )
- { // param=
+ } else if ( x.length == 1 ) { // param=
name = x[0] ;
value = "" ;
- }
- else
- { // param=value
+ } else { // param=value
name = x[0] ;
value = x[1] ;
}
@@ -101,29 +116,26 @@ public class FusekiLib
return map ;
}
- public static String safeParameter(HttpServletRequest request, String pName)
- {
+ public static String safeParameter(HttpServletRequest request, String pName) {
String value = request.getParameter(pName) ;
value = StringUtils.replaceChars(value, "\r", "") ;
value = StringUtils.replaceChars(value, "\n", "") ;
- return value ;
+ return value ;
}
-
+
// Do the addition directly on the dataset
- public static void addDataInto(Graph data, DatasetGraph dsg, Node graphName)
- {
- //Prefixes?
+ public static void addDataInto(Graph data, DatasetGraph dsg, Node graphName) {
+ // Prefixes?
if ( graphName == null )
graphName = Quad.defaultGraphNodeGenerated ;
-
+
Iterator<Triple> iter = data.find(Node.ANY, Node.ANY, Node.ANY) ;
- for ( ; iter.hasNext() ; )
- {
- Triple t = iter.next();
+ for (; iter.hasNext();) {
+ Triple t = iter.next() ;
dsg.add(graphName, t.getSubject(), t.getPredicate(), t.getObject()) ;
}
-
- PrefixMapping pmapSrc = data.getPrefixMapping() ;
+
+ PrefixMapping pmapSrc = data.getPrefixMapping() ;
PrefixMapping pmapDest = dsg.getDefaultGraph().getPrefixMapping() ;
pmapDest.withDefaultMappings(pmapSrc) ;
}
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Query.java Sat Aug 17 09:57:06 2013
@@ -20,6 +20,9 @@ package org.apache.jena.fuseki.servlets;
import static java.lang.String.format ;
import static org.apache.jena.fuseki.HttpNames.* ;
+import static org.apache.jena.fuseki.server.CounterName.QueryExecErrors ;
+import static org.apache.jena.fuseki.server.CounterName.QueryTimeouts ;
+import static org.apache.jena.fuseki.server.CounterName.RequestsBad ;
import java.io.IOException ;
import java.io.InputStream ;
@@ -30,11 +33,10 @@ import javax.servlet.http.HttpServletRes
import org.apache.jena.atlas.io.IO ;
import org.apache.jena.atlas.io.IndentedLineBuffer ;
-import org.apache.jena.atlas.web.MediaType ;
+import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.FusekiException ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.HttpNames ;
-import static org.apache.jena.fuseki.server.CounterName.* ;
import org.apache.jena.riot.WebContent ;
import org.apache.jena.riot.web.HttpOp ;
import org.apache.jena.web.HttpSC ;
@@ -79,7 +81,7 @@ public abstract class SPARQL_Query exten
return ;
}
- MediaType ct = FusekiLib.contentType(action.request) ;
+ ContentType ct = FusekiLib.getContentType(action) ;
String incoming = ct.getContentType() ;
// POST application/sparql-query
@@ -141,7 +143,7 @@ public abstract class SPARQL_Query exten
/** Helper for validating request */
protected void validateParams(HttpServletRequest request, Collection<String> params)
{
- MediaType ct = FusekiLib.contentType(request) ;
+ ContentType ct = FusekiLib.getContentType(request) ;
boolean mustHaveQueryParam = true ;
if ( ct != null )
{
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java Sat Aug 17 09:57:06 2013
@@ -18,10 +18,8 @@
package org.apache.jena.fuseki.servlets;
-import static java.lang.String.format ;
import static org.apache.jena.fuseki.HttpNames.* ;
-import java.io.ByteArrayInputStream ;
import java.io.IOException ;
import java.io.InputStream ;
import java.util.Enumeration ;
@@ -31,16 +29,16 @@ import javax.servlet.ServletException ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
-import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.HttpNames ;
import org.apache.jena.fuseki.server.CounterName ;
import org.apache.jena.riot.Lang ;
import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.RiotReader ;
-import org.apache.jena.riot.WebContent ;
import org.apache.jena.riot.lang.LangRIOT ;
-import org.apache.jena.riot.system.* ;
-import org.apache.jena.web.HttpSC ;
+import org.apache.jena.riot.system.ErrorHandler ;
+import org.apache.jena.riot.system.ErrorHandlerFactory ;
+import org.apache.jena.riot.system.IRIResolver ;
+import org.apache.jena.riot.system.StreamRDF ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@@ -48,9 +46,6 @@ 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.sparql.core.DatasetGraph ;
-import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
-import com.hp.hpl.jena.sparql.graph.GraphFactory ;
-import com.hp.hpl.jena.util.FileUtils ;
public abstract class SPARQL_REST extends SPARQL_ServletBase
{
@@ -293,88 +288,19 @@ public abstract class SPARQL_REST extend
protected abstract void doDelete(HttpAction action) ;
protected abstract void doPut(HttpAction action) ;
protected abstract void doOptions(HttpAction action) ;
-
- // @@ Check and use more.
- protected static ContentType getContentType(HttpAction action) {
- String contentTypeHeader = action.request.getContentType() ;
-
- if ( contentTypeHeader == null )
- errorBadRequest("No content type: " + contentTypeHeader) ;
- ContentType ct = ContentType.create(contentTypeHeader) ;
- return ct ;
- }
-
- protected static DatasetGraph parseBody(HttpAction action) {
- ContentType ct = getContentType(action) ;
- String base = wholeRequestURL(action.request) ;
-
- if ( WebContent.contentTypeMultiFormData.equalsIgnoreCase(ct.getContentType()) ) {
- Graph graphTmp = SPARQL_Upload.upload(action, base) ;
- return DatasetGraphFactory.create(graphTmp) ;
- }
-
- if ( WebContent.contentTypeMultiMixed.equals(ct.getContentType()) ) {
- error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "multipart/mixed not supported") ;
- return null ;
- }
-
- int len = action.request.getContentLength() ;
- Lang lang = WebContent.contentTypeToLang(ct.getContentType()) ;
- if ( lang == null ) {
- errorBadRequest("Unknown content type for triples: " + ct) ;
- return null ;
- }
-
- if ( action.verbose ) {
- if ( len >= 0 )
- log.info(format("[%d] Body: Content-Length=%d, Content-Type=%s, Charset=%s => %s", action.id, len,
- ct.getContentType(), ct.getCharset(), lang.getName())) ;
- else
- log.info(format("[%d] Body: Content-Type=%s, Charset=%s => %s", action.id, ct.getContentType(),
- ct.getCharset(), lang.getName())) ;
- }
-
- try {
- InputStream input = action.request.getInputStream() ;
- boolean buffering = false ;
- if ( buffering ) {
- // Slurp the input : can be helpful for debugging.
- if ( len >= 0 ) {
- byte b[] = new byte[len] ;
- input.read(b) ;
- input = new ByteArrayInputStream(b) ;
- } else {
- // Without content length, reading to end of file is
- // occassionaly fraught.
- // Reason unknown - maybe some client mishandling of the
- // stream.
- String x = FileUtils.readWholeFileAsUTF8(input) ;
- input = new ByteArrayInputStream(x.getBytes("UTF-8")) ;
- }
- }
-
- return parse(action, input, lang, base) ;
- } catch (IOException ex) { errorOccurred(ex) ; return null ; }
- }
-
- private static DatasetGraph parse(HttpAction action, InputStream input, Lang lang, String base)
- {
- Graph graphTmp = GraphFactory.createGraphMem() ;
- StreamRDF dest = StreamRDFLib.graph(graphTmp) ;
- parse(action, dest, input, lang, base) ;
- DatasetGraph dsgTmp = DatasetGraphFactory.create(graphTmp) ;
- return dsgTmp ;
- }
- private static void parse(HttpAction action, StreamRDF dest, InputStream input, Lang lang, String base) {
+ // @@ Move to SPARQL_ServletBase
+ // Check for all RiotReader
+ public static void parse(HttpAction action, StreamRDF dest, InputStream input, Lang lang, String base) {
+ // Need to adjust the error handler.
+// try { RDFDataMgr.parse(dest, input, base, lang) ; }
+// catch (RiotException ex) { errorBadRequest("Parse error: "+ex.getMessage()) ; }
LangRIOT parser = RiotReader.createParser(input, lang, base, dest) ;
parser.getProfile().setHandler(errorHandler) ;
try { parser.parse() ; }
catch (RiotException ex) { errorBadRequest("Parse error: "+ex.getMessage()) ; }
}
-
-
-
+
@Override
protected void validate(HttpAction action)
{
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java Sat Aug 17 09:57:06 2013
@@ -18,19 +18,23 @@
package org.apache.jena.fuseki.servlets;
+import static java.lang.String.format ;
+
+import java.io.IOException ;
import java.io.InputStream ;
+import org.apache.jena.atlas.io.IO ;
import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.HttpNames ;
import org.apache.jena.riot.Lang ;
-import org.apache.jena.riot.RDFDataMgr ;
import org.apache.jena.riot.WebContent ;
import org.apache.jena.riot.system.StreamRDF ;
import org.apache.jena.riot.system.StreamRDFLib ;
+import org.apache.jena.web.HttpSC ;
import com.hp.hpl.jena.graph.Graph ;
-import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.graph.GraphFactory ;
/** The WRITE operations added to the READ operations */
public class SPARQL_REST_RW extends SPARQL_REST_R
@@ -75,6 +79,21 @@ public class SPARQL_REST_RW extends SPAR
protected void doPost(HttpAction action) { doPutPost(action, false) ; }
private void doPutPost(HttpAction action, boolean overwrite) {
+ ContentType ct = FusekiLib.getContentType(action) ;
+ if ( ct == null )
+ errorBadRequest("No Content-Type:") ;
+
+ // Helper case - if it's a possible HTTP file upload, pretend that's the action.
+ if ( WebContent.contentTypeMultiFormData.equalsIgnoreCase(ct.getContentType()) ) {
+ String base = wholeRequestURL(action.request) ;
+ SPARQL_Upload.upload(action, base) ;
+ return ;
+ }
+
+ if ( WebContent.contentTypeMultiMixed.equals(ct.getContentType()) ) {
+ error(HttpSC.UNSUPPORTED_MEDIA_TYPE_415, "multipart/mixed not supported") ;
+ }
+
boolean existedBefore = false ;
if ( action.isTransactional() )
existedBefore = addDataIntoTxn(action, overwrite) ;
@@ -96,13 +115,6 @@ public class SPARQL_REST_RW extends SPAR
*/
protected static boolean addDataIntoTxn(HttpAction action, boolean overwrite)
{
- ContentType ct = getContentType(action) ;
- String base = wholeRequestURL(action.request) ;
- Lang lang = WebContent.contentTypeToLang(ct.getContentType()) ;
- if ( lang == null ) {
- errorBadRequest("Unknown content type for triples: " + ct) ;
- return true ;
- }
action.beginWrite();
Target target = determineTarget(action) ;
@@ -110,13 +122,13 @@ public class SPARQL_REST_RW extends SPAR
try {
if ( log.isDebugEnabled() )
log.debug(" ->"+target) ;
- InputStream input = action.request.getInputStream() ;
existedBefore = target.exists() ;
+
Graph g = target.graph() ;
if ( overwrite && existedBefore )
clearGraph(target) ;
StreamRDF sink = StreamRDFLib.graph(g) ;
- RDFDataMgr.parse(sink, input, base, lang) ;
+ incomingData(action, sink);
action.commit() ;
return existedBefore ;
} catch (Exception ex) {
@@ -137,8 +149,12 @@ public class SPARQL_REST_RW extends SPAR
* @param cleanDest Whether to remove daat first (true = PUT, false = POST)
* @return whether the target existed beforehand.
*/
- protected static boolean addDataIntoNonTxn(HttpAction action, boolean cleanDest) {
- DatasetGraph body = parseBody(action) ;
+
+ protected static boolean addDataIntoNonTxn(HttpAction action, boolean overwrite) {
+ Graph graphTmp = GraphFactory.createGraphMem() ;
+ StreamRDF dest = StreamRDFLib.graph(graphTmp) ;
+ incomingData(action, dest);
+ // Now insert into dataset
action.beginWrite() ;
Target target = determineTarget(action) ;
boolean existedBefore = false ;
@@ -146,15 +162,39 @@ public class SPARQL_REST_RW extends SPAR
if ( log.isDebugEnabled() )
log.debug(" ->"+target) ;
existedBefore = target.exists() ;
- if ( cleanDest && existedBefore )
+ if ( overwrite && existedBefore )
clearGraph(target) ;
- //addDataInto(body.getDefaultGraph(), action) ;
- FusekiLib.addDataInto(body.getDefaultGraph(), target.dsg, target.graphName) ;
+ FusekiLib.addDataInto(graphTmp, target.dsg, target.graphName) ;
action.commit() ;
return existedBefore ;
} finally { action.endWrite() ; }
}
+ private static void incomingData(HttpAction action, StreamRDF dest) {
+ String base = wholeRequestURL(action.request) ;
+ ContentType ct = FusekiLib.getContentType(action) ;
+ Lang lang = WebContent.contentTypeToLang(ct.getContentType()) ;
+ if ( lang == null ) {
+ errorBadRequest("Unknown content type for triples: " + ct) ;
+ return ;
+ }
+ InputStream input = null ;
+ try { input = action.request.getInputStream() ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+
+ int len = action.request.getContentLength() ;
+ if ( action.verbose ) {
+ if ( len >= 0 )
+ log.info(format("[%d] Body: Content-Length=%d, Content-Type=%s, Charset=%s => %s", action.id, len,
+ ct.getContentType(), ct.getCharset(), lang.getName())) ;
+ else
+ log.info(format("[%d] Body: Content-Type=%s, Charset=%s => %s", action.id, ct.getContentType(),
+ ct.getCharset(), lang.getName())) ;
+ }
+
+ parse(action, dest, input, lang, base) ;
+ }
+
protected static void deleteGraph(HttpAction action) {
Target target = determineTarget(action) ;
if ( target.isDefault )
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Update.java Sat Aug 17 09:57:06 2013
@@ -39,7 +39,7 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse ;
import org.apache.jena.atlas.io.IO ;
-import org.apache.jena.atlas.web.MediaType ;
+import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.HttpNames ;
import org.apache.jena.iri.IRI ;
@@ -93,11 +93,11 @@ public class SPARQL_Update extends SPARQ
// WebContent needs to migrate to using ContentType.
String ctStr ;
{
- MediaType incoming = FusekiLib.contentType(action.request) ;
- if ( incoming == null )
+ ContentType ct = FusekiLib.getContentType(action) ;
+ if ( ct == null )
ctStr = WebContent.contentTypeSPARQLUpdate ;
else
- ctStr = incoming.getContentType() ;
+ ctStr = ct.getContentType() ;
}
if (WebContent.contentTypeSPARQLUpdate.equals(ctStr))
@@ -125,7 +125,7 @@ public class SPARQL_Update extends SPARQ
if ( ! HttpNames.METHOD_POST.equalsIgnoreCase(request.getMethod()) )
errorMethodNotAllowed("SPARQL Update : use POST") ;
- MediaType incoming = FusekiLib.contentType(request) ;
+ ContentType incoming = FusekiLib.getContentType(action) ;
String ctStr = ( incoming == null ) ? WebContent.contentTypeSPARQLUpdate : incoming.getContentType() ;
// ----
Modified: jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java?rev=1514974&r1=1514973&r2=1514974&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java (original)
+++ jena/trunk/jena-fuseki/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_Upload.java Sat Aug 17 09:57:06 2013
@@ -31,12 +31,15 @@ import org.apache.commons.fileupload.Fil
import org.apache.commons.fileupload.FileItemStream ;
import org.apache.commons.fileupload.servlet.ServletFileUpload ;
import org.apache.commons.fileupload.util.Streams ;
+import org.apache.jena.atlas.lib.Pair ;
import org.apache.jena.atlas.web.ContentType ;
import org.apache.jena.fuseki.FusekiLib ;
import org.apache.jena.fuseki.HttpNames ;
import org.apache.jena.iri.IRI ;
-import org.apache.jena.riot.* ;
-import org.apache.jena.riot.lang.LangRIOT ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.WebContent ;
+import org.apache.jena.riot.lang.StreamRDFCounting ;
import org.apache.jena.riot.system.* ;
import org.apache.jena.web.HttpSC ;
@@ -72,68 +75,85 @@ public class SPARQL_Upload extends SPARQ
@Override
protected void perform(HttpAction action)
{
-// if ( action.isTransactional() )
-// {}
-
// Only allows one file in the upload.
boolean isMultipart = ServletFileUpload.isMultipartContent(action.request);
if ( ! isMultipart )
error(HttpSC.BAD_REQUEST_400 , "Not a file upload") ;
-
- long tripleCount = -1 ;
- action.beginWrite() ;
+ long count = upload(action, "http://example/upload-base/") ;
try {
- Graph graphTmp = GraphFactory.createDefaultGraph() ;
- String graphName = upload(action, graphTmp, "http://example/upload-base/") ;
- tripleCount = graphTmp.size() ;
-
- log.info(format("[%d] Upload: Graph: %s (%d triple(s))",
- action.id, graphName, tripleCount)) ;
-
- Node gn = graphName.equals(HttpNames.valueDefault)
- ? Quad.defaultGraphNodeGenerated
- : NodeFactory.createURI(graphName) ;
-
+ action.response.setContentType("text/plain") ;
+ action.response.getOutputStream().print("Triples = "+count) ;
+ success(action) ;
+ }
+ catch (Exception ex) { errorOccurred(ex) ; }
+ }
+
+ // Also used by SPARQL_REST
+ static public long upload(HttpAction action, String base)
+ {
+ if ( action.isTransactional() )
+ return uploadTxn(action, base) ;
+ else
+ return uploadNonTxn(action, base) ;
+ }
+
+ /** Non-transaction - buffer to a temporary graph so that parse errors
+ * are caught before inserting any data.
+ */
+ private static long uploadNonTxn(HttpAction action, String base) {
+ Pair<String, Graph> p = uploadWorker(action, base) ;
+ String graphName = p.getLeft() ;
+ Graph graphTmp = p.getRight() ;
+ long tripleCount = graphTmp.size() ;
+
+ log.info(format("[%d] Upload: Graph: %s (%d triple(s))",
+ action.id, graphName, tripleCount)) ;
+
+ Node gn = graphName.equals(HttpNames.valueDefault)
+ ? Quad.defaultGraphNodeGenerated
+ : NodeFactory.createURI(graphName) ;
+
+ action.beginWrite() ;
+ try {
FusekiLib.addDataInto(graphTmp, action.getActiveDSG(), gn) ;
- tripleCount = graphTmp.size();
action.commit() ;
+ return tripleCount ;
} catch (RuntimeException ex)
{
// If anything went wrong, try to backout.
try { action.abort() ; } catch (Exception ex2) {}
errorOccurred(ex.getMessage()) ;
+ return -1 ;
}
finally { action.endWrite() ; }
- try {
- action.response.setContentType("text/plain") ;
- action.response.getOutputStream().print("Triples = "+tripleCount) ;
- success(action) ;
- }
- catch (Exception ex) { errorOccurred(ex) ; }
}
- // Used by SPARQL_REST
- static public Graph upload(HttpAction action, String destination)
- {
- // We read into a in-memory graph, then (if successful) update the dataset.
- // This isolates errors.
- Graph graphTmp = GraphFactory.createDefaultGraph() ;
- String graphName = upload(action, graphTmp, destination) ;
- return graphTmp ;
- }
-
- /** @return any graph name found.
+ /** Transactional - we'd like data to go straight to the destination, with an abort on parse error.
+ * But file upload with a name means that the name can be after the data
+ * (it is in the Fuseki default pages).
+ * Use Graph Store protocol for bulk uploads.
+ * (It would be possible to process the incoming stream and see the graph name first.)
+ */
+ private static long uploadTxn(HttpAction action, String base) {
+ // We can't do better than the non-transaction approach.
+ return uploadNonTxn(action, base) ;
+ }
+
+ /** process an HTTP upload of RDF.
+ * We can't stream straight into a dataset because the graph name can be after the data.
+ * @return graph name and count
*/
- static private String upload(HttpAction action, Graph graphDst, String base)
+ static private Pair<String, Graph> uploadWorker(HttpAction action, String base)
{
+ Graph graphTmp = GraphFactory.createDefaultGraph() ;
ServletFileUpload upload = new ServletFileUpload();
- // Locking only needed over the insert into the dataset
String graphName = null ;
+ long count = -1 ;
+
String name = null ;
ContentType ct = null ;
Lang lang = null ;
- int tripleCount = 0 ;
try {
FileItemIterator iter = upload.getItemIterator(action.request);
@@ -148,7 +168,7 @@ public class SPARQL_Upload extends SPARQ
if ( fieldName.equals(HttpNames.paramGraph) )
{
graphName = value ;
- if ( graphName != null && ! graphName.equals(HttpNames.valueDefault) )
+ if ( graphName != null && ! graphName.equals("") && ! graphName.equals(HttpNames.valueDefault) )
{
IRI iri = IRIResolver.parseIRI(value) ;
if ( iri.hasViolation(false) )
@@ -188,19 +208,19 @@ public class SPARQL_Upload extends SPARQ
// Desperate.
lang = RDFLanguages.RDFXML ;
- StreamRDF dest = StreamRDFLib.graph(graphDst) ;
- LangRIOT parser = RiotReader.createParser(stream, lang, base, dest) ;
- parser.getProfile().setHandler(errorHandler) ;
log.info(format("[%d] Upload: Filename: %s, Content-Type=%s, Charset=%s => %s",
action.id, name, ct.getContentType(), ct.getCharset(), lang.getName())) ;
- try { parser.parse() ; }
- catch (RiotException ex) { errorBadRequest("Parse error: "+ex.getMessage()) ; }
+
+ StreamRDF x = StreamRDFLib.graph(graphTmp) ;
+ StreamRDFCounting dest = StreamRDFLib.count(x) ;
+ SPARQL_REST.parse(action, dest, stream, lang, base);
+ count = dest.count() ;
}
}
- if ( graphName == null )
- graphName = "default" ;
- return graphName ;
+ if ( graphName == null || graphName.equals("") )
+ graphName = HttpNames.valueDefault ;
+ return Pair.create(graphName, graphTmp) ;
}
catch (ActionErrorException ex) { throw ex ; }
catch (Exception ex) { errorOccurred(ex) ; return null ; }