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 2014/08/02 16:01:26 UTC

svn commit: r1615316 - in /jena/Experimental/jena-fuseki2: src-dev/dev/ src/main/java/org/apache/jena/fuseki/mgt/ src/main/java/org/apache/jena/fuseki/server/ src/main/java/org/apache/jena/fuseki/servlets/

Author: andy
Date: Sat Aug  2 14:01:25 2014
New Revision: 1615316

URL: http://svn.apache.org/r1615316
Log:
Support for web context and other webapp deployment fixes.

Modified:
    jena/Experimental/jena-fuseki2/src-dev/dev/PROJECT.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionBase.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionSPARQL.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/FusekiFilter.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
    jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java

Modified: jena/Experimental/jena-fuseki2/src-dev/dev/PROJECT.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src-dev/dev/PROJECT.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src-dev/dev/PROJECT.java (original)
+++ jena/Experimental/jena-fuseki2/src-dev/dev/PROJECT.java Sat Aug  2 14:01:25 2014
@@ -19,6 +19,10 @@
 package dev;
 
 public class PROJECT {
+    
+    // URI parsed during execCommonWorker and again in uber dispatch
+    //  --> do once. Info in action (context path, dataset name, operation) + admin
+    
     // Refindable backups
     // Name of backup in the response to back up starting.
     //   Task specific return as well?

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java Sat Aug  2 14:01:25 2014
@@ -40,8 +40,10 @@ public abstract class ActionCtl extends 
         String datasetUri = mapRequestToDatasetName(action) ;
         if ( datasetUri != null ) {
             dataAccessPoint = DataAccessPointRegistry.get().get(datasetUri) ;
-            if ( dataAccessPoint == null )
+            if ( dataAccessPoint == null ) {
                 ServletOps.errorNotFound("Not found: "+datasetUri) ;
+                return ;
+            }
         }
         else {
             // This is a placeholder when creating new DatasetRefs

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java Sat Aug  2 14:01:25 2014
@@ -68,7 +68,6 @@ public class ActionTasks extends ActionB
         else
             ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
     }
-    
 
     private void execGet(HttpAction action, String name) {
         if ( name == null )

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java Sat Aug  2 14:01:25 2014
@@ -329,11 +329,21 @@ public class FusekiServer
     }
     
     public static void addGlobals(Map<String, String> params) {
+        if ( params == null ) {
+            Fuseki.configLog.warn("FusekiServer.addGlobals : params is null", new Throwable()) ;
+            return ;
+        }
+        
         if ( ! params.containsKey("FUSEKI_BASE") )
-            params.put("FUSEKI_BASE", FusekiServer.FUSEKI_BASE.toString()) ;
+            params.put("FUSEKI_BASE", pathStringOrElse(FUSEKI_BASE, "unset")) ;
         if ( ! params.containsKey("FUSEKI_HOME") )
-            params.put("FUSEKI_HOME", FusekiServer.FUSEKI_HOME.toString()) ;
+            params.put("FUSEKI_HOME", pathStringOrElse(FUSEKI_HOME, "unset")) ;
+    }
 
+    private static String pathStringOrElse(Path path, String dft) {
+        if ( path == null )
+            return dft ;
+        return path.toString() ;
     }
     
     // DRY -- ActionDatasets (and others?)

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionBase.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionBase.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionBase.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionBase.java Sat Aug  2 14:01:25 2014
@@ -64,12 +64,11 @@ public abstract class ActionBase extends
             
             // Lifecycle
             HttpAction action = allocHttpAction(id, request, response) ;
-            // then add to doCommonWorker
-            // work with HttpServletResponseTracker
-            
+
             printRequest(action) ;
             action.setStartTime() ;
             
+            // The response may be changed to a HttpServletResponseTracker
             response = action.response ;
             initResponse(request, response) ;
             Context cxt = ARQ.getContext() ;

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionLib.java Sat Aug  2 14:01:25 2014
@@ -30,16 +30,19 @@ import org.apache.jena.fuseki.server.Dat
 /** Operations related to servlets */
 
 public class ActionLib {
-    // TODO Combine ServletOps?
+    public static String mapRequestToDataset(HttpAction action) {
+        String uri = action.getActionURI() ;
+        return mapActionRequestToDataset(uri) ;
+    }
     
     /** Map request to uri in the registry.
-     * A possible implementation for mapRequestToDataset(String)
+     *  A possible implementation for mapRequestToDataset(String)
      *  that assumes the form /dataset/service 
-     *  Returning null means no mapping found. 
+     *  Returning null means no mapping found.
+     *  The URI must be the action URI (no contact path) 
      */
     
-    public static String mapRequestToDataset(String uri)
-    {
+    public static String mapActionRequestToDataset(String uri) {
         // Chop off trailing part - the service selector
         // e.g. /dataset/sparql => /dataset 
         int i = uri.lastIndexOf('/') ;
@@ -54,10 +57,11 @@ public class ActionLib {
         return uri.substring(0, i) ;
     }
 
-    public static String mapRequestToOperation(DataAccessPoint dsRef, String uri, String datasetURI)
-    {
+    /** Calculate the operation , given action and data access point */ 
+    public static String mapRequestToOperation(HttpAction action, DataAccessPoint dsRef) {
         if ( dsRef == null )
             return "" ;
+        String uri = action.getActionURI() ;
         String name = dsRef.getName();
         if ( name.length() >= uri.length() )
             return "" ;
@@ -110,20 +114,25 @@ public class ActionLib {
     /* 
      * The context path can be:
      * "" for the root context
-     * "/webapp" for named contexts
+     * "/APP" for named contexts
      * so:
      * "/dataset/server" becomes "/dataset/server"
-     * "/webapp/dataset/server" becomes "/dataset/server"
+     * "/APP/dataset/server" becomes "/dataset/server"
      */
     public static String removeContextPath(HttpAction action) {
-//        Log.info(this, "URI                     = '"+action.request.getRequestURI()) ;
-//        Log.info(this, "Context path            = '"+action.request.getContextPath()+"'") ;
-//        Log.info(this, "Servlet path            = '"+action.request.getServletPath()+"'") ;
-//        ServletContext cxt = this.getServletContext() ;
-//        Log.info(this, "ServletContext path     = '"+cxt.getContextPath()+"'") ;
 
-        String uri = action.request.getRequestURI() ;
-        String contextPath = action.request.getServletContext().getContextPath() ;
+        return actionURI(action.request) ;
+    }
+    
+    public static String actionURI(HttpServletRequest request) {
+//      Log.info(this, "URI                     = '"+request.getRequestURI()) ;
+//      Log.info(this, "Context path            = '"+request.getContextPath()+"'") ;
+//      Log.info(this, "Servlet path            = '"+request.getServletPath()+"'") ;
+//      ServletContext cxt = this.getServletContext() ;
+//      Log.info(this, "ServletContext path     = '"+cxt.getContextPath()+"'") ;
+        
+        String contextPath = request.getServletContext().getContextPath() ;
+        String uri = request.getRequestURI() ;
         if ( contextPath == null )
             return uri ;
         if ( contextPath.isEmpty())
@@ -131,7 +140,7 @@ public class ActionLib {
         String x = uri ;
         if ( uri.startsWith(contextPath) )
             x = uri.substring(contextPath.length()) ;
-        //log.info("removeContext: uri = "+uri+" contextPath="+contextPath+ "--> x="+x) ;
+        //log.info("uriWithoutContextPath: uri = "+uri+" contextPath="+contextPath+ "--> x="+x) ;
         return x ;
     }
 

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionSPARQL.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionSPARQL.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionSPARQL.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/ActionSPARQL.java Sat Aug  2 14:01:25 2014
@@ -50,7 +50,6 @@ public abstract class ActionSPARQL exten
         DataService dSrv ;
         
         String datasetUri = mapRequestToDataset(action) ;
-        
         if ( datasetUri != null ) {
             dataAccessPoint = DataAccessPointRegistry.get().get(datasetUri) ;
             if ( dataAccessPoint == null ) {
@@ -68,8 +67,7 @@ public abstract class ActionSPARQL exten
             dSrv = DataService.serviceOnlyDataService() ;
         }
 
-        String uri = action.request.getRequestURI() ;
-        String operationName = ActionLib.mapRequestToOperation(dataAccessPoint, uri, datasetUri) ;
+        String operationName = mapRequestToOperation(action, dataAccessPoint) ;
         action.setRequest(dataAccessPoint, dSrv) ;
         
         //operationName = ""
@@ -123,11 +121,18 @@ public abstract class ActionSPARQL exten
     /** Map request to uri in the registry.
      *  null means no mapping done (passthrough). 
      */
-    protected String mapRequestToDataset(HttpAction action) 
-    {
-        return ActionLib.mapRequestToDataset(action.request.getRequestURI()) ;
+    protected String mapRequestToDataset(HttpAction action) {
+        return ActionLib.mapRequestToDataset(action) ;
     }
-    
+
+    /**
+     * Map request to uri in the registry. null means no mapping done
+     * (passthrough).
+     */
+    protected String mapRequestToOperation(HttpAction action, DataAccessPoint dataAccessPoint) {
+        return ActionLib.mapRequestToOperation(action, dataAccessPoint) ;
+    }
+
     protected static void incCounter(Counters counters, CounterName name) {
         if ( counters == null ) return ;
         incCounter(counters.getCounters(), name) ; 

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/FusekiFilter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/FusekiFilter.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/FusekiFilter.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/FusekiFilter.java Sat Aug  2 14:01:25 2014
@@ -46,10 +46,9 @@ public class FusekiFilter implements Fil
             HttpServletRequest req = (HttpServletRequest)request ;
             HttpServletResponse resp = (HttpServletResponse)response ;
 
-            // XXX Context path
             String x = request.getServletContext().getContextPath() ;
-            String uri = req.getRequestURI() ;
-            String datasetUri = ActionLib.mapRequestToDataset(uri) ;
+            String uri = ActionLib.actionURI(req) ;
+            String datasetUri = ActionLib.mapActionRequestToDataset(uri) ;
 
             // is it a long running operation?
             // (this could be a separate filter)

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java Sat Aug  2 14:01:25 2014
@@ -80,15 +80,17 @@ public class HttpAction
     private long finishTime = -2 ;
     
     // Outcome.
-    int statusCode = -1 ;
-    String message = null ;
-    int contentLength = -1 ;
-    String contentType = null ;
+    public int statusCode = -1 ;
+    public String message = null ;
+    public int contentLength = -1 ;
+    public String contentType = null ;
     
     // Cleared to archive:
-    Map <String, String> headers = new HashMap<>() ;
+    public Map <String, String> headers = new HashMap<>() ;
     public HttpServletRequest request;
     public HttpServletResponseTracker response ;
+    private final String actionURI ;
+    private final String contextPath ;
     
     public HttpAction(long id, Logger log, HttpServletRequest request, HttpServletResponse response, boolean verbose) {
         this.id = id ;
@@ -98,6 +100,8 @@ public class HttpAction
         // Should this be set when setDataset is called from the dataset context?
         // Currently server-wide, e.g. from the command line.
         this.verbose = verbose ;
+        this.contextPath = request.getServletContext().getContextPath() ;
+        this.actionURI = ActionLib.actionURI(request) ;
     }
 
     /** Initialization after action creation during lifecycle setup */
@@ -146,6 +150,20 @@ public class HttpAction
         return dsg ;
     }
         
+    /** This is the requestURI with the context path removed.
+     * It should be used internally for dispatch
+     */
+    public String getActionURI() {
+        return actionURI ;
+    }
+    
+    /** This is the requestURI with the context path removed.
+     * It should be used internally for dispatch
+     */
+    public String getContextPath() {
+        return contextPath ;
+    }
+
     public void setEndpoint(Endpoint srvRef, String endpointName) {
         this.endpoint = srvRef ; 
         this.endpointName = endpointName ;

Modified: jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java?rev=1615316&r1=1615315&r2=1615316&view=diff
==============================================================================
--- jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java (original)
+++ jena/Experimental/jena-fuseki2/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_UberServlet.java Sat Aug  2 14:01:25 2014
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.jena.atlas.web.MediaType ;
 import org.apache.jena.fuseki.DEF ;
+import org.apache.jena.fuseki.Fuseki ;
 import org.apache.jena.fuseki.FusekiException ;
 import org.apache.jena.fuseki.conneg.ConNeg ;
 import org.apache.jena.fuseki.server.DataAccessPoint ;
@@ -112,9 +113,9 @@ public abstract class SPARQL_UberServlet
     
     public SPARQL_UberServlet() { super(); }
 
-    private String getEPName(String dsname, List<String> endpoints)
-    {
-        if (endpoints == null || endpoints.size() == 0) return null ;
+    private String getEPName(String dsname, List<String> endpoints) {
+        if (endpoints == null || endpoints.size() == 0) 
+            return null ;
         String x = endpoints.get(0) ;
         if ( ! dsname.endsWith("/") )
             x = dsname+"/"+x ;
@@ -141,23 +142,20 @@ public abstract class SPARQL_UberServlet
      *  nor any stats have been done.
      */
     @Override
-    protected void executeAction(HttpAction action)
-    {
-        // XXX Worry about context path.
+    protected void executeAction(HttpAction action) {
         long id = action.id ;
         HttpServletRequest request = action.request ;
         HttpServletResponse response = action.response ;
-        String uri = request.getRequestURI() ;
+        String actionURI = action.getActionURI() ;            // No context path
         String method = request.getMethod() ;
         
-        
         DataAccessPoint desc = action.getDataAccessPoint() ;
         DataService dSrv = action.getDataService() ;
 
 //        if ( ! dSrv.isActive() )
 //            ServletOps.error(HttpSC.SERVICE_UNAVAILABLE_503, "Dataset not currently active");
         
-        String trailing = findTrailing(uri, desc.getName()) ;
+        String trailing = findTrailing(actionURI, desc.getName()) ;
         String qs = request.getQueryString() ;
 
         boolean hasParams = request.getParameterMap().size() > 0 ;
@@ -176,12 +174,14 @@ public abstract class SPARQL_UberServlet
         if ( ct != null )
             mt = MediaType.create(ct, charset) ;
         
-        action.log.info(format("[%d] %s %s :: '%s' :: %s ? %s", id, method, desc.getName(), trailing, (mt==null?"<none>":mt), (qs==null?"":qs))) ;
+        if (action.log.isInfoEnabled() ) {
+            //String cxt = action.getContextPath() ;
+            action.log.info(format("[%d] %s %s :: '%s' :: %s ? %s", id, method, desc.getName(), trailing, (mt==null?"<none>":mt), (qs==null?"":qs))) ;
+        }
                        
         boolean hasTrailing = ( trailing.length() != 0 ) ;
         
-        if ( ! hasTrailing && ! hasParams )
-        {
+        if ( !hasTrailing && !hasParams ) {
             // Check enabled.  But no trailing here.
             // if ( serviceDispatch(action, desc.readWriteGraphStore, trailing, restQuads_RW) ) return ;
             // if ( serviceDispatch(action, desc.readGraphStore, trailing, restQuads_R) ) return ;
@@ -189,29 +189,26 @@ public abstract class SPARQL_UberServlet
             return ;
         }
         
-        if ( ! hasTrailing )
-        {
-            // Has params of some kind.
-            if ( hasParamQuery || contentTypeSPARQLQuery.equalsIgnoreCase(ct) )
-            {
-                // SPARQL Query
-                if ( ! allowQuery(action))
-                    ServletOps.errorForbidden("Forbidden: SPARQL query") ; 
-                executeRequest(action, queryServlet) ;
-                return ;
-            }
-                 
-            if ( hasParamUpdate || contentTypeSPARQLUpdate.equalsIgnoreCase(ct) )
-            {
-                // SPARQL Update
-                if ( ! allowQuery(action))
-                    ServletOps.errorForbidden("Forbidden: SPARQL query") ; 
-                executeRequest(action, updateServlet) ;
-                return ;
+        if ( !hasTrailing ) {
+            if ( ct != null ) {
+                if ( hasParamQuery || contentTypeSPARQLQuery.equalsIgnoreCase(ct) ) {
+                    // SPARQL Query
+                    if ( !allowQuery(action) )
+                        ServletOps.errorForbidden("Forbidden: SPARQL query") ;
+                    executeRequest(action, queryServlet) ;
+                    return ;
+                }
+
+                if ( hasParamUpdate || contentTypeSPARQLUpdate.equalsIgnoreCase(ct) ) {
+                    // SPARQL Update
+                    if ( !allowQuery(action) )
+                        ServletOps.errorForbidden("Forbidden: SPARQL query") ;
+                    executeRequest(action, updateServlet) ;
+                    return ;
+                }
             }
             
-            if ( hasParamGraph || hasParamGraphDefault )
-            {
+            if ( hasParamGraph || hasParamGraphDefault ) {
                 doGraphStoreProtocol(action) ;
                 return ;
             }
@@ -221,8 +218,7 @@ public abstract class SPARQL_UberServlet
         }
         
         final boolean checkForPossibleService = true ;
-        if ( checkForPossibleService )
-        {
+        if ( checkForPossibleService ) {
             // There is a trailing part.
             // Check it's not the same name as a registered service.
             // If so, dispatch to that service.
@@ -259,15 +255,14 @@ public abstract class SPARQL_UberServlet
         return x ;
     }
     
-    private void doGraphStoreProtocol(HttpAction action)
-    {
+    private void doGraphStoreProtocol(HttpAction action) {
         // The GSP servlets handle direct and indirect naming. 
         Endpoint operation = action.getEndpoint() ;
         String method = action.request.getMethod() ;
         
         if ( HttpNames.METHOD_GET.equalsIgnoreCase(method) ||
              HttpNames.METHOD_HEAD.equalsIgnoreCase(method) ) 
-       {
+        {
            if ( ! allowREST_R(action))
            // Graphs Store Protocol, indirect naming, read
            // Indirect naming. Prefer the R service if available.
@@ -287,8 +282,7 @@ public abstract class SPARQL_UberServlet
        return ;
     }
 
-    private void executeRequest(HttpAction action,ActionSPARQL servlet)
-    {
+    private void executeRequest(HttpAction action, ActionSPARQL servlet) {
         servlet.executeLifecycle(action) ;
 //      // Forwarded dispatch.
 //      try
@@ -305,8 +299,7 @@ public abstract class SPARQL_UberServlet
 //      } catch (Exception e) { errorOccurred(e) ; }        
     }
 
-    protected static MediaType contentNegotationQuads(HttpAction action)
-    {
+    protected static MediaType contentNegotationQuads(HttpAction action) {
         MediaType mt = ConNeg.chooseContentType(action.request, DEF.quadsOffer, DEF.acceptNQuads) ;
         if ( mt == null )
             return null ;
@@ -318,10 +311,14 @@ public abstract class SPARQL_UberServlet
     }
 
     /** return true if dispatched 
-     * @param opName */
-    private boolean serviceDispatch(HttpAction action, OperationName opName , ActionSPARQL servlet)
-    {
+     * @param opName 
+     */
+    private boolean serviceDispatch(HttpAction action, OperationName opName, ActionSPARQL servlet) {
         Endpoint operation = action.getEndpoint() ;
+        if ( operation == null ) {
+            Fuseki.serverLog.warn("No operation: "+opName, new Throwable()) ;
+            return false ;
+        }
         if ( ! operation.isType(opName) ) 
             return false ;
         servlet.executeLifecycle(action) ;
@@ -329,8 +326,7 @@ public abstract class SPARQL_UberServlet
     }
 
     /** Find part after the dataset name: service name or the graph (direct naming) */ 
-    protected String findTrailing(String uri, String dsname) 
-    {
+    protected String findTrailing(String uri, String dsname) {
         if ( dsname.length() >= uri.length() )
             return "" ;
         return uri.substring(dsname.length()+1) ;   // Skip the separating "/"
@@ -360,4 +356,3 @@ public abstract class SPARQL_UberServlet
     protected void doDelete(HttpServletRequest request, HttpServletResponse response)
     { doCommon(request, response) ; }
 }
-