Author: bdelacretaz
Date: Mon Jul 26 16:31:49 2010
New Revision: 979347

URL: http://svn.apache.org/viewvc?rev=979347&view=rev
Log:
SLING-505 - servlet-based rendering of job and stream nodes, meant to be 
overridden with custom scripts.

Added:
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
   (with props)
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/BackgroundTestServlet.java
      - copied, changed from r979260, 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
   (with props)
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobStreamServlet.java
      - copied, changed from r979209, 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/OutputReplayServlet.java
Removed:
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/OutputReplayServlet.java
Modified:
    sling/trunk/contrib/extensions/bgservlets/pom.xml
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/nodestream/NodeOutputStream.java
    
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java

Modified: sling/trunk/contrib/extensions/bgservlets/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/pom.xml?rev=979347&r1=979346&r2=979347&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/pom.xml (original)
+++ sling/trunk/contrib/extensions/bgservlets/pom.xml Mon Jul 26 16:31:49 2010
@@ -104,6 +104,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.json</artifactId>
+      <version>2.0.4-incubator</version>
+    </dependency>
+    <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
     </dependency>

Added: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java?rev=979347&view=auto
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
 (added)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
 Mon Jul 26 16:31:49 2010
@@ -0,0 +1,27 @@
+/*
+ * 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.sling.bgservlets;
+
+public class BackgroundServletConstants {
+    /** Resource type for the Job node */
+    public static final String JOB_RESOURCE_TYPE = "sling/bg/job";
+    
+    /** Resource type for the stream node */
+    public static final String STREAM_RESOURCE_TYPE = "sling/bg/stream";
+}

Propchange: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/BackgroundServletConstants.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java?rev=979347&r1=979346&r2=979347&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
 (original)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
 Mon Jul 26 16:31:49 2010
@@ -107,9 +107,16 @@ public class BackgroundServletStarterFil
                 }
                 executionEngine.queueForExecution(job);
 
-                // TODO not really an error, should send a nicer message
-                response.sendError(HttpServletResponse.SC_ACCEPTED,
-                        "Running request in the background using " + job);
+                // Redirect to the job's status page, using same extension
+                // as this request
+                String ext = slingRequest.getRequestPathInfo().getExtension();
+                if(ext == null) {
+                    ext = "";
+                } else if(ext.length() > 0) {
+                    ext = "." + ext;
+                }
+                final String path = request.getContextPath() + job.getPath() + 
ext;
+                response.sendRedirect(path);
             } catch (org.apache.sling.api.resource.LoginException e) {
                 throw new ServletException("LoginException in doFilter", e);
             }

Modified: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/nodestream/NodeOutputStream.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/nodestream/NodeOutputStream.java?rev=979347&r1=979346&r2=979347&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/nodestream/NodeOutputStream.java
 (original)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/nodestream/NodeOutputStream.java
 Mon Jul 26 16:31:49 2010
@@ -48,9 +48,6 @@ public class NodeOutputStream extends Ou
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    /** Prefix for Property names used to store our streams */
-    public static final String STREAM_PROPERTY_NAME_PREFIX = "_NODE_STREAM_";
-    
     /** Node type for our stream nodes */
     public static final String STREAM_NODE_TYPE = "nt:unstructured";
     

Copied: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/BackgroundTestServlet.java
 (from r979260, 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java)
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/BackgroundTestServlet.java?p2=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/BackgroundTestServlet.java&p1=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java&r1=979260&r2=979347&rev=979347&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
 (original)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/BackgroundTestServlet.java
 Mon Jul 26 16:31:49 2010
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.bgservlets.impl;
+package org.apache.sling.bgservlets.impl.servlets;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -60,10 +60,10 @@ public class BackgroundTestServlet exten
         try {
             for (int i = 1; i <= cycles; i++) {
                 if (i % flushEvery == 0) {
-                    w.println("Flushing output");
+                    w.println("Flushing output<br/>");
                     w.flush();
                 }
-                w.printf("Cycle %d of %d\n", i, cycles);
+                w.printf("Cycle %d of %d\n<br/>", i, cycles);
                 try {
                     Thread.sleep(interval);
                 } catch (InterruptedException iex) {

Added: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java?rev=979347&view=auto
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
 (added)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
 Mon Jul 26 16:31:49 2010
@@ -0,0 +1,116 @@
+/*
+ * 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.sling.bgservlets.impl.servlets;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.bgservlets.BackgroundServletConstants;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.io.JSONWriter;
+
+/** Default rendering of a job node in various formats,
+ *  meant to be displayed when the job is started.
+ */
+...@component
+...@service
+...@property(name = "sling.servlet.resourceTypes", value = 
BackgroundServletConstants.JOB_RESOURCE_TYPE)
+...@suppresswarnings("serial")
+public class JobInfoServlet extends SlingSafeMethodsServlet {
+
+    public static final String DEFAULT_ENCODING = "UTF-8";
+    public static final String DEFAULT_EXT = "txt";
+    
+    private static final Map<String, Renderer> renderers;
+    static {
+        renderers = new HashMap<String, Renderer>();
+        renderers.put("txt", new TextRenderer());
+        renderers.put("html", new HtmlRenderer());
+        renderers.put("json", new JsonRenderer());
+    }
+    
+    static interface Renderer {
+        void render(PrintWriter pw, String streamPath, String streamResource) 
throws IOException;
+    }
+    
+    private static class TextRenderer implements Renderer {
+        public void render(PrintWriter pw, String streamPath, String 
streamResource) {
+            pw.println("Background execution scheduled, job output available 
at ");
+            pw.println(streamPath);
+        }
+    }
+    
+    private static class HtmlRenderer implements Renderer {
+        public void render(PrintWriter pw, String streamPath, String 
streamResource) {
+            pw.println("<html><head><title>Background job</title>");
+            pw.println("<link rel='stream' href='" + streamPath + "'/>");
+            pw.println("</head><body>");
+            pw.println("<h1>Background job scheduled</h1>");
+            pw.println("Job output available at");
+            pw.println("<a href='" + streamPath + "'>" + streamResource + 
"</a>.");
+            pw.println("</body>");
+        }
+    }
+    
+    private static class JsonRenderer implements Renderer {
+        public void render(PrintWriter pw, String streamPath, String 
streamResource) throws IOException {
+            JSONWriter w = new JSONWriter(pw);
+            try {
+                w.object();
+                w.key("info");
+                w.value("Background job scheduled");
+                w.key("jobStreamPath");
+                w.value(streamPath);
+                w.endObject();
+            } catch (JSONException e) {
+                throw new IOException("JSONException in " + 
getClass().getSimpleName(), e);
+            }
+        }
+    }
+    
+    @Override
+    protected void doGet(SlingHttpServletRequest request,
+            SlingHttpServletResponse response) throws ServletException,
+            IOException {
+        final String streamResource = request.getResource().getPath() + 
"/stream." + request.getRequestPathInfo().getExtension(); 
+        final String streamPath = request.getContextPath() + streamResource;
+        final String ext = request.getRequestPathInfo().getExtension();
+        Renderer r = renderers.get(ext);
+        if(r == null) {
+            r = renderers.get(DEFAULT_EXT);
+        }
+        if(r == null) {
+            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No 
JobRenderer available for extension '" + ext + "'");
+        }
+        response.setContentType(request.getResponseContentType());
+        response.setCharacterEncoding(DEFAULT_ENCODING);
+        r.render(response.getWriter(), streamPath, streamResource);
+    }
+}

Propchange: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobStreamServlet.java
 (from r979209, 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/OutputReplayServlet.java)
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobStreamServlet.java?p2=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobStreamServlet.java&p1=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/OutputReplayServlet.java&r1=979209&r2=979347&rev=979347&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/OutputReplayServlet.java
 (original)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobStreamServlet.java
 Mon Jul 26 16:31:49 2010
@@ -16,38 +16,36 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.bgservlets.impl;
+package org.apache.sling.bgservlets.impl.servlets;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
 import javax.jcr.Node;
+import javax.jcr.RepositoryException;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.bgservlets.BackgroundServletConstants;
 import org.apache.sling.bgservlets.JobData;
 import org.apache.sling.bgservlets.JobStorage;
 
-/** Servlet that replays the output of servlets executed in
- *  the background.
+/** Default rendering of the job's stream node: replays the
+ *  stored stream.    
  */
 @Component
 @Service
 @SuppressWarnings("serial")
-...@properties ( {
-    @Property(name="sling.servlet.resourceTypes", 
value="sling/servlet/default"),
-    @Property(name="sling.servlet.extensions", value="bgreplay")
-})
-public class OutputReplayServlet extends SlingSafeMethodsServlet {
+...@property(name = "sling.servlet.resourceTypes", value = 
BackgroundServletConstants.STREAM_RESOURCE_TYPE)
+public class JobStreamServlet extends SlingSafeMethodsServlet {
 
     @Reference
     private JobStorage jobStorage;
@@ -60,22 +58,27 @@ public class OutputReplayServlet extends
             response.sendError(HttpServletResponse.SC_NOT_FOUND, 
                     "Resource does not adapt to a Node: " + 
request.getResource().getPath());
         }
-        
-        // TODO content-type, length etc.
-        final JobData d = jobStorage.getJobData(n); 
-        final InputStream is = d.getInputStream();
+
+        // The stream is a child of the job node
         try {
-            final OutputStream os = response.getOutputStream();
-            final byte [] buffer = new byte[32768];
-            int count = 0;
-            while((count = is.read(buffer, 0, buffer.length)) > 0) {
-                os.write(buffer, 0, count);
-            }
-            os.flush();
-        } finally {
-            if(is != null) {
-                is.close();
+            final JobData d = jobStorage.getJobData(n.getParent()); 
+            final InputStream is = d.getInputStream();
+            try {
+                response.setContentType(request.getResponseContentType());
+                final OutputStream os = response.getOutputStream();
+                final byte [] buffer = new byte[32768];
+                int count = 0;
+                while((count = is.read(buffer, 0, buffer.length)) > 0) {
+                    os.write(buffer, 0, count);
+                }
+                os.flush();
+            } finally {
+                if(is != null) {
+                    is.close();
+                }
             }
+        } catch(RepositoryException re) {
+            throw new ServletException("RepositoryException in doGet()", re);
         }
     }
 }

Modified: 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java?rev=979347&r1=979346&r2=979347&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java
 (original)
+++ 
sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java
 Mon Jul 26 16:31:49 2010
@@ -24,6 +24,8 @@ import java.io.OutputStream;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.bgservlets.BackgroundServletConstants;
 import org.apache.sling.bgservlets.JobData;
 import org.apache.sling.bgservlets.impl.nodestream.NodeInputStream;
 import org.apache.sling.bgservlets.impl.nodestream.NodeOutputStream;
@@ -33,12 +35,14 @@ class JobDataImpl implements JobData {
        private final Node node;
        private final String path;
        
-       public static final String STREAM_PATH = "outputStream";
+       public static final String STREAM_PATH = "stream";
        
+    public static final String RT_PROP = SlingConstants.NAMESPACE_PREFIX + ":" 
+ SlingConstants.PROPERTY_RESOURCE_TYPE;
+    
        /** Build a JobDataImpl on supplied node, which must exists */
        JobDataImpl(Node n) throws RepositoryException {
                node = n;
-               path = n.getPath();
+               path = node.getPath();
        }
        
        public InputStream getInputStream() {
@@ -58,7 +62,9 @@ class JobDataImpl implements JobData {
                 throw new IllegalArgumentException("Stream node already 
exists: " 
                         + node.getPath() + "/" + STREAM_PATH);
             }
+            node.setProperty(RT_PROP, 
BackgroundServletConstants.JOB_RESOURCE_TYPE);
             final Node stream = node.addNode(STREAM_PATH);
+            stream.setProperty(RT_PROP, 
BackgroundServletConstants.STREAM_RESOURCE_TYPE);
             node.save();
             return new NodeOutputStream(stream);
         } catch(Exception e) {


Reply via email to