package org.apache.slide.projector.engine;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.slide.projector.ConfigurationException;
import org.apache.slide.projector.Constants;
import org.apache.slide.projector.Context;
import org.apache.slide.projector.HttpContext;
import org.apache.slide.projector.Processor;
import org.apache.slide.projector.Projector;
import org.apache.slide.projector.Result;
import org.apache.slide.projector.URI;
import org.apache.slide.projector.application.ApplicationManager;
import org.apache.slide.projector.descriptor.ParameterDescriptor;
import org.apache.slide.projector.processor.SimpleProcessor;
import org.apache.slide.projector.processor.core.ExceptionRenderer;
import org.apache.slide.projector.util.StreamHelper;
import org.apache.slide.projector.value.ObjectValue;
import org.apache.slide.projector.value.StreamableValue;
import org.apache.slide.projector.value.URIValue;
import org.apache.slide.projector.value.Value;
public class ProcessServlet extends HttpServlet {
private static Logger logger = Logger.getLogger(ProcessServlet.class.getName());
public final static URIValue DEFAULT_EXCEPTION_PROCESSOR = new URIValue("exception.html");
private final static Random random = new Random(System.currentTimeMillis());
private final static String allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ApplicationManager.getInstance();
boolean sessionCreated = request.getSession(false) == null;
Context context = new HttpContext(request, response);
logger.log(Level.FINE, "Request uri=" + request.getRequestURI());
logger.log(Level.FINE, "Context path=" + request.getContextPath());
logger.log(Level.FINE, "Servlet path=" + request.getServletPath());
URI uri = new URIValue(request.getRequestURI().substring(request.getContextPath().length()+request.getServletPath().length()+1));
try {
Result result;
Processor processor;
try {
logger.log(Level.FINE, "Processing started with URI=" + uri);
Map requestParameters = request.getParameterMap();
if ( requestParameters.containsKey(Constants.PROCESS_ID_PARAMETER) ) {
context.setProcessId(requestParameters.get(Constants.PROCESS_ID_PARAMETER).toString());
} else {
StringBuffer processIdBuffer = new StringBuffer(Constants.PROCESS_ID_LENGTH);
for ( int i = 0; i < Constants.PROCESS_ID_LENGTH; i++) {
processIdBuffer.append(allowedChars.charAt(random.nextInt(allowedChars.length())));
}
context.setProcessId(processIdBuffer.toString());
}
processor = ProcessorManager.getInstance().getProcessor(uri);
Scheduler.getInstance();
Scheduler.setContext(context);
if ( sessionCreated ) {
// new session
Scheduler.getInstance().launchSessionJobs(context);
}
Scheduler.getInstance().launchRequestJobs(context);
if ( ProcessorManager.getInstance().getProcessorDescriptor(uri).isBookmark() ) {
context.setBookmark(uri);
}
ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors();
result = ProcessorManager.process(processor, new HashMap(requestParameters), context);
} catch ( Exception exception ) {
logger.log(Level.SEVERE, "Exception while processing processor with URI="+uri+"", exception);
processor = ProcessorManager.getInstance().getProcessor(DEFAULT_EXCEPTION_PROCESSOR);
Map exceptionParameters = new HashMap();
exceptionParameters.put(ExceptionRenderer.EXCEPTION, new ObjectValue(exception));
result = ProcessorManager.process(processor, exceptionParameters, context);
}
Value presentableResource = ((HttpContext)context).getPresentableResource();
if (presentableResource == null) {
// check for 'output' resource in processor result
presentableResource = (Value)result.getResultEntries().get(SimpleProcessor.OUTPUT);
}
if ( presentableResource != null ) {
if ( presentableResource instanceof StreamableValue ) {
response.setContentType(((StreamableValue)presentableResource).getContentType()+"; charset=UTF-8");
response.setContentLength(((StreamableValue)presentableResource).getContentLength());
StreamHelper.copy(((StreamableValue)presentableResource).getInputStream(), response.getOutputStream());
if (!((StreamableValue)presentableResource).isDocument()) {
logger.log(Level.FINE, "You received a fragment on top level, no complete document!");
}
}
} else {
logger.log(Level.SEVERE, "No renderable resource composed!");
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception while processing request", e);
} finally {
Scheduler.setContext(null);
}
}
public void init(ServletConfig config) {
String filename = config.getInitParameter("configuration");
try {
Projector.configure(new FileInputStream(filename));
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Invalid projector configuration. Projector not started!", e);
} catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Projector configuration file projector.xml not found. Projector not started!", e);
}
}
}