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/12/11 18:10:51 UTC

svn commit: r1550192 - in /jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets: SPARQL_REST.java SPARQL_REST_RW.java

Author: andy
Date: Wed Dec 11 17:10:50 2013
New Revision: 1550192

URL: http://svn.apache.org/r1550192
Log:
HTML Form style upload of multiple files for GSP PUT/POST (partial impl).

Modified:
    jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java
    jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java

Modified: jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java
URL: http://svn.apache.org/viewvc/jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java?rev=1550192&r1=1550191&r2=1550192&view=diff
==============================================================================
--- jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java (original)
+++ jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST.java Wed Dec 11 17:10:50 2013
@@ -18,27 +18,29 @@
 
 package org.apache.jena.fuseki.servlets;
 
+import static java.lang.String.format ;
 import static org.apache.jena.fuseki.HttpNames.* ;
 
 import java.io.IOException ;
 import java.io.InputStream ;
 import java.util.Enumeration ;
 import java.util.Locale ;
+import java.util.zip.GZIPInputStream ;
 
 import javax.servlet.ServletException ;
 import javax.servlet.http.HttpServletRequest ;
 import javax.servlet.http.HttpServletResponse ;
 
+import org.apache.commons.fileupload.FileItemIterator ;
+import org.apache.commons.fileupload.FileItemStream ;
+import org.apache.commons.fileupload.servlet.ServletFileUpload ;
+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.* ;
 import org.apache.jena.riot.lang.LangRIOT ;
-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.apache.jena.riot.lang.StreamRDFCounting ;
+import org.apache.jena.riot.system.* ;
 import org.slf4j.Logger ;
 import org.slf4j.LoggerFactory ;
 
@@ -86,7 +88,6 @@ public abstract class SPARQL_REST extend
         Node gn = NodeFactory.createURI(absUri) ;
         return Target.createNamed(action.getActiveDSG(), absUri, gn) ;
     }
-    
 
     // struct for target
     protected static final class Target
@@ -204,7 +205,7 @@ public abstract class SPARQL_REST extend
 
     // Counter wrappers
     
-    protected void doGet$(HttpAction action) {
+    private final void doGet$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPget) ;
         try {
             doGet(action) ;
@@ -215,7 +216,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doHead$(HttpAction action) {
+    private final void doHead$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPhead) ;
         try {
             doHead(action) ;
@@ -226,7 +227,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doPost$(HttpAction action) {
+    private final void doPost$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPpost) ;
         try {
             doPost(action) ;
@@ -237,7 +238,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doPatch$(HttpAction action) {
+    private final void doPatch$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPpatch) ;
         try {
             doPatch(action) ;
@@ -248,7 +249,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doDelete$(HttpAction action) {
+    private final void doDelete$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPdelete) ;
         try {
             doDelete(action) ;
@@ -259,7 +260,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doPut$(HttpAction action) {
+    private final void doPut$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPput) ;
         try {
             doPut(action) ;
@@ -270,7 +271,7 @@ public abstract class SPARQL_REST extend
         }
     }
 
-    protected void doOptions$(HttpAction action) {
+    private final void doOptions$(HttpAction action) {
         incCounter(action.srvRef, CounterName.GSPoptions) ;
         try {
             doOptions(action) ;
@@ -289,7 +290,7 @@ public abstract class SPARQL_REST extend
     protected abstract void doPut(HttpAction action) ;
     protected abstract void doOptions(HttpAction action) ;
     
-    // @@ Move to SPARQL_ServletBase
+    // XXX 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.
@@ -351,4 +352,86 @@ public abstract class SPARQL_REST extend
             errorBadRequest("Multiple occurrences of '"+name+"'") ;
         return values[0] ;
     }
+    
+    // XXX Where to put this?
+    /**  Process an HTTP upload of RDF files (triples or quads)
+     *   Stream straight into a graph or dataset -- unlike SPARQL_Upload the destination is known
+     *   at the start of the multipart file body
+     */
+    
+    static public void fileUploadWorker(HttpAction action, String base)
+    {
+        // XXX Extend determineTarget to allow for datasets.  Conflict with direct naming?
+        Target target = determineTarget(action) ;
+
+        String item = (target==null)?"quad":"triple" ;
+
+        // Load quads or triples.
+        // Caution: if a target grpah is given and then a quads format found,
+        // the default graph of the quad steram is sent to the target graph.
+        StreamRDF dest = 
+            (target == null) 
+            ? StreamRDFLib.dataset(action.getActiveDSG())
+            : StreamRDFLib.graph(target.graph()) ; 
+            
+        ServletFileUpload upload = new ServletFileUpload();
+        long count = -1 ;
+        
+        //log.info(format("[%d] Upload: Field=%s ignored", action.id, fieldName)) ;
+        
+        try {
+            FileItemIterator iter = upload.getItemIterator(action.request);
+            while (iter.hasNext()) {
+                FileItemStream fileStream = iter.next();
+                if (fileStream.isFormField())
+                    errorBadRequest("Only files accept in multipart file upload") ;
+                //Ignore the field name.
+                //String fieldName = fileStream.getFieldName();
+
+                InputStream stream = fileStream.openStream();
+                // Process the input stream
+                String contentTypeHeader = fileStream.getContentType() ;
+                ContentType ct = ContentType.create(contentTypeHeader) ;
+                Lang lang = RDFLanguages.contentTypeToLang(ct.getContentType()) ;
+
+                if ( lang == null ) {
+                    String name = fileStream.getName() ; 
+                    if ( name == null || name.equals("") ) 
+                        errorBadRequest("No name for content - can't determine RDF syntax") ;
+                    lang = RDFLanguages.filenameToLang(name) ;
+                    if (name.endsWith(".gz"))
+                        stream = new GZIPInputStream(stream);
+                }
+                if ( lang == null )
+                    // Desperate.
+                    lang = RDFLanguages.RDFXML ;
+
+                String printfilename = fileStream.getName() ; 
+                if ( printfilename == null  || printfilename.equals("") )
+                    printfilename = "<none>" ; 
+
+                // Before
+                // action.log.info(format("[%d] Filename: %s, Content-Type=%s, Charset=%s => %s", 
+                //                        action.id, printfilename,  ct.getContentType(), ct.getCharset(), lang.getName())) ;
+                
+                StreamRDFCounting countingDest =  StreamRDFLib.count(dest) ;
+                try {
+                    SPARQL_REST.parse(action, countingDest, stream, lang, base);
+                    long c = countingDest.count() ;
+                    
+                    action.log.info(format("[%d] Filename: %s, Content-Type=%s, Charset=%s => %s : %d %s%s", 
+                                           action.id, printfilename,  ct.getContentType(), ct.getCharset(), lang.getName(),
+                                           c, item, (c==1)?"":"s")) ;
+                } catch (RiotParseException ex) {
+                    action.log.info(format("[%d] Filename: %s, Content-Type=%s, Charset=%s => %s : %s",
+                                           action.id, printfilename,  ct.getContentType(), ct.getCharset(), lang.getName(),
+                                           ex.getMessage())) ;
+                    throw ex ;
+                }
+            }
+        }
+        catch (ActionErrorException ex) { throw ex ; }
+        catch (Exception ex)            { errorOccurred(ex) ; }
+    }            
+
 }

Modified: jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java
URL: http://svn.apache.org/viewvc/jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java?rev=1550192&r1=1550191&r2=1550192&view=diff
==============================================================================
--- jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java (original)
+++ jena/branches/jena-fuseki-new-ui/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_REST_RW.java Wed Dec 11 17:10:50 2013
@@ -75,10 +75,10 @@ public class SPARQL_REST_RW extends SPAR
     }
 
     @Override
-    protected void doPut(HttpAction action)     { doPutPost(action, true) ; }
+    protected void doPut(HttpAction action)         { doPutPost(action, true) ; }
 
     @Override
-    protected void doPost(HttpAction action)     { doPutPost(action, false) ; }
+    protected void doPost(HttpAction action)        { doPutPost(action, false) ; }
 
     private void doPutPost(HttpAction action, boolean overwrite) {
         ContentType ct = FusekiLib.getContentType(action) ;
@@ -88,7 +88,7 @@ public class SPARQL_REST_RW extends SPAR
         // 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) ;
+            fileUpload(action, base);
             return ; 
         }
 
@@ -103,9 +103,9 @@ public class SPARQL_REST_RW extends SPAR
             existedBefore = addDataIntoNonTxn(action, overwrite) ;
             
         if ( existedBefore )
-            ActionSPARQL.successNoContent(action) ;
+            successNoContent(action) ;
         else
-            ActionSPARQL.successCreated(action) ;
+            successCreated(action) ;
     }
 
     /** Directly add data in a transaction.
@@ -211,7 +211,59 @@ public class SPARQL_REST_RW extends SPAR
     
         parse(action, dest, input, lang, base) ;
     }
+    
+    static public void fileUpload(HttpAction action, String base)
+    {
+        if ( action.isTransactional() )
+            uploadTxn(action, base) ;
+        else
+            uploadNonTxn(action, base) ;
+    }
 
+    /** Non-transaction - buffer to a temporary graph so that parse errors
+     * are caught before inserting any data. 
+     */
+     private static void uploadNonTxn(HttpAction action, String base) {
+         System.err.println("Dangerous fake") ; 
+         // Need tempoary destination
+         action.beginWrite() ;
+         fileUploadWorker(action, base) ;
+         action.commit() ;
+         // XXX
+//         Pair<String, Graph> p = null ;
+//         String graphName = p.getLeft() ;
+//         Graph graphTmp = p.getRight() ;
+//         long tripleCount = graphTmp.size() ;
+//
+//         action.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) ;
+//            action.commit() ;
+//            return ;
+//        } catch (RuntimeException ex)
+//        {
+//            // If anything went wrong, try to backout.
+//            try { action.abort() ; } catch (Exception ex2) {}
+//            errorOccurred(ex.getMessage()) ;
+//            return ;
+//        } 
+//        finally { action.endWrite() ; }
+    }
+
+     /** Transactional - data to go straight to the destination, with an abort on parse error.
+      */
+      private static void uploadTxn(HttpAction action, String base) {
+          fileUploadWorker(action, base) ;
+      }
+     
+    
     protected static void deleteGraph(HttpAction action) {
         Target target = determineTarget(action) ;
         if ( target.isDefault )