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 2012/01/12 16:16:43 UTC

svn commit: r1230584 - in /incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki: mgt/ server/ servlets/

Author: andy
Date: Thu Jan 12 15:16:42 2012
New Revision: 1230584

URL: http://svn.apache.org/viewvc?rev=1230584&view=rev
Log:
Add a backup action.

Added:
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ServerServlet.java
      - copied, changed from r1230447, incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServerServlet.java
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServletBase.java
Removed:
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServerServlet.java
Modified:
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionDataset.java
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/server/SPARQLServer.java
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
    incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java

Added: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java?rev=1230584&view=auto
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java (added)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java Thu Jan 12 15:16:42 2012
@@ -0,0 +1,171 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.mgt ;
+
+import static java.lang.String.format ;
+
+import java.io.BufferedOutputStream ;
+import java.io.FileNotFoundException ;
+import java.io.FileOutputStream ;
+import java.io.IOException ;
+import java.io.OutputStream ;
+import java.io.PrintWriter ;
+import java.util.concurrent.Callable ;
+import java.util.concurrent.ExecutorService ;
+import java.util.concurrent.Executors ;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.fuseki.http.HttpSC ;
+import org.apache.jena.fuseki.server.DatasetRef ;
+import org.apache.jena.fuseki.server.DatasetRegistry ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletBase ;
+import org.openjena.atlas.io.IO ;
+import org.openjena.atlas.logging.Log ;
+import org.openjena.riot.out.NQuadsWriter ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.util.Utils ;
+
+public class ActionBackup extends ServletBase
+{
+    public ActionBackup()
+    {
+        super(false) ;
+    }
+
+    // Limit to one backup at a time.
+    public static final ExecutorService backupService = Executors.newFixedThreadPool(1) ;
+    
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
+    {
+        // Split SPARQL ServletBase into Servletbase. 
+        
+        // request.getRemoteUser() ;
+        // request.getUserPrincipal() ;
+
+        final String dataset = request.getParameter("dataset") ;
+        // HttpSession session = request.getSession(true) ;
+        // session.setAttribute("dataset", dataset) ;
+        // session.setMaxInactiveInterval(15*60) ; // 10 mins
+
+        boolean known = DatasetRegistry.get().isRegistered(dataset) ;
+        if (!known)
+        {
+            response.sendError(HttpSC.BAD_REQUEST_400, "No such dataset: " + dataset) ;
+            return ;
+        }
+
+        DatasetRef ref = DatasetRegistry.get().get(dataset) ;
+        DatasetGraph dsg = ref.dataset ;
+        final HttpAction action = new HttpAction(requestIdAlloc.incrementAndGet(), dsg, request, response, false) ;
+        scheduleBackup(action, dataset) ;
+    }
+
+    private void scheduleBackup(final HttpAction action, final String dataset)
+    {
+        String timestamp = Utils.nowAsString("yyyy-MM-dd_HH-mm-ss") ;
+        final String filename = "backups" + dataset + "_" + timestamp ;
+        
+        try {
+            final Callable<Boolean> task = new Callable<Boolean>() {
+                @Override
+                public Boolean call() throws Exception
+                {
+                    log.info(format("[%d] Start backup %s to '%s'", action.id, dataset, filename)) ;
+                    action.beginRead() ;
+                    try {
+                        backup(action.getActiveDSG(), filename) ;
+                        log.info(format("[%d] Finish backup %s to '%s'", action.id, dataset, filename)) ;
+                    }
+                    catch ( RuntimeException ex )
+                    {
+                        log.info(format("[%d] Exception during backup: ", action.id, ex.getMessage()), ex) ;
+                        return Boolean.FALSE ;
+                    }
+                    finally {
+                        action.endRead() ;
+                    }
+                    return Boolean.TRUE ;
+                }} ;
+            
+            log.info(format("[%d] Schedule backup %s to '%s'", action.id, dataset, filename)) ;                
+            backupService.submit(task) ;
+        } 
+        //catch (FusekiException ex)
+        catch (RuntimeException ex)
+        {
+            log.warn("Unanticipated exception", ex) ;
+            try { action.response.sendError(HttpSC.INTERNAL_SERVER_ERROR_500, ex.getMessage()) ; }
+            catch (IOException e) { IO.exception(e) ; }
+            return ;            
+        }
+        
+        successPage(action, "Backup scheduled - see server log for details") ;
+    }
+    
+    // Share with new ServletBase.
+    protected static void successPage(HttpAction action, String message)
+    {
+        try {
+            action.response.setContentType("text/html");
+            action.response.setStatus(HttpSC.OK_200);
+            PrintWriter out = action.response.getWriter() ;
+            out.println("<html>") ;
+            out.println("<head>") ;
+            out.println("</head>") ;
+            out.println("<body>") ;
+            out.println("<h1>Success</h1>");
+            if ( message != null )
+            {
+                out.println("<p>") ;
+                out.println(message) ;
+                out.println("</p>") ;
+            }
+            out.println("</body>") ;
+            out.println("</html>") ;
+            out.flush() ;
+        } catch (IOException ex) { IO.exception(ex) ; }
+    }
+    
+    public static void backup(DatasetGraph dsg, String backupfile)
+    {
+        try
+        {
+            OutputStream out = new FileOutputStream(backupfile) ;
+            out = new BufferedOutputStream(out) ;
+            NQuadsWriter.write(out, dsg) ;
+            out.close() ;
+        } 
+        catch (FileNotFoundException e)
+        {
+            Log.warn(ActionBackup.class, "File not found: "+backupfile) ;
+            throw new FusekiException("File not found: "+backupfile) ;
+        } 
+        catch (IOException e)
+        { IO.exception(e) ; }
+
+        // LOG
+
+    }
+}

Modified: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionDataset.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionDataset.java?rev=1230584&r1=1230583&r2=1230584&view=diff
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionDataset.java (original)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ActionDataset.java Thu Jan 12 15:16:42 2012
@@ -80,7 +80,7 @@ public class ActionDataset extends HttpS
             out.println("<p><a href=\"info\">Next</a></p>") ;
         }
         
-//        Cookie cookie = new Cookie("org.openjena.fuseki.session", dataset) ;
+//        Cookie cookie = new Cookie("org.apache.jena.fuseki.session", dataset) ;
 //        // 24 hours.
 //        cookie.setMaxAge(24*60*60) ;
         

Copied: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ServerServlet.java (from r1230447, incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServerServlet.java)
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ServerServlet.java?p2=incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ServerServlet.java&p1=incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServerServlet.java&r1=1230447&r2=1230584&rev=1230584&view=diff
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServerServlet.java (original)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/mgt/ServerServlet.java Thu Jan 12 15:16:42 2012
@@ -20,7 +20,7 @@
  */
 
 // Could be neater - much, much neater!
-package org.apache.jena.fuseki.servlets;
+package org.apache.jena.fuseki.mgt;
 
 import java.io.IOException ;
 import java.io.PrintWriter ;

Modified: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/server/SPARQLServer.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/server/SPARQLServer.java?rev=1230584&r1=1230583&r2=1230584&view=diff
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/server/SPARQLServer.java (original)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/server/SPARQLServer.java Thu Jan 12 15:16:42 2012
@@ -28,7 +28,9 @@ import javax.servlet.http.HttpServlet ;
 
 import org.apache.jena.fuseki.Fuseki ;
 import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.fuseki.mgt.ActionBackup ;
 import org.apache.jena.fuseki.mgt.ActionDataset ;
+import org.apache.jena.fuseki.mgt.ServerServlet ;
 import org.apache.jena.fuseki.servlets.* ;
 import org.apache.jena.fuseki.validation.DataValidator ;
 import org.apache.jena.fuseki.validation.IRIValidator ;
@@ -138,6 +140,8 @@ public class SPARQLServer
         String validationRoot = "/validate" ;
         String sparqlProcessor = "/sparql" ;
         
+        // Should all services be /_/.... or some such?
+        
         if ( installManager || installServices)
         {
             server.setHandler(context);
@@ -156,9 +160,9 @@ public class SPARQLServer
             HttpServlet datasetChooser = new ActionDataset() ;
             addServlet(context, datasetChooser, "/dataset") ;
             
-            // Development : server control panel.
-            addServlet(context, new ServerServlet(), "/server") ;
-            
+//            // Development : server control panel.
+//            addServlet(context, new ServerServlet(), "/server") ;
+//            addServlet(context, new ActionBackup(), "/backup") ;
         }
         
         if ( installServices )

Modified: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java?rev=1230584&r1=1230583&r2=1230584&view=diff
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java (original)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/HttpAction.java Thu Jan 12 15:16:42 2012
@@ -19,9 +19,6 @@
 package org.apache.jena.fuseki.servlets;
 
 
-import java.util.HashMap ;
-import java.util.Map ;
-
 import javax.servlet.http.HttpServletRequest ;
 import javax.servlet.http.HttpServletResponse ;
 
@@ -34,32 +31,33 @@ import com.hp.hpl.jena.sparql.core.Datas
 import com.hp.hpl.jena.sparql.core.Transactional ;
 import com.hp.hpl.jena.tdb.migrate.DatasetGraphWithLock ;
 
-class HttpAction
+public class HttpAction
 {
-    final long id ;
+    public final long id ;
     private final DatasetGraph dsg ;
     private final Transactional transactional ;
     private DatasetGraph activeDSG ;
-    final Lock lock ;
-    final HttpServletRequest request;
-    final HttpServletResponse response ;
-    final boolean verbose ;
-    
-    // ---- Concurrency checking.
-    private static Map<Lock, ConcurrencyPolicyMRSW> lockCounters = new HashMap<Lock, ConcurrencyPolicyMRSW>() ;
-    private static ConcurrencyPolicyMRSW getConcurrencyPolicy(Lock lock)
-    {
-        synchronized(lockCounters)
-        {
-            ConcurrencyPolicyMRSW x = lockCounters.get(lock) ;
-            if ( x == null )
-            {
-                x = new ConcurrencyPolicyMRSW() ;
-                lockCounters.put(lock, x) ;
-            }
-            return x ;
-        }
-    }
+    
+    public final Lock lock ;
+    public final HttpServletRequest request;
+    public final HttpServletResponse response ;
+    public final boolean verbose ;
+    
+//    // ---- Concurrency checking.
+//    private static Map<Lock, ConcurrencyPolicyMRSW> lockCounters = new HashMap<Lock, ConcurrencyPolicyMRSW>() ;
+//    private static ConcurrencyPolicyMRSW getConcurrencyPolicy(Lock lock)
+//    {
+//        synchronized(lockCounters)
+//        {
+//            ConcurrencyPolicyMRSW x = lockCounters.get(lock) ;
+//            if ( x == null )
+//            {
+//                x = new ConcurrencyPolicyMRSW() ;
+//                lockCounters.put(lock, x) ;
+//            }
+//            return x ;
+//        }
+//    }
 
     public HttpAction(long id, DatasetGraph dsg, HttpServletRequest request, HttpServletResponse response, boolean verbose)
     {

Modified: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java?rev=1230584&r1=1230583&r2=1230584&view=diff
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java (original)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/SPARQL_ServletBase.java Thu Jan 12 15:16:42 2012
@@ -21,33 +21,25 @@ package org.apache.jena.fuseki.servlets;
 import static java.lang.String.format ;
 
 import java.io.IOException ;
-import java.io.PrintWriter ;
 import java.util.Enumeration ;
 import java.util.Map ;
-import java.util.concurrent.atomic.AtomicLong ;
 
 import javax.servlet.ServletException ;
-import javax.servlet.http.HttpServlet ;
 import javax.servlet.http.HttpServletRequest ;
 import javax.servlet.http.HttpServletResponse ;
 
-import org.apache.jena.fuseki.Fuseki ;
 import org.apache.jena.fuseki.HttpNames ;
 import org.apache.jena.fuseki.http.HttpSC ;
 import org.apache.jena.fuseki.server.DatasetRef ;
 import org.apache.jena.fuseki.server.DatasetRegistry ;
-import org.slf4j.Logger ;
 
 import com.hp.hpl.jena.query.ARQ ;
 import com.hp.hpl.jena.query.QueryCancelledException ;
 import com.hp.hpl.jena.sparql.core.DatasetGraph ;
 
-public abstract class SPARQL_ServletBase extends HttpServlet
+public abstract class SPARQL_ServletBase extends ServletBase
 {
-    protected static final Logger log = Fuseki.requestLog ;
-    protected static AtomicLong requestIdAlloc = new AtomicLong(0) ;
     private final PlainRequestFlag queryStringHandling ;
-    protected final boolean verbose_debug ;
 
     // Flag for whether a request (no query string) is handled as a regular operation or
     // routed to special handler.
@@ -55,8 +47,8 @@ public abstract class SPARQL_ServletBase
     
     protected SPARQL_ServletBase(PlainRequestFlag noQueryStringIsOK, boolean verbose_debug)
     {
+        super(verbose_debug) ;
         this.queryStringHandling = noQueryStringIsOK ;
-        this.verbose_debug = verbose_debug ;
     }
     
     // Common framework for handling HTTP requests
@@ -152,7 +144,6 @@ public abstract class SPARQL_ServletBase
             }
         }
     }
-
     
     private void printResponse(long id, HttpServletResponseTracker response)
     {
@@ -205,135 +196,4 @@ public abstract class SPARQL_ServletBase
      *  Or: (2) return true for continue.
      */
     protected abstract boolean requestNoQueryString(HttpServletRequest request, HttpServletResponse response) ;
-    
-    protected static String wholeRequestURL(HttpServletRequest request)
-    {
-        StringBuffer sb = request.getRequestURL() ;
-        String queryString = request.getQueryString() ;
-        if ( queryString != null )
-        {
-            sb.append("?") ;
-            sb.append(queryString) ;
-        }
-        return sb.toString() ;
-    }
-    
-    protected static void successNoContent(HttpAction action)
-    {
-        success(action, HttpSC.NO_CONTENT_204);
-    }
-    
-    protected static void success(HttpAction action)
-    {
-        success(action, HttpSC.OK_200);
-    }
-
-    protected static void successCreated(HttpAction action)
-    {
-        success(action, HttpSC.CREATED_201);
-    }
-    
-    // When 404 is no big deal e.g. HEAD
-    protected static void successNotFound(HttpAction action) 
-    {
-        success(action, HttpSC.NOT_FOUND_404) ;
-    }
-
-    //
-    protected static void success(HttpAction action, int httpStatusCode)
-    {
-        action.response.setStatus(httpStatusCode);
-    }
-    
-    protected static void successPage(HttpAction action, String message)
-    {
-        try {
-            action.response.setContentType("text/html");
-            action.response.setStatus(HttpSC.OK_200);
-            PrintWriter out = action.response.getWriter() ;
-            out.println("<html>") ;
-            out.println("<head>") ;
-            out.println("</head>") ;
-            out.println("<body>") ;
-            out.println("<h1>Success</h1>");
-            if ( message != null )
-            {
-                out.println("<p>") ;
-                out.println(message) ;
-                out.println("</p>") ;
-            }
-            out.println("</body>") ;
-            out.println("</html>") ;
-            out.flush() ;
-        } catch (IOException ex) { errorOccurred(ex) ; }
-    }
-
-    protected static void warning(String string)
-    {
-        log.warn(string) ;
-    }
-    
-    protected static void warning(String string, Throwable thorwable)
-    {
-        log.warn(string, thorwable) ;
-    }
-    
-    protected static void errorBadRequest(String string)
-    {
-        error(HttpSC.BAD_REQUEST_400, string) ;
-    }
-
-    protected static void errorNotFound(String string)
-    {
-        error(HttpSC.NOT_FOUND_404, string) ;
-    }
-
-    protected static void errorNotImplemented(String msg)
-    {
-        error(HttpSC.NOT_IMPLEMENTED_501, msg) ;
-    }
-    
-    protected static void errorMethodNotAllowed(String method)
-    {
-        error(HttpSC.METHOD_NOT_ALLOWED_405, "HTTP method not allowed: "+method) ;
-    }
-
-    protected static void error(int statusCode)
-    {
-        throw new ActionErrorException(null, null, statusCode) ;
-    }
-    
-
-    protected static void error(int statusCode, String string)
-    {
-        throw new ActionErrorException(null, string, statusCode) ;
-    }
-    
-    protected static void errorOccurred(String message)
-    {
-        errorOccurred(message, null) ;
-    }
-
-    protected static void errorOccurred(Throwable ex)
-    {
-        errorOccurred(null, ex) ;
-    }
-
-    protected static void errorOccurred(String message, Throwable ex)
-    {
-        throw new ActionErrorException(ex, message, HttpSC.INTERNAL_SERVER_ERROR_500) ;
-    }
-    
-    protected static String formatForLog(String string)
-    {
-        string = string.replace('\n', ' ') ;
-        string = string.replace('\r', ' ') ;
-        return string ; 
-    }
-    
-   public static void setCommonHeaders(HttpServletResponse httpResponse)
-    {
-        httpResponse.setHeader(HttpNames.hAccessControlAllowOrigin, "*") ;
-        httpResponse.setHeader(HttpNames.hServer, Fuseki.serverHttpName) ;
-    }
 }

Added: incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServletBase.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServletBase.java?rev=1230584&view=auto
==============================================================================
--- incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServletBase.java (added)
+++ incubator/jena/Jena2/Fuseki/trunk/src/main/java/org/apache/jena/fuseki/servlets/ServletBase.java Thu Jan 12 15:16:42 2012
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.servlets;
+
+import java.io.IOException ;
+import java.io.PrintWriter ;
+import java.util.concurrent.atomic.AtomicLong ;
+
+import javax.servlet.http.HttpServlet ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.HttpNames ;
+import org.apache.jena.fuseki.http.HttpSC ;
+import org.slf4j.Logger ;
+
+public abstract class ServletBase extends HttpServlet
+{
+    protected static final Logger log = Fuseki.requestLog ;
+    protected static AtomicLong requestIdAlloc = new AtomicLong(0) ;
+    protected final boolean verbose_debug ;
+
+    protected ServletBase(boolean verbose_debug)
+    {
+        this.verbose_debug = verbose_debug ;
+    }
+    
+    private void responseSendError(HttpServletResponse response, int statusCode, String message)
+    {
+        try { response.sendError(statusCode, message) ; }
+        catch (IOException ex) { errorOccurred(ex) ; }
+    }
+    
+    private void responseSendError(HttpServletResponse response, int statusCode)
+    {
+        try { response.sendError(statusCode) ; }
+        catch (IOException ex) { errorOccurred(ex) ; }
+    }
+
+    protected static String wholeRequestURL(HttpServletRequest request)
+    {
+        StringBuffer sb = request.getRequestURL() ;
+        String queryString = request.getQueryString() ;
+        if ( queryString != null )
+        {
+            sb.append("?") ;
+            sb.append(queryString) ;
+        }
+        return sb.toString() ;
+    }
+    
+    protected static void successNoContent(HttpAction action)
+    {
+        success(action, HttpSC.NO_CONTENT_204);
+    }
+    
+    protected static void success(HttpAction action)
+    {
+        success(action, HttpSC.OK_200);
+    }
+
+    protected static void successCreated(HttpAction action)
+    {
+        success(action, HttpSC.CREATED_201);
+    }
+    
+    // When 404 is no big deal e.g. HEAD
+    protected static void successNotFound(HttpAction action) 
+    {
+        success(action, HttpSC.NOT_FOUND_404) ;
+    }
+
+    //
+    protected static void success(HttpAction action, int httpStatusCode)
+    {
+        action.response.setStatus(httpStatusCode);
+    }
+    
+    protected static void successPage(HttpAction action, String message)
+    {
+        try {
+            action.response.setContentType("text/html");
+            action.response.setStatus(HttpSC.OK_200);
+            PrintWriter out = action.response.getWriter() ;
+            out.println("<html>") ;
+            out.println("<head>") ;
+            out.println("</head>") ;
+            out.println("<body>") ;
+            out.println("<h1>Success</h1>");
+            if ( message != null )
+            {
+                out.println("<p>") ;
+                out.println(message) ;
+                out.println("</p>") ;
+            }
+            out.println("</body>") ;
+            out.println("</html>") ;
+            out.flush() ;
+        } catch (IOException ex) { errorOccurred(ex) ; }
+    }
+
+    protected static void warning(String string)
+    {
+        log.warn(string) ;
+    }
+    
+    protected static void warning(String string, Throwable thorwable)
+    {
+        log.warn(string, thorwable) ;
+    }
+    
+    protected static void errorBadRequest(String string)
+    {
+        error(HttpSC.BAD_REQUEST_400, string) ;
+    }
+
+    protected static void errorNotFound(String string)
+    {
+        error(HttpSC.NOT_FOUND_404, string) ;
+    }
+
+    protected static void errorNotImplemented(String msg)
+    {
+        error(HttpSC.NOT_IMPLEMENTED_501, msg) ;
+    }
+    
+    protected static void errorMethodNotAllowed(String method)
+    {
+        error(HttpSC.METHOD_NOT_ALLOWED_405, "HTTP method not allowed: "+method) ;
+    }
+
+    protected static void error(int statusCode)
+    {
+        throw new ActionErrorException(null, null, statusCode) ;
+    }
+    
+
+    protected static void error(int statusCode, String string)
+    {
+        throw new ActionErrorException(null, string, statusCode) ;
+    }
+    
+    protected static void errorOccurred(String message)
+    {
+        errorOccurred(message, null) ;
+    }
+
+    protected static void errorOccurred(Throwable ex)
+    {
+        errorOccurred(null, ex) ;
+    }
+
+    protected static void errorOccurred(String message, Throwable ex)
+    {
+        throw new ActionErrorException(ex, message, HttpSC.INTERNAL_SERVER_ERROR_500) ;
+    }
+    
+    protected static String formatForLog(String string)
+    {
+        string = string.replace('\n', ' ') ;
+        string = string.replace('\r', ' ') ;
+        return string ; 
+    }
+    
+   public static void setCommonHeaders(HttpServletResponse httpResponse)
+    {
+        httpResponse.setHeader(HttpNames.hAccessControlAllowOrigin, "*") ;
+        httpResponse.setHeader(HttpNames.hServer, Fuseki.serverHttpName) ;
+    }
+}