| Method from org.apache.velocity.tools.view.servlet.VelocityViewServlet Detail: |
protected Context createContext(HttpServletRequest request,
HttpServletResponse response) {
ChainedContext ctx =
new ChainedContext(velocity, request, response, getServletContext());
/* if we have a toolbox manager, get a toolbox from it */
if (toolboxManager != null)
{
ctx.setToolbox(toolboxManager.getToolbox(ctx));
}
return ctx;
}
|
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
doRequest(request, response);
}
Handles GET - calls doRequest() |
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
doRequest(request, response);
}
Handle a POST request - calls doRequest() |
protected void doRequest(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
Context context = null;
try
{
// first, get a context
context = createContext(request, response);
// set the content type
setContentType(request, response);
// get the template
Template template = handleRequest(request, response, context);
// bail if we can't find the template
if (template == null)
{
velocity.warn("VelocityViewServlet: couldn't find template to match request.");
return;
}
// merge the template and context
mergeTemplate(template, context, response);
}
catch (Exception e)
{
// log the exception
velocity.error("VelocityViewServlet: Exception processing the template: "+e);
// call the error handler to let the derived class
// do something useful with this failure.
error(request, response, e);
}
finally
{
// call cleanup routine to let a derived class do some cleanup
requestCleanup(request, response, context);
}
}
Handles with both GET and POST requests |
protected void error(HttpServletRequest request,
HttpServletResponse response,
Exception e) throws ServletException {
try
{
StringBuffer html = new StringBuffer();
html.append("< html >\n");
html.append("< head >< title >Error< /title >< /head >\n");
html.append("< body >\n");
html.append("< h2 >VelocityViewServlet : Error processing the template< /h2 >\n");
Throwable cause = e;
String why = cause.getMessage();
if (why != null && why.trim().length() > 0)
{
html.append(why);
html.append("\n< br >\n");
}
// if it's an MIE, i want the real stack trace!
if (cause instanceof MethodInvocationException)
{
// get the real cause
cause = ((MethodInvocationException)cause).getWrappedThrowable();
}
StringWriter sw = new StringWriter();
cause.printStackTrace(new PrintWriter(sw));
html.append("< pre >\n");
html.append(sw.toString());
html.append("< /pre >\n");
html.append("< /body >\n");
html.append("< /html >");
getResponseWriter(response).write(html.toString());
}
catch (Exception e2)
{
// clearly something is quite wrong.
// let's log the new exception then give up and
// throw a servlet exception that wraps the first one
velocity.error("VelocityViewServlet: Exception while printing error screen: "+e2);
throw new ServletException(e);
}
}
Invoked when there is an error thrown in any part of doRequest() processing.
Default will send a simple HTML response indicating there was a problem. |
protected String findInitParameter(ServletConfig config,
String key) {
// check the servlet config
String param = config.getInitParameter(key);
if (param == null || param.length() == 0)
{
// check the servlet context
ServletContext servletContext = config.getServletContext();
param = servletContext.getInitParameter(key);
}
return param;
}
Looks up an init parameter with the specified key in either the
ServletConfig or, failing that, in the ServletContext. |
protected Writer getResponseWriter(HttpServletResponse response) throws IOException, UnsupportedEncodingException {
Writer writer = null;
try
{
writer = response.getWriter();
}
catch (IllegalStateException e)
{
// ASSUMPTION: We already called getOutputStream(), so
// calls to getWriter() fail. Use of OutputStreamWriter
// assures our desired character set
if (this.warnOfOutputStreamDeprecation)
{
this.warnOfOutputStreamDeprecation = false;
velocity.warn("VelocityViewServlet: " +
"Use of ServletResponse's getOutputStream() " +
"method with VelocityViewServlet is " +
"deprecated -- support will be removed in " +
"an upcoming release");
}
// Assume the encoding has been set via setContentType().
String encoding = response.getCharacterEncoding();
if (encoding == null)
{
encoding = DEFAULT_OUTPUT_ENCODING;
}
writer = new OutputStreamWriter(response.getOutputStream(),
encoding);
}
return writer;
}
Procure a Writer with correct encoding which can be used
even if HttpServletResponse's getOutputStream() method
has already been called.
This is a transitional method which will be removed in a
future version of Velocity. It is not recommended that you
override this method.
|
public Template getTemplate(String name) throws Exception, ResourceNotFoundException, ParseErrorException {
return velocity.getTemplate(name);
}
Retrieves the requested template. |
public Template getTemplate(String name,
String encoding) throws Exception, ResourceNotFoundException, ParseErrorException {
return velocity.getTemplate(name, encoding);
}
Retrieves the requested template with the specified character encoding. |
protected VelocityEngine getVelocityEngine() {
return velocity;
}
Returns the underlying VelocityEngine being used. |
protected String getVelocityProperty(String key,
String alternate) {
String prop = (String)velocity.getProperty(key);
if (prop == null || prop.length() == 0)
{
return alternate;
}
return prop;
}
Simplifies process of getting a property from VelocityEngine,
because the VelocityEngine interface sucks compared to the singleton's.
Use of this method assumes that #initVelocity(ServletConfig)
has already been called. |
protected Template handleRequest(HttpServletRequest request,
HttpServletResponse response,
Context ctx) throws Exception {
// If we get here from RequestDispatcher.include(), getServletPath()
// will return the original (wrong) URI requested. The following special
// attribute holds the correct path. See section 8.3 of the Servlet
// 2.3 specification.
String path = (String)request.getAttribute("javax.servlet.include.servlet_path");
// also take into account the PathInfo stated on SRV.4.4 Request Path Elements
String info = (String)request.getAttribute("javax.servlet.include.path_info");
if (path == null)
{
path = request.getServletPath();
info = request.getPathInfo();
}
if (info != null)
{
path += info;
}
return getTemplate(path);
}
|
public void init(ServletConfig config) throws ServletException {
super.init(config);
// do whatever we have to do to init Velocity
initVelocity(config);
// init this servlet's toolbox (if any)
initToolbox(config);
// we can get these now that velocity is initialized
defaultContentType =
(String)getVelocityProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
String encoding =
(String)getVelocityProperty(RuntimeConstants.OUTPUT_ENCODING,
DEFAULT_OUTPUT_ENCODING);
// For non Latin-1 encodings, ensure that the charset is
// included in the Content-Type header.
if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))
{
int index = defaultContentType.lastIndexOf("charset");
if (index < 0)
{
// the charset specifier is not yet present in header.
// append character encoding to default content-type
defaultContentType += "; charset=" + encoding;
}
else
{
// The user may have configuration issues.
velocity.warn("VelocityViewServlet: Charset was already " +
"specified in the Content-Type property. " +
"Output encoding property will be ignored.");
}
}
velocity.info("VelocityViewServlet: Default content-type is: " +
defaultContentType);
}
Initializes servlet, toolbox and Velocity template engine.
Called by the servlet container on loading.
NOTE: If no charset is specified in the default.contentType
property (in your velocity.properties) and you have specified
an output.encoding property, then that will be used as the
charset for the default content-type of pages served by this
servlet.
|
protected void initToolbox(ServletConfig config) throws ServletException {
/* check the servlet config and context for a toolbox param */
String file = findInitParameter(config, TOOLBOX_KEY);
/* if we have a toolbox, get a manager for it */
if (file != null)
{
toolboxManager =
ServletToolboxManager.getInstance(getServletContext(), file);
}
else
{
velocity.info("VelocityViewServlet: No toolbox entry in configuration.");
}
}
Initializes the ServletToolboxManager for this servlet's
toolbox (if any). |
protected void initVelocity(ServletConfig config) throws ServletException {
velocity = new VelocityEngine();
setVelocityEngine(velocity);
// register this engine to be the default handler of log messages
// if the user points commons-logging to the LogSystemCommonsLog
LogSystemCommonsLog.setVelocityEngine(velocity);
velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
// default to servletlogger, which logs to the servlet engines log
velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
ServletLogger.class.getName());
// by default, load resources with webapp resource loader
velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp");
velocity.setProperty("webapp.resource.loader.class",
WebappLoader.class.getName());
// Try reading an overriding Velocity configuration
try
{
ExtendedProperties p = loadConfiguration(config);
velocity.setExtendedProperties(p);
}
catch(Exception e)
{
getServletContext().log("VelocityViewServlet: Unable to read Velocity configuration file: "+e);
getServletContext().log("VelocityViewServlet: Using default Velocity configuration.");
}
// now all is ready - init Velocity
try
{
velocity.init();
}
catch(Exception e)
{
getServletContext().log("VelocityViewServlet: PANIC! unable to init() - "+e);
throw new ServletException(e);
}
}
Initializes the Velocity runtime, first calling
loadConfiguration(ServletConfig) to get a
org.apache.commons.collections.ExtendedProperties
of configuration information
and then calling velocityEngine.init(). Override this
to do anything to the environment before the
initialization of the singleton takes place, or to
initialize the singleton in other ways. |
protected ExtendedProperties loadConfiguration(ServletConfig config) throws IOException {
// grab the path to the custom props file (if any)
String propsFile = findInitParameter(config, INIT_PROPS_KEY);
ExtendedProperties p = new ExtendedProperties();
if (propsFile != null)
{
p.load(getServletContext().getResourceAsStream(propsFile));
velocity.info("VelocityViewServlet: Custom Properties File: "+propsFile);
}
else
{
velocity.info("VelocityViewServlet: No custom properties found. " +
"Using default Velocity configuration.");
}
return p;
}
Loads the configuration information and returns that
information as an ExtendedProperties, which will be used to
initialize the Velocity runtime.
Currently, this method gets the initialization parameter
VelocityServlet.INIT_PROPS_KEY, which should be a file containing
the configuration information.
To configure your Servlet Spec 2.2 compliant servlet runner to pass
this to you, put the following in your WEB-INF/web.xml file
<servlet>
<servlet-name> YourServlet </servlet-name>
<servlet-class> your.package.YourServlet </servlet-class>
<init-param>
<param-name> org.apache.velocity.properties </param-name>
<param-value> velocity.properties </param-value>
</init-param>
</servlet>
Alternately, if you wish to configure an entire context in this
fashion, you may use the following:
<context-param>
<param-name> org.apache.velocity.properties </param-name>
<param-value> velocity.properties </param-value>
<description> Path to Velocity configuration </description>
</context-param>
Derived classes may do the same, or take advantage of this code to do the loading for them via :
ExtendedProperties p = super.loadConfiguration(config);
and then add or modify the configuration values from the file.
|
protected void mergeTemplate(Template template,
Context context,
HttpServletResponse response) throws Exception, IOException, MethodInvocationException, ResourceNotFoundException, UnsupportedEncodingException, ParseErrorException {
VelocityWriter vw = null;
Writer writer = getResponseWriter(response);
try
{
vw = (VelocityWriter)writerPool.get();
if (vw == null)
{
vw = new VelocityWriter(writer, 4 * 1024, true);
}
else
{
vw.recycle(writer);
}
performMerge(template, context, vw);
}
finally
{
if (vw != null)
{
try
{
// flush and put back into the pool
// don't close to allow us to play
// nicely with others.
vw.flush();
/* This hack sets the VelocityWriter's internal ref to the
* PrintWriter to null to keep memory free while
* the writer is pooled. See bug report #18951 */
vw.recycle(null);
writerPool.put(vw);
}
catch (Exception e)
{
velocity.debug("VelocityViewServlet: " +
"Trouble releasing VelocityWriter: " +
e.getMessage());
}
}
}
}
Merges the template with the context. Only override this if you really, really
really need to. (And don't call us with questions if it breaks :) |
protected void performMerge(Template template,
Context context,
Writer writer) throws Exception, MethodInvocationException, ResourceNotFoundException, ParseErrorException {
template.merge(context, writer);
}
This is here so developers may override it and gain access to the
Writer which the template will be merged into. See
VELTOOLS-7
for discussion of this. |
protected void requestCleanup(HttpServletRequest request,
HttpServletResponse response,
Context context) {
}
Cleanup routine called at the end of the request processing sequence
allows a derived class to do resource cleanup or other end of
process cycle tasks. This default implementation does nothing. |
protected void setContentType(HttpServletRequest request,
HttpServletResponse response) {
response.setContentType(defaultContentType);
}
response.setContentType(defaultContentType);
where defaultContentType is set to the value of the default.contentType
property, or "text/html" if that is not set. |
protected void setVelocityEngine(VelocityEngine ve) {
if (ve == null)
{
throw new NullPointerException("Cannot set the VelocityEngine to null");
}
this.velocity = ve;
}
Sets the underlying VelocityEngine |