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 ; }