/* Reattore HTTP Server
Copyright (C) 2002 Michael Hope <michaelh@juju.net.nz>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: VelocityInterceptor.java,v 1.13 2003/03/05 04:31:57 michaelh Exp $
*/
package juju.reattore.server.intercept.impl;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.exception.*;
import org.apache.commons.logging.*;
import java.io.*;
import juju.reattore.protocol.http.*;
import juju.reattore.server.intercept.Interceptor;
import juju.reattore.io.impl.ByteBufferSource;
/** Interceptor that serves a Apache Velocity based template.
@tag velocity
@group Interceptor
@todo Minor: Uses ByteArrayOutputStream, which could be replaced with a Source.
@todo Doesn't configure the velocity engine.
*/
public class VelocityInterceptor
implements Interceptor {
private static Log log = LogFactory.getLog(VelocityInterceptor.class);
private VelocityEngine engine;
private String lockedPath;
/** Create a new interceptor
@todo Minor: Doesn't handle errors during init very well.
*/
public VelocityInterceptor() {
engine = createEngine();
try {
engine.init();
}
catch (Exception ex) {
log.error("While initialising", ex);
throw new RuntimeException(ex);
}
}
private static VelocityEngine createEngine() {
VelocityEngine ret = new VelocityEngine();
return ret;
}
/** Lock this interceptor to only ever return the contents of the
given path no matter what the request.
@param path The path to lock to, or null to clear.
*/
public void setLockedPath(String path) {
lockedPath = path;
}
/** Hook to allow a derrived class to add extra items to the
context.
@param ctx Main context
@param req Incoming request
@param resp Outgoing response
@return true if the request was handled and processing should
abort.
*/
protected boolean populateContext(VelocityContext ctx, HttpRequest req, HttpResponse resp) {
return false;
}
/** @see Interceptor
@todo populateContext() is a bit of a hack
*/
public boolean process(HttpRequest req, HttpResponse resp) {
VelocityContext ctx = new VelocityContext();
ctx.put("resp", resp);
ctx.put("req", req);
if (populateContext(ctx, req, resp) == true) {
/* Handled already */
return true;
}
String path = lockedPath != null ? lockedPath : req.getPath();
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(out);
try {
if (engine.mergeTemplate(path, ctx,
writer) == true) {
writer.flush();
/* All done */
resp.setBody(new ByteBufferSource(out.toByteArray()));
resp.setStatus(HttpResponse.SC_OK);
resp.setHeader(HttpConstants.CONTENT_TYPE, HttpConstants.TEXT_HTML);
return true;
}
else {
log.debug("Template could not process " + path);
resp.setStatus(HttpResponse.SC_NOT_FOUND);
return false;
}
}
catch (ResourceNotFoundException ex) {
log.debug("Error while processing " + path, ex);
resp.setStatus(HttpResponse.SC_NOT_FOUND);
return false;
}
catch (ParseErrorException ex) {
log.debug("Error while processing " + path, ex);
resp.setStatus(HttpResponse.SC_INTERNAL_SERVER_ERROR);
return false;
}
catch (MethodInvocationException ex) {
log.debug("Error while processing " + path, ex);
resp.setStatus(HttpResponse.SC_INTERNAL_SERVER_ERROR);
return false;
}
catch (Exception ex) {
log.debug("Error while processing " + path, ex);
resp.setStatus(HttpResponse.SC_INTERNAL_SERVER_ERROR);
return false;
}
}
}