in velocity-engine-core/src/main/java/org/apache/velocity/Template.java [280:435]
public void merge( Context context, Writer writer, List<String> macroLibraries)
throws ResourceNotFoundException, ParseErrorException, MethodInvocationException
{
try
{
/*
* we shouldn't have to do this, as if there is an error condition,
* the application code should never get a reference to the
* Template
*/
if (errorCondition != null)
{
throw errorCondition;
}
if (data != null)
{
/*
* create an InternalContextAdapter to carry the user Context down
* into the rendering engine. Set the template name and render()
*/
InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
/*
* Set the macro libraries
*/
List<Template> libTemplates = new ArrayList<>();
ica.setMacroLibraries(libTemplates);
if (macroLibraries != null)
{
for (String macroLibrary : macroLibraries)
{
/*
* Build the macro library
*/
try
{
Template t = rsvc.getTemplate(macroLibrary);
libTemplates.add(t);
}
catch (ResourceNotFoundException re)
{
/*
* the macro lib wasn't found. Note it and throw
*/
log.error("cannot find template {}", macroLibrary);
throw re;
}
catch (ParseErrorException pe)
{
/*
* the macro lib was found, but didn't parse - syntax error
* note it and throw
*/
rsvc.getLog("parser").error("syntax error in template {}: {}",
macroLibrary, pe.getMessage(), pe);
throw pe;
}
catch (Exception e)
{
throw new RuntimeException("parse failed in template " +
macroLibrary + ".", e);
}
}
}
if (provideScope)
{
ica.put(scopeName, new Scope(this, ica.get(scopeName)));
}
try
{
ica.pushCurrentTemplateName(name);
ica.setCurrentResource(this);
((SimpleNode) data).render(ica, writer);
}
catch (StopCommand stop)
{
if (!stop.isFor(this))
{
throw stop;
}
else
{
Logger renderingLog = rsvc.getLog("rendering");
renderingLog.debug(stop.getMessage());
}
}
catch (IOException e)
{
throw new VelocityException("IO Error rendering template '" + name + "'", e, rsvc.getLogContext().getStackTrace());
}
finally
{
/*
* lets make sure that we always clean up the context
*/
ica.popCurrentTemplateName();
ica.setCurrentResource(null);
if (provideScope)
{
Object obj = ica.get(scopeName);
if (obj instanceof Scope)
{
Scope scope = (Scope) obj;
if (scope.getParent() != null)
{
ica.put(scopeName, scope.getParent());
}
else if (scope.getReplaced() != null)
{
ica.put(scopeName, scope.getReplaced());
}
else
{
ica.remove(scopeName);
}
}
}
}
}
else
{
/*
* this shouldn't happen either, but just in case.
*/
String msg = "Template merging failed. The document is null, " +
"most likely due to a parsing error.";
throw new RuntimeException(msg);
}
}
catch (VelocityException ve)
{
/* it's a good place to display the VTL stack trace if we have one */
String[] vtlStacktrace = ve.getVtlStackTrace();
if (vtlStacktrace != null)
{
Logger renderingLog = rsvc.getLog("rendering");
renderingLog.error(ve.getMessage());
renderingLog.error("VTL stacktrace:");
for (String level : vtlStacktrace)
{
renderingLog.error(level);
}
}
throw ve;
}
}