You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Justin Edelson <ju...@gmail.com> on 2010/07/13 15:11:20 UTC

Re: svn commit: r963686 - in /sling/trunk/contrib/extensions/bgservlets: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/bgservlets/ src/main/java/org/apache/sling...

This looks pretty cool. I like the idea of using the Servlet interface
instead of Callable/Runnable.

I have two comments:

1) The request/response pair passed to the servlet should be entirely
synthetic. This is true in general AFAIK[1]; in Sling it is especially
true because request.getResourceResolver() will return a closed resource
resolver.

2) Even with synthetic request/response objects, I suspect that not all
servlets are going to work in the background (or s/going to/should/).
Thus, what about using a marker interface on the servlet to declare that
it should be run in the background. Or... to declare that it can be run
in the background.

Justin

[1] that is, the ServletRequest and ServletResponse objects are not
meant to be used outside of the request thread owned by the servlet
container.

On 7/13/10 7:58 AM, bdelacretaz@apache.org wrote:
> Author: bdelacretaz
> Date: Tue Jul 13 11:58:51 2010
> New Revision: 963686
> 
> URL: http://svn.apache.org/viewvc?rev=963686&view=rev
> Log:
> SLING-550 - first shot at background servlets engine, works for some simple cases, no job control yet
> 
> Added:
>     sling/trunk/contrib/extensions/bgservlets/   (with props)
>     sling/trunk/contrib/extensions/bgservlets/pom.xml   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/
>     sling/trunk/contrib/extensions/bgservlets/src/main/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java   (with props)
>     sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java   (with props)
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/
> ------------------------------------------------------------------------------
> --- svn:ignore (added)
> +++ svn:ignore Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,13 @@
> +target
> +bin
> +derby.log
> +*.iml
> +*.ipr
> +*.iws
> +.settings
> +.project
> +.classpath
> +.externalToolBuilders
> +maven-eclipse.xml
> +
> +
> 
> Added: sling/trunk/contrib/extensions/bgservlets/pom.xml
> URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/pom.xml?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/pom.xml (added)
> +++ sling/trunk/contrib/extensions/bgservlets/pom.xml Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,94 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +  <!--
> +    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.
> +  -->
> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
> +
> +  <modelVersion>4.0.0</modelVersion>
> +  <parent>
> +    <groupId>org.apache.sling</groupId>
> +    <artifactId>sling</artifactId>
> +    <version>9</version>
> +    <relativePath>../../../parent/pom.xml</relativePath>
> +  </parent>
> +
> +  <artifactId>org.apache.sling.bgservlets</artifactId>
> +  <version>0.0.1-SNAPSHOT</version>
> +  <packaging>bundle</packaging>
> +
> +  <name>Apache Sling Background Servlets Engine</name>
> +  <description> 
> +    Allows scripts and servlets to run as background tasks
> +    which can be suspended, resumed, stopped and restarted.
> +  </description>
> +
> +  <scm>
> +    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/bgservlets</connection>
> +    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/bgservlets</developerConnection>
> +    <url>http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/bgservlets</url>
> +  </scm>
> +
> +  <build>
> +    <plugins>
> +      <plugin>
> +        <groupId>org.apache.felix</groupId>
> +        <artifactId>maven-scr-plugin</artifactId>
> +      </plugin>
> +      <plugin>
> +        <groupId>org.apache.felix</groupId>
> +        <artifactId>maven-bundle-plugin</artifactId>
> +        <extensions>true</extensions>
> +        <configuration>
> +          <instructions>
> +            <Export-Package>org.apache.sling.bgservlets</Export-Package>
> +            <Private-Package>org.apache.sling.bgservlets.impl.*</Private-Package>
> +          </instructions>
> +        </configuration>
> +      </plugin>
> +    </plugins>
> +  </build>
> +
> +  <dependencies>
> +    <dependency>
> +      <groupId>org.osgi</groupId>
> +      <artifactId>org.osgi.core</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.osgi</groupId>
> +      <artifactId>org.osgi.compendium</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.apache.felix</groupId>
> +      <artifactId>org.apache.felix.scr.annotations</artifactId>
> +      <version>1.2.0</version>
> +      <scope>compile</scope>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.apache.sling</groupId>
> +      <artifactId>org.apache.sling.api</artifactId>
> +      <version>2.0.8</version>
> +      <scope>provided</scope>
> +    </dependency>
> +    <dependency>
> +      <groupId>javax.servlet</groupId>
> +      <artifactId>servlet-api</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.slf4j</groupId>
> +      <artifactId>slf4j-api</artifactId>
> +    </dependency>
> +  </dependencies>
> +</project>
> \ No newline at end of file
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/pom.xml
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java
> URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,28 @@
> +/*
> + * 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;
> +
> +/** Service that executes Runnables, will later allow
> + * 	them to be suspended, resumed, stopped and restarted.
> + */
> +public interface ExecutionEngine {
> +	
> +	/** Add a job to the execution queue */
> +	void queueForExecution(Runnable job);
> +}
> \ No newline at end of file
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/ExecutionEngine.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
> Added: 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=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,91 @@
> +/*
> + * 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;
> +
> +import java.io.IOException;
> +
> +import javax.servlet.Filter;
> +import javax.servlet.FilterChain;
> +import javax.servlet.FilterConfig;
> +import javax.servlet.ServletException;
> +import javax.servlet.ServletRequest;
> +import javax.servlet.ServletResponse;
> +import javax.servlet.http.HttpServletRequest;
> +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.bgservlets.ExecutionEngine;
> +import org.slf4j.Logger;
> +import org.slf4j.LoggerFactory;
> +
> +/** Filter that runs the current request in the background
> + * 	if specific request parameters are set.
> + *  TODO: define the position of this filter in the chain,
> + *  and how do we enforce it?
> + */
> +@Component
> +@Service
> +@Properties({
> +	@Property(name="filter.scope", value="request"),
> +	@Property(name="filter.order", intValue=java.lang.Integer.MIN_VALUE)
> +})
> +public class BackgroundServletStarterFilter implements Filter{
> +
> +	private final Logger log = LoggerFactory.getLogger(getClass());
> +	
> +	@Reference
> +	private ExecutionEngine executionEngine;
> +	
> +	/** 
> +	 * Request runs in the background if this request parameter is present 
> +	 * TODO should be configurable, and maybe use other decision methods */
> +	public static final String BG_PARAM = "sling:bg";
> +	
> +	public void doFilter(final ServletRequest sreq, final ServletResponse sresp, 
> +			final FilterChain chain) throws IOException, ServletException {
> +		if(!(sreq instanceof HttpServletRequest)) {
> +			throw new ServletException("request is not an HttpServletRequest: " + sresp.getClass().getName());
> +		}
> +		if(!(sresp instanceof HttpServletResponse)) {
> +			throw new ServletException("response is not an HttpServletResponse: " + sresp.getClass().getName());
> +		}
> +		final HttpServletRequest request = (HttpServletRequest)sreq;
> +		final HttpServletResponse response = (HttpServletResponse)sresp; 
> +		if(sreq.getParameter(BG_PARAM) != null) {
> +			final FilterChainExecutionJob job = new FilterChainExecutionJob(chain, request, response);
> +			log.debug("{} request parameter present, running request in the background using {}", BG_PARAM, job);
> +			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);
> +		} else {
> +			chain.doFilter(sreq, sresp);
> +		}
> +	}
> +
> +	public void destroy() {
> +	}
> +
> +	public void init(FilterConfig cfg) throws ServletException {
> +	}
> +}
> \ No newline at end of file
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
> Added: 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/BackgroundTestServlet.java?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,78 @@
> +/*
> + * 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;
> +
> +import java.io.IOException;
> +import java.io.PrintWriter;
> +
> +import javax.servlet.ServletException;
> +
> +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;
> +
> +/** Servlet used for interactive testing of the background
> + * 	servlets engine.
> + * 	TODO remove once we have better tests.
> + */
> +@Component
> +@Service
> +@SuppressWarnings("serial")
> +@Property(name="sling.servlet.paths", value="/system/bgservlets/test")
> +public class BackgroundTestServlet extends SlingSafeMethodsServlet {
> +
> +	@Override
> +	protected void doGet(SlingHttpServletRequest request,
> +			SlingHttpServletResponse response) throws ServletException,
> +			IOException {
> +		response.setContentType("text/plain");
> +		final PrintWriter w = response.getWriter();
> +		
> +		final int cycles = getIntParam(request, "cycles", 10);
> +		final int interval = getIntParam(request, "interval", 1);
> +		final int flushEvery = getIntParam(request, "flushEvery", 2);
> +		
> +		for(int i=1; i <= cycles; i++) {
> +			if(i % flushEvery == 0) {
> +				w.println("Flushing output");
> +				w.flush();
> +			}
> +			w.printf("Cycle %d of %d\n", i, cycles);
> +			try {
> +				Thread.sleep(interval * 1000);
> +			} catch(InterruptedException iex) {
> +				throw new ServletException("InterruptedException", iex);
> +			}
> +		}
> +		w.println("All done.");
> +		w.flush();
> +	}
> +	
> +	private int getIntParam(SlingHttpServletRequest request, String name, int defaultValue) {
> +		int result = defaultValue;
> +		final String str = request.getParameter(name);
> +		if(str != null) {
> +			result = Integer.parseInt(str);
> +		}
> +		return result;
> +	}
> +}
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
> Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java
> URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,74 @@
> +/*
> + * 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;
> +
> +import java.util.concurrent.ArrayBlockingQueue;
> +import java.util.concurrent.BlockingQueue;
> +import java.util.concurrent.Executor;
> +import java.util.concurrent.RejectedExecutionHandler;
> +import java.util.concurrent.ThreadPoolExecutor;
> +import java.util.concurrent.TimeUnit;
> +
> +import org.apache.felix.scr.annotations.Component;
> +import org.apache.felix.scr.annotations.Service;
> +import org.apache.sling.api.SlingException;
> +import org.apache.sling.bgservlets.ExecutionEngine;
> +import org.osgi.service.component.ComponentContext;
> +
> +/** Simple ExecutionEngine
> + * 	TODO should use Sling's thread pool, and check synergies
> + * 	with scheduler services */
> +@Component
> +@Service
> +public class ExecutionEngineImpl implements ExecutionEngine {
> +
> +	private Executor executor;
> +	
> +	@SuppressWarnings("serial")
> +	public static class QueueFullException extends SlingException {
> +		QueueFullException(Runnable r) {
> +			super("Execution queue is full, cannot execute " + r);
> +		}
> +	}
> +	
> +	public void activate(ComponentContext context) {
> +		// TODO configurable!
> +		final int corePoolSize = 2;
> +        int maximumPoolSize = 2;
> +        long keepAliveTime = 30;
> +        TimeUnit unit = TimeUnit.SECONDS;
> +        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(4); 
> +        RejectedExecutionHandler handler = new RejectedExecutionHandler() {
> +			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
> +				throw new QueueFullException(r);
> +			}
> +		};
> +        executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); 
> +	}
> +	
> +	public void deactivate(ComponentContext context) {
> +		// TODO how to shutdown executor?
> +		executor = null;
> +	}
> +	
> +	public void queueForExecution(Runnable job) {
> +		// TODO wrap job in our own Runnable to detect start/end etc.
> +		executor.execute(job);
> +	}
> +}
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
> Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
> URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,68 @@
> +/*
> + * 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;
> +
> +import java.io.IOException;
> +
> +import javax.servlet.FilterChain;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +
> +import org.slf4j.Logger;
> +import org.slf4j.LoggerFactory;
> +
> +/** Runnable that executes a FilterChain, using 
> + * 	a ServletResponseWrapper to capture the output.
> + */
> +class FilterChainExecutionJob implements Runnable {
> +	private final Logger log = LoggerFactory.getLogger(getClass());
> +	private final FilterChain chain;
> +	private final ServletResponseWrapper response;
> +	
> +	// TODO is it ok to keep a reference to the request until run() is called??
> +	private final HttpServletRequest request;
> +	
> +	FilterChainExecutionJob(FilterChain chain, HttpServletRequest request, HttpServletResponse hsr) throws IOException {
> +		this.chain = chain;
> +		this.request = request;
> +		response  = new ServletResponseWrapper(hsr);
> +	}
> +	
> +	public String toString() {
> +		return "Background request job: " + response;
> +	}
> +	
> +	public void run() {
> +		log.info("{} execution starts", this);
> +		try {
> +			chain.doFilter(request, response);
> +		} catch(Exception e) {
> +			// TODO report errors in the background job's output
> +			log.error("chain.doFilter failed", e);
> +		} finally {
> +			try {
> +				response.cleanup();
> +			} catch(IOException ioe) {
> +				// TODO report errors in the background job's output
> +				log.error("ServletResponseWrapper cleanup failed", ioe);
> +			}
> +		}
> +		log.info("{} execution ends", this);
> +	}
> +}
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
> Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
> URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java?rev=963686&view=auto
> ==============================================================================
> --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java (added)
> +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java Tue Jul 13 11:58:51 2010
> @@ -0,0 +1,93 @@
> +/*
> + * 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;
> +
> +import java.io.File;
> +import java.io.FileOutputStream;
> +import java.io.IOException;
> +import java.io.OutputStream;
> +import java.io.OutputStreamWriter;
> +import java.io.PrintWriter;
> +
> +import javax.servlet.ServletOutputStream;
> +import javax.servlet.http.HttpServletResponse;
> +import javax.servlet.http.HttpServletResponseWrapper;
> +
> +/** Wraps an HttpServletResponse for background processing */
> +class ServletResponseWrapper extends HttpServletResponseWrapper {
> +
> +	private final String outputPath;
> +	private final ServletOutputStream stream;
> +	private final PrintWriter writer;
> +	
> +	static class CustomOutputStream extends ServletOutputStream {
> +
> +		private final OutputStream os;
> +		
> +		CustomOutputStream(OutputStream os) {
> +			this.os = os;
> +		}
> +		
> +		@Override
> +		public void write(int b) throws IOException {
> +			os.write(b);
> +		}
> +
> +		@Override
> +		public void close() throws IOException {
> +			os.close();
> +		}
> +
> +		@Override
> +		public void flush() throws IOException {
> +			os.flush();
> +		}
> +		
> +	}
> +	
> +	ServletResponseWrapper(HttpServletResponse response) throws IOException {
> +		super(response);
> +		// TODO write output to the Sling repository. For now: just a temp file
> +		final File output = File.createTempFile(getClass().getSimpleName(), ".data");
> +		output.deleteOnExit();
> +		outputPath = output.getAbsolutePath();
> +		stream = new CustomOutputStream(new FileOutputStream(output));
> +		writer = new PrintWriter(new OutputStreamWriter(stream));
> +	}
> +	
> +	public String toString() {
> +		return getClass().getName() + ":" + outputPath;
> +	}
> +	
> +	void cleanup() throws IOException {
> +		stream.flush();
> +		stream.close();
> +	}
> +	
> +	@Override
> +	public ServletOutputStream getOutputStream() throws IOException {
> +		return stream;
> +	}
> +
> +	@Override
> +	public PrintWriter getWriter() throws IOException {
> +		return writer;
> +	}
> +
> +}
> \ No newline at end of file
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Revision Rev URL
> 
>